用类模板设计一个队列(选用数组或链表),解决n个人围成一圈的问题

    技术2022-07-11  87

    1. 用栈(数组)实现 思想: 因为数组是一维的,头尾不相连,所以考虑使用两个整型变量记录队列的头和尾在数组中的下标(也就是pop和push的位置),通过对数组长度取余的方式从数组的头跳到尾,实现头尾相连(围成一圈)。

    文字很难描述,可以在脑海中想象一下,有点像是火车在围成一圈的轨道上跑的感觉,火车是队列,轨道是数组。比如长度为10的数组(下标0到9),pop或者push的下标从9增加到10时,通过对10取余回到下标为0的位置。

    #include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> using namespace std; template<typename T> class Queue { public: Queue(int size) { MAX_SIZE = size; tp = new T[size]; this->size = 0; this->p_pop = 0; //队列从下标0开始pop出数据,所以初始化为0 this->p_push = -1; //队列从下标0开始push数据,所以初始化为-1 } ~Queue() { delete tp; } void push(T dat) { if (this->size == MAX_SIZE) { printf("stack is overflow!\n"); return; } p_push++; p_push %= MAX_SIZE; //push入数据到数组的末尾时,通过取余跳到数组的开头,实现循环和重复利用地址 tp[p_push] = dat; size++; } T pop() { if (size == 0) { printf("stack is empty!\n"); exit(1); } T temp = tp[p_pop++]; p_pop %= MAX_SIZE; //pop出数据到数组的末尾时,通过取余跳到数组的 size--; return temp; } int getSize() { return size; } void travel() { int len = size; int p = p_pop; printf(":==================================\n"); printf("size=%d\t", size); printf("p_pop=%d, p_push=%d\n", p_pop, p_push); // while (p != p_push + 1) { //用下标判断队列为空 // printf("%d ", tp[p]); // p++; // p %= MAX_SIZE; // } while (len--) {//用队列长度判断队列为空 printf("%d ", tp[p]); p++; p %= MAX_SIZE; } printf("\n==================================;\n"); } private: int size; //队列的长度 int MAX_SIZE; //队列长度上限,也就是数组的长度,通过构造函数初始化 T* tp; int p_pop; //记录pop的位置,也就是队列的头 int p_push; //记录push的位置,也就是队列的尾 }; int main() { Queue<int> queue(30); queue.travel(); //打印空表验证 //报三减一的游戏来验证 for (int i = 1; i <= 13; i++) {序号为1~13的人围成一圈队列 queue.push(i); } queue.travel(); int count = 0; //报数的记录,报到3的倍数的人被淘汰 while (queue.getSize()) { count++; int temp = queue.pop(); //报数的人被pop出来 if (count % 3 == 0) { //如果是3的倍数直接淘汰,不push回队列。 printf("%d\n", temp); } else { //不是3的倍数的成员push回队列,接着后面的游戏 queue.push(temp); } } queue.travel();//打印空表验证 return 0; }

    运行结果(Eclipse):

    2. 用链表实现 思想: 类(List)模板内创建结构体(即每一个成员),结构体内存放数据data和尾指针next(指向下一个成员从而实现循环一圈)。

    #include <iostream> #include <cstdio> #include <cstring> #include <cmath> using namespace std; template<class T> class Link { public: Link() : head(0), tail(0), LinkSize(0) { } ~Link() { Clear(); } bool is_Empty(); int getSize(); void Push(const T&); void Pop(); void show(); void Clear(); T& getHead() { //其实可以和Pop函数合并成一个函数,带有返回值T的Pop函数 return head->data; } private: struct Node { T data; //Node* prev; Node* next; Node(const T& data, Node* next = NULL) : data(data), next(next) { } ; }; Node* head, *tail; int LinkSize; }; template<class T> inline int Link<T>::getSize() { return LinkSize; } template<class T> inline bool Link<T>::is_Empty() { return head == NULL; } template<class T> inline void Link<T>::Push(const T& data) { if (is_Empty()) { head = new Node(data); tail = head; } else { tail->next = new Node(data); tail = tail->next; } LinkSize++; } template<class T> inline void Link<T>::Pop() { Node* temp = head; head = head->next; delete temp; LinkSize--; } template<class T> inline void Link<T>::Clear() { while (!is_Empty()) { Pop(); } } template<class T> inline void Link<T>::show() { Node* lp = head; for (int i = 0; i < LinkSize; i++) { cout << lp->data << "\t"; lp = lp->next; } cout << endl; cout << endl; } int main() { int i , j; Link<int> link1; for (i = 1; i <= 9; i++) { link1.Push(i); } link1.show(); i = 0; while (!link1.is_Empty()) { i++; j = link1.getHead(); if (i % 3 != 0) { link1.Push(j); } link1.Pop(); if (i % 3 == 0) { cout << j << " is out!" << endl; link1.show(); } } return 0; }

    运行结果(Eclipse):

    ======================================================== 【文章为本人的学习笔记部分的分享,有任何错误地方欢迎评论指出,万分感谢!】

    Processed: 0.009, SQL: 9