数据结构之队列
什么是队列
- 队列是和栈一样
操作受限 的线性表,栈是只允许在线性表的一端进行入栈和出栈操作,而队列是会允许在线性表的一端进行入队,在另外一端进行出队操作
队列的基本操作- bool initQueue(Queue & Q); // 初始化队列
- void destroyQueue(Queue Q); // 如果是顺序队列则不需要销毁
- bool push(Queue & Q, ElemType x); // 入队
- bool pop(Queue & Q, ElemType & x); // 出队
- // 获取队头元素的值
- void getTop(Queue Q, ELemType & x);
- bool queueEmpty(Queue Q); // 判断队列是否为空
复制代码顺序队列
- 用静态数组实现的队列(使用顺序存储结构实现的队列)
缺点:空间固定
顺序队列的代码实现- #include<stdio.h>
- #define Elemtype int
- #define MaxSize 10
- typedef struct SQueue{
- Elemtype data[MaxSize];
- size_t front,rear; // 队头和队尾指针(存储数组下标)
- }SQueue;
- bool initQueue(SQueue & Q)
- {
- Q.front = 0;
- Q.rear = 0;
- }
- // 入队
- bool push(Queue & Q, ElemType x)
- {
- // 如果队列满了则返回false
- if((Q.rear + 1) % MaxSize == Q.front)
- return false;
- Q.data[Q.rear] = x;
- Q.rear = (Q.rear+1) % MaxSize;
- }
- // 出队
- bool pop(Queue & Q, ElemType & x)
- {
- // 如果队列为空,则返回false
- if(Q.front == Q.rear)
- return false
- x = Q.data[Q.front];
- Q.front = (Q.front + 1) % MaxSize;
- }
- // 获取队头元素的值
- void getTop(Queue Q, ELemType & x){
- // 如果队列为空,则返回false
- if(Q.front == Q.rear)
- return false
- x = Q.data[Q.front];
- }
- // 判断队列是否为空
- bool SqueueEmpty(SQueue Q);{
- if(Q.front == Q.rear)
- return true;
- return false;
- }
复制代码代码缺陷
上述代码实现的队列,会浪费一个存储空间,如何避免浪费一个存储空间呢?
- 使用一个length变量,存储队列的长度
- typedef struct SQueue{
- Elemtype data[MaxSize];
- size_t front,rear; // 队头和队尾指针(存储数组下标)
- Size_t length;
- }SQueue;
- bool initQueue(SQueue & Q)
- {
- Q.front = 0;
- Q.rear = 0;
- Q.length = 0; // 计数器
- }
- // 入队
- bool push(Queue & Q, ElemType x)
- {
- // 如果队列满了则返回false
- if(Q.front == Q.rear && Q.length == MaxSize)
- return false;
- Q.data[Q.rear] = x;
- Q.rear = (Q.rear+1) % MaxSize;
- Q.length++;
- }
- // 出队
- bool pop(Queue & Q, ElemType & x)
- {
- // 如果队列为空,则返回false
- if(Q.front == Q.rear && Q.length == 0)
- return false
- x = Q.data[Q.front];
- Q.front = (Q.front + 1) % MaxSize;
- Q.rear--;
- }
复制代码
- 使用一个flag变量,出队时将flag 置为0 , 入队将flag置为1
- typedef struct SQueue{
- Elemtype data[MaxSize];
- size_t front,rear; // 队头和队尾指针(存储数组下标)
- bool flag;
- }SQueue;
- bool initQueue(SQueue & Q)
- {
- Q.front = 0;
- Q.rear = 0;
- }
- // 入队
- bool push(Queue & Q, ElemType x)
- {
- // 如果队列满了则返回false
- if(Q.front == Q.rear && Q.flag = 1)
- return false;
- Q.data[Q.rear] = x;
- Q.rear = (Q.rear+1) % MaxSize;
- Q.flag = 1;
- }
- // 出队
- bool pop(Queue & Q, ElemType & x)
- {
- // 如果队列为空,则返回false
- if(Q.front == Q.rear && Q.flag == 0)
- return false
- x = Q.data[Q.front];
- Q.front = (Q.front + 1) % MaxSize;
- Q.rear--;
- Q.flat = 0;
- }
复制代码链式队列
- 用链表实现的队列(存储空间不固定,根据内存来确定)
- #include<stdio.h>
- #include<stdlib.h>
- #define ElemType int
- typedef struct LinkNode { // 链式队列结点
- ElemType data;
- struct LinkNode* next;
- }LinkNode;
- typedef struct {
- LinkNode* front, * rear; // 队列的队头和队尾指针
- }LinkQueue;
- // 初始化链式队列
- bool initLinkQueue(LinkQueue& LQ)
- {
- LinkNode* n = (LinkNode*)malloc(sizeof(LinkNode));
- if (n == NULL)
- return false;
- n->next = NULL;
- LQ.front = n;
- LQ.rear = n;
- return true;
- }
- // 销毁链式队列
- void destoryQueue(LinkQueue& LQ)
- {
- LinkNode* cur = LQ.front->next;
- LinkNode* next;
- while (cur != NULL)
- {
- next = cur->next;
- free(cur);
- cur = next;
- }
- free(LQ.front); // 释放头结点
- LQ.front = NULL;
- LQ.rear = NULL;
- }
- // 判断链式队列为空
- bool isEmpty(LinkQueue LQ)
- {
- if (LQ.front == LQ.rear)
- return true;
- else
- return false;
- }
- // 入队
- bool push(LinkQueue& LQ, ElemType x)
- {
- LinkNode* n = (LinkNode*)malloc(sizeof(LinkNode));
- if (n == NULL)
- return false;
- n->data = x;
- n->next = NULL;
- LQ.rear->next = n;
- LQ.rear = n; // 修改队尾指针
- return true;
- }
- // 出队
- bool pop(LinkQueue& LQ, ElemType& x)
- {
- if (isEmpty(LQ)) // 判断链式队列是否为空
- return false;
- LinkNode* head = LQ.front;
- LinkNode* cur = head->next; // 当前要出的结点
- x = cur->data;
- head->next = cur->next;
- if (LQ.rear == cur) // 此次出队的是最后一个结点
- LQ.rear = LQ.front;
- free(cur); // 释放结点
- return true;
- }
- // 获取队头结点存放的数据
- bool getTop(LinkQueue& LQ, ElemType& x)
- {
- if (isEmpty(LQ)) // 判断链式队列是否为空
- return false;
- LinkNode* head = LQ.front;
- LinkNode* cur = head->next; // 队头结点
- x = cur->data;
- return true;
- }
- // 打印整个队列
- void printQueue(LinkQueue LQ)
- {
- LinkNode* cur = LQ.front->next; // 作为遍历整个队列的结点
- if(!isEmpty(LQ))
- {
- while (cur != NULL)
- {
- printf("%d <- ", cur->data);
- cur = cur->next;
- }
- printf("NULL\n");
- }
- }
- // 测试函数
- void test_LinkQueue(){
- LinkQueue LQ;
- initLinkQueue(LQ);
- push(LQ, 1);
- push(LQ, 2);
- push(LQ, 3);
- push(LQ, 4);
- printQueue(LQ);
- ElemType x = 0;
- pop(LQ, x);
- pop(LQ, x);
- printQueue(LQ);
- }
- int main()
- {
- test_LinkQueue();
- return 0;
- }
复制代码队列的变种(双端队列)
双端队列:受限制的线性表,可以在线性表的两端进行插入和删除操作
- 双端队列只允许在队列的一端进行插入和删除操作就等价于栈
- 输入受限的双端队列: 只允许一端进行插入,两端允许删除的线性表
- 输出受限的双端队列: 只允许一段进行删除,两段允许插入的线性表
练习题:判断输出序列合法性
若数据元素输入序列为1,2,3,4,5 则哪些输出序列是合法的,哪些是非法的? 来源:程序园用户自行投稿发布,如果侵权,请联系站长删除 免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |