数据结构 栈和队列(二)队列 思维导图
3.2.1 队列的基本概念 1、概念
队列(Queue) 是只允许在一端进行插入,在另一端删除的线性表
队列 是一种特殊的线性结构,它只允许在队列的首部(head/front)进行删除操作,这称为“出队”,而在队列的尾部(tail/rear)进行插入操作,这称为“入队”。当队列中没有元素时(即head == tail),称为空队列。比如买票,每个排队买票的窗口就是一个队列。在这个队列当中,新来的人总是站在队列的最后面,来得越早的人越靠前,也就是越早能买到票,我们称为“先进先出”(First In First Out, FIFO)原则。🚘
队列是一个有序列表,可以用数组 或是链表 来实现
在队首删除元素,在队尾插入元素
“先进先出”(FIFO)原则
2、基本操作
队列基本操作
InitQueue(&Q): 初始化队列,构造一个空队列Q。
DestroyQueue(&Q): 销毁队列。销毁并释放队列Q所占用的内存空间。
EnQueue(&Q,x): 入队,若队列Q未满,将x加入,使之成为新的队尾。
DeQueue(&Q,&x): 出队,若队列Q非空,删除队头元素,并用x返回。
GetHead(Q,&x): 读队头元素,若队列Q非空,则将队头元素赋值给x。
其他常用操作:
QueueEmpty(Q): 判队列空,若队列Q为空返回true,否则返回false。
3.2.2 顺序队列 1、顺序队列
初始状态(队空状态): Q.front == Q.rear == 0
进队操作: 队不满,先送值到队尾元素,再将队尾指针加1
出队操作: 队不空,先去队头元素值,再将队头指针加1
会出现“上溢出”,即“假溢出”
2、循环队列
为了解决顺序队列的“假溢出 ”,充分利用空间,即把存储队列元素的表从逻辑上视为一个环 。
用模运算将存储空间在逻辑上变成了“环状” 。取模运算,即取余运算。两个整数 a,b,a%b == a除以b的余数。
队空状态: Q.front == Q.rear;
队满状态: (Q.rear + 1) % MaxSize == Q.front
进队操作: (Q.rear + 1) % MaxSize
出队操作: (Q.front + 1) % MaxSize
队列个数: (Q.rear - Q.front + MaxSize) % MaxSize
3、区分队空和队满的方式 (1)
牺牲一个存储单元 ,队列已满的条件:队尾指针的再下一个位置是队头,
即(Q.rear+1)%MaxSize == Q.front
(2)
类型中增设表示元素个数的数据成员 。
插入成功 size++;
删除成功 size–;
队满条件: size==MaxSize
队空条件: size == 0;
队列元素个数 = size
(3)
类型中增设tag数据成员
每次删除操作成功时,都令tag=0;
每次插入操作成功时,都令tag=1;
队满条件: front==rear && tag == 1
队空条件: front==rear && tag == 0
4、代码实现 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 #include <iostream> #include <stdlib.h> #include <stdio.h> #define MaxSize 10 using namespace std ;typedef struct { int data[MaxSize]; int front, rear; } SqQueue; bool InitQueue (SqQueue &Q) { Q.front = Q.rear = 0 ; } bool isEmpty (SqQueue Q) { return Q.front == Q.rear; } bool isFull (SqQueue Q) { return (Q.rear + 1 ) % MaxSize == Q.front; } bool EnQueue (SqQueue &Q, int e) { if (isFull(Q)) return false ; Q.data[Q.rear] = e; Q.rear = (Q.rear + 1 ) % MaxSize; return true ; } bool DeQueue (SqQueue &Q, int &e) { if (isEmpty(Q)) return false ; e = Q.data[Q.front]; Q.front = (Q.front + 1 ) % MaxSize; return true ; } int GetTop(SqQueue Q) { if (isEmpty(Q)) return -1 ; return Q.data[Q.front]; } int GetLength (SqQueue Q) { if (isEmpty(Q)) return -1 ; return (Q.rear - Q.front + MaxSize) % MaxSize; } void printQueue (SqQueue Q) { int t = Q.front; int len = t + GetLength(Q); for (int i = t; i < len; i++) { cout << "queue[" << i % MaxSize << "] = " << Q.data[i % MaxSize] << endl ; } } int main () { SqQueue Q; InitQueue(Q); bool loop = true ; while (loop) { system("pause" ); system("cls" ); cout << "欢迎进行队列的操作,请按指定序号操作,考研顺利!" << endl ; cout << "---------------------菜单---------------------" << endl ; cout << "1、入队" << endl ; cout << "2、出队" << endl ; cout << "3、输出队" << endl ; cout << "4、查看队头元素" << endl ; cout << "5、查看队长" << endl ; cout << "0、退出" << endl ; int num; cout << "请选择序号:" ; cin >> num; switch (num) { case 1 : if (isFull(Q)) { cout << "队满" << endl ; } else { int e; cout << "请输入数据:" ; cin >> e; EnQueue(Q, e); } break ; case 2 : if (isEmpty(Q)) { cout << "队空" << endl ; } else { int e = -1 ; DeQueue(Q, e); cout << "出队的数据为:" << e << endl ; } break ; case 3 : if (isEmpty(Q)) cout << "队空" << endl ; else printQueue(Q); break ; case 4 : if (isEmpty(Q)) { cout << "队空" << endl ; } else { cout << "队顶的数据为: " << GetTop(Q) << endl ; } break ; case 5 : cout << "队长为:" << GetLength(Q) << endl ; break ; case 0 : loop = false ; break ; case 6 : break ; default : break ; } } return 0 ; }
5、效果实现
3.2.3 链式队列 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 #include <iostream> #include <stdlib.h> #include <stdio.h> #define MaxSize 10 using namespace std ;typedef struct LinkNode { int data;; LinkNode *next; } LinkNode; typedef struct { int size ; LinkNode *front, *rear; }LinkQueue; bool InitQueue (LinkQueue &Q) { Q.front = Q.rear = (LinkNode *)malloc (sizeof (LinkNode)); Q.front->next = NULL ; Q.size = 0 ; return true ; } bool isEmpty (LinkQueue Q) { return Q.size == 0 ; } bool EnQueue (LinkQueue &Q, int e) { LinkNode *t; t = (LinkNode *)malloc (sizeof (LinkNode)); t->data = e; t->next = NULL ; Q.rear->next = t; Q.rear = t; Q.size ++; return true ; } bool DeQueue (LinkQueue &Q, int &e) { if (isEmpty(Q)) return false ; LinkNode *p = Q.front->next; e = p->data; Q.front->next = p->next; if (Q.rear == p) Q.rear = Q.front; free (p); Q.size --; return true ; } int GetTop (LinkQueue Q) { if (isEmpty(Q)) return -1 ; return Q.front->next->data; } int GetLength (LinkQueue Q) { return Q.size ; } void printQueue (LinkQueue Q) { LinkNode *t = Q.front->next; while (t != NULL ) { cout << t->data << "->" ; t = t->next; } printf ("\n" ); } int main () { LinkQueue Q; InitQueue(Q); bool loop = true ; while (loop) { system("pause" ); system("cls" ); cout << "欢迎进行队列的操作,请按指定序号操作,考研顺利!" << endl ; cout << "---------------------菜单---------------------" << endl ; cout << "1、入队" << endl ; cout << "2、出队" << endl ; cout << "3、输出队" << endl ; cout << "4、查看队头元素" << endl ; cout << "5、查看队长" << endl ; cout << "0、退出" << endl ; int num; cout << "请选择序号:" ; cin >> num; switch (num) { case 1 : int e; cout << "请输入数据:" ; cin >> e; EnQueue(Q, e); break ; case 2 : if (isEmpty(Q)) { cout << "队空" << endl ; } else { int e = -1 ; DeQueue(Q, e); cout << "出队的数据为:" << e << endl ; } break ; case 3 : if (isEmpty(Q)) cout << "队空" << endl ; else printQueue(Q); break ; case 4 : if (isEmpty(Q)) { cout << "队空" << endl ; } else { cout << "队顶的数据为: " << GetTop(Q) << endl ; } break ; case 5 : cout << "队长为:" << GetLength(Q) << endl ; break ; case 0 : loop = false ; break ; case 6 : break ; default : break ; } } return 0 ; }
3.2.4 双端队列