队列
1.队列的性质(先进先出):
- 新元素插入队尾(新来的同学站在最后面)
- 出队方案唯一(队伍买饭的先后顺序确定)
- 队首元素先出(站在前面的同学先买饭)
2.进队,出队,删除等操作的实现
1 #include <iostream> 2 #include <cassert> 3 using namespace std; 4 class Queue { 5 private: 6 int *data; 7 int head, tail, length; 8 public: 9 Queue(int length_input) { //构造函数 10 data = new int[length_input]; 11 length = length_input; 12 head = 0; 13 tail = -1; 14 } 15 ~Queue() { //析构函数 16 delete[] data; 17 } 18 void push(int element) { //加入队列函数 19 if (tail + 1 < length) { //判断队列是否有位置可插入 20 tail++; 21 data[tail] = element; 22 } 23 } 24 void output() { //将整个队列输出 25 for (int i = head; i <= tail; i++) { 26 cout << data[i] << " "; 27 } 28 cout << endl; 29 } 30 int front(){ //队首元素的输出 31 assert(head<=tail); //宏断言,判断队列是否为空,为空则终止程序 32 return data[head]; //不为空,返回队首元素 33 } 34 void pop(){ //删除队首元素 35 assert(head<=tail); //宏断言,判断队列是否为空,为空则终止程序 36 head++; //不为空,head向后移动一位,表示删除队首元素 37 } 38 }; 39 int main() { 40 Queue queue(100); 41 for (int i = 1; i <= 10; i++) { 42 queue.push(i); 43 } 44 queue.output(); 45 cout<<queue.front()<<endl; 46 queue.pop(); 47 queue.output(); 48 return 0; 49 }
3.循环队列:
前面讲到的队列实现方式有一个问题:“假上溢”。什么叫“假上溢”呢?回忆一下之前的插入队列的代码:
1 void push(int element) { //加入队列函数 2 if (tail + 1 < length) { //判断队列是否有位置可插入 3 tail++; 4 data[tail] = element; 5 } 6 }
当 tail 达到队列的上限后就不能在插入了,此时再插入就意味着溢出。但是 tail 达到上限后就意味着要插入的元素真的『无处可放』了么?能不能构造出一个队列无法加入元素,但队列并没有满的例子?
回忆一下删除队首元素的操作
1 void pop(){ //删除队首元素 2 assert(head<=tail); //宏断言,判断队列是否为空,为空则终止程序 3 head++; //不为空,head向后移动一位,表示删除队首元素 4 }
如果一个队列在不断的执行插入、弹出、插入、弹出……那么可以想象,当执行到 tail 达到队列上限之后,便不能再插入到队列中了,而此时队列其实是空的。
对于这种存储区没有用满,而队列却发生了溢出的现象,我们称之为“假上溢”,也叫“假溢出”。
能不能想出一种解决方案,能将所有的存储区充分利用起来呢?
循环队列,顾名思义,就是以循环的方式来存储队列。回顾一下我们之前用到的队尾标记 tail。对于循环队列,当队尾标记 tail 到达数组的上界后,如果队列内的元素个数没有达到容量上限,就跳转到数组的起始位置,也就是 0 的位置;队首标记 head 到达数组上界采取同样的处理。通过这样的方法,我们就能够最大化利用内存空间,避免“假上溢”的情况出现啦。
性质:
- 在循环队列里,如果容量没有达到上限,当队尾队首标记达到数组上界后,就跳转到数组起始位置
- 循环队列里通过统计队列里元素个数,判断能否继续往队列里插入元素
循环队列的入队,出队和遍历
1 #include <iostream> 2 #include <cassert> 3 using namespace std; 4 class Queue { 5 private: 6 int *data; 7 int head, tail, length, count; //增加一个count用来存储当前队列中一共有多少个元素 8 public: 9 Queue(int length_input) { 10 data = new int[length_input]; 11 length = length_input; 12 head = 0; 13 tail = -1; 14 count = 0; 15 } 16 ~Queue() { 17 delete[] data; 18 } 19 bool push(int element) { 20 if (count < length) { 21 tail = (tail + 1) % length; 22 data[tail] = element; 23 count++; 24 return true; 25 } else { 26 return false; 27 } 28 } 29 void output() { 30 for (int i = head; i != tail + 1; i = (i + 1) % length) { 31 cout << data[i] << " "; 32 } 33 cout << endl; 34 } 35 int front() { 36 assert(count>0); 37 return data[head]; 38 } 39 void pop() { 40 assert(count>0); 41 head=(head+1)%length; 42 count--; 43 } 44 }; 45 int main() { 46 Queue queue(100); 47 for (int i = 1; i <= 10; i++) { 48 queue.push(i); 49 } 50 queue.output(); 51 cout << queue.front() << endl; 52 queue.pop(); 53 queue.output(); 54 return 0; 55 }