赞
踩
本片文章详细介绍了另外两种存储逻辑关系为 “一对一” 的数据结构——栈和队列中的队列,并使用C语言实现链队列。
队列C语言实现源码:队列源码
以队列在存储数据时具有特殊的顺序规则:
队列:使用队列存储数据,遵循 “先进先出” 的原则,即最先进队列的数据最先出队列。队列也可以分为顺序队列(基于数组实现)和链队列(基于链表实现)。
队列的实现方式分为顺序和链式结构,分别适用于不同的场景。顺序结构在内存中占据一块连续的空间,而链式结构通过节点之间的指针连接。这使得栈和队列在实际应用中更灵活,可以根据具体需求选择不同的实现方式。
链式队列的实现其实和之前单链表的实现很类似,只不过队列中数据的进出要遵循 “先进先出” 的原则。
链式队列节点的定义:
typedef int QDataType;
typedef struct QueueNode
{
QDataType val;
struct QueueNode* next;
}QNode;
队列的定义通常包括两个指针和一个整型,一个指针front指向队列的头,一个指针tail指向队列的尾,还有一个整型size用来记录队列的数据个数。
下面是队列结构的定义:
typedef struct Queue
{
QNode* front;//指向队列头部的指针
QNode* tail;//指向队列尾部的指针
int size;//记录队列中元素个数
}Queue;
刚开始队列为空,头指针front和尾指针tail指向NULL,此时队列中元素个数为0,因此将size初始化为0。
代码如下:
void QueueInit(Queue* pq)
{
assert(pq);//检查参数有效性
pq->front = pq->tail = NULL;
pq->size = 0;
}
数据入队列分为一下两种情况:
数据1 2 3 4 入队列图解:
代码如下:
void QueuePush(Queue* pq, QDataType x) { assert(pq);//检查参数有效性 //创建新节点 QNode* newnode = (QNode*)malloc(sizeof(QNode)); if (newnode == NULL) { perror("QueuePush->malloc"); exit(-1); } newnode->next = NULL; newnode->val = x; //入队列 //1. 队列为空 //2. 队列不为空 if (pq->front == NULL) { assert(!pq->tail);// 队列为空时,tail front都为空 pq->front = pq->tail = newnode; } else { pq->tail->next = newnode; pq->tail = newnode; } pq->size++; }
我们知道,队列只能在队尾一端入数据,出数据时只能出队头的数据。因为它要保证有数据元素需要出队时,按照 “先进先出” 的原则。
数据出队的步骤如下:
数据1 2 3 4 出队列图解:
代码如下:
void QueuePop(Queue* pq) { assert(pq);//检查参数有效性 assert(!QueueEmpty(pq));//检查队列是否为空,为空不能pop //出队列 //1. 队列只有1个元素 //2.队列有2个以上元素 if (pq->front->next == NULL) { free(pq->front); pq->front = pq->tail = NULL; } else { QNode* next = pq->front->next; free(pq->front); pq->front = next; } pq->size--; }
获取队头元素的步骤如下:
代码如下:
QDataType QueueFront(Queue* pq)
{
assert(pq);//检查参数有效性
assert(!QueueEmpty(pq));//检查队列是否为空,为空不能取队头元素
return pq->front->val;
}
获取队尾元素的步骤如下:
代码如下:
QDataType QueueBack(Queue* pq)
{
assert(pq);//检查参数有效性
assert(!QueueEmpty(pq));//检查队列是否为空,为空不能取队尾元素
return pq->tail->val;
}
队列中的size记录的就是队列中元素的个数,如要获取队列元素个数,返回size即可。
代码如下:
int QueueSize(Queue* pq)
{
assert(pq);//检查参数有效性
return pq->size;
}
根据队列初始化函数,我们知道,队列为空时,front 和 tail 都指向NULL。
此时size=0,也可以用size来判断,这里作者选择用front 和 tail 来进行判断。
代码如下:
bool QueueEmpty(Queue* pq)
{
assert(pq);//检查参数有效性
return pq->front == NULL && pq->tail == NULL;
}
链队列用来存储数据的节点都是动态申请的,因此队列销毁时,只需要遍历该链队列,依次释放每个节点。最后将 front 和 tail 置为NULL,size 置为0即可。
代码如下:
void QueueDestroy(Queue* pq)
{
assert(pq);//检查参数有效性
QNode* cur = pq->front;
while (cur)
{
QNode* next = cur->next;
free(cur);
cur = next;
}
pq->front = pq->tail = NULL;
pq->size = 0;
}
至此,本片文章就结束了,若本篇内容对您有所帮助,请三连点赞,关注,收藏支持下。
创作不易,白嫖不好,各位的支持和认可,就是我创作的最大动力,我们下篇文章见!
如果本篇博客有任何错误,请批评指教,不胜感激 !!!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。