赞
踩
目录
只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出
的特点。入队列:进行插入操作的一端称为队尾
出队列:进行删除操作的一端称为队头
队列要进行的是尾插,头删,因此用列表更优,我们用单链表来实现队列的核心功能
定义单结点,有元素,和下一个结点的地址。
要对头和尾进行操作,那么在定义两个指针来指向链表首尾
队列是一个结构体,将首位两指针放入队列表示队列的首尾
- typedef int QDatatype;
-
- //定义单链表结点
- typedef struct QueueNode
- {
- QDatatype data;
- struct QueueNode* next;
- }QNode;
-
- //定义队列
- typedef struct Queue
- {
- QNode* head;
- QNode* tail;
- }Queue;
队列初始化首尾为空
//队列初始化 void QueueInit(Queue* pq) { assert(pq); pq->head = pq->tail = NULL; }
注意:不能直接将队列首尾指针置空,若队列本身不为空,首尾指针置空会造成野指针问题。
先将队列中每个结点释放后,再对队列的首尾进行置空。
- //队列销毁
- void QueueDestory(Queue* pq)
- {
- assert(pq);
- QNode* cur = pq->head;
- while (cur)
- {
- QNode* next = cur->next;
- free(cur);
- cur = next;
- }
- pq->head = pq->tail = NULL;
- }
相当于单链表尾插
断言后先进行结点的开辟。因为没有创建哨兵结点,所以我们要判断头为空时的情况。
尾插后记得更新尾结点。
- //入队
- void QueuePush(Queue* pq, QDatatype x)
- {
- assert(pq);
- QNode* newnode = (QNode*)malloc(sizeof(QNode));
- assert(newnode);
- newnode->data = x;
- newnode->next = NULL;
- if (pq->head == NULL)
- {
- assert(pq->tail==NULL);
- pq->head = pq->tail = newnode;
- }
- else
- {
- pq->tail->next = newnode;
- pq->tail = newnode;
- }
- }
断言时还要判断队列是否为空,即assert(pq->head&&pq->tail);
这里要注意为什么判断的时head的next是否为空而不是直接判断head:
若队列只有一个结点时,此时head=tail,head指向next,head置空,但此时tail还指向原head的位置,会造成野指针的问题。
- //出队
- void QueuePop(Queue* pq)
- {
- assert(pq);
- assert(pq->head&&pq->tail);
-
- if (pq->head->next==NULL)
- {
- free(pq->head);
- pq->head = pq->tail = NULL;
- }
- else
- {
- QNode* next = pq->head->next;
- free(pq->head);
- pq->head = next;
- }
- }
当head和tail为空时返回true,否则返回false,直接return即可
//判断是否为空 bool QueueEmpty(Queue* pq) { assert(pq); return pq->head == NULL&&pq->tail == NULL; }
直接计数遍历返回即可,但是这样效率会降低。
优化:直接在定义队列时,在首尾指针下加入一个计数变量,初始化时置0,每次入队时++,出队时--,需要用到个数时直接返回即可。
- //队列元素个数
- size_t QueueSize(Queue* pq)
- {
- assert(pq);
- QNode* cur = pq->head;
- size_t size = 0;
- while (cur)
- {
- size++;
- cur = cur->next;
- }
- return size;
- }
通过首尾指针直接访问结点元素即可。
- //对头元素
- QDatatype QueueFront(Queue* pq)
- {
- assert(pq);
- assert(pq->head);
- return pq->head->data;
- }
-
- //队尾元素
- QDatatype QueueBack(Queue* pq)
- {
- assert(pq);
- assert(pq->tail);
- return pq->tail->data;
- }
直接手动创建队列进行入队出队测试:
入队:1 2 3 4 5
出队预计:1 2 3 4 5
- void TestQueue()
- {
- Queue q;
- QueueInit(&q);
- QueuePush(&q,1);
- QueuePush(&q, 2);
- QueuePush(&q, 3);
- QueuePush(&q, 4);
- QueuePush(&q, 5);
- while (!QueueEmpty(&q))
- {
- printf("%d ",QueueFront(&q));
- QueuePop(&q);
- }
- printf("\n");
- }
1 2 3 4 5
栈: 后进先出 5 4 3 2 1
队列:先进先出 1 2 3 4 5
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。