队列

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 }

 

posted @ 2016-07-14 16:09  绵绵思远道  阅读(199)  评论(0编辑  收藏  举报