坚持看完,结尾有思维导图总结
这里写目录标题
- 队列的定义于性质
- 如何实现
- 队列的功能
- 初始化队列
- 入队列
- 出队列
- 队列的销毁
- 队列取队头数据
- 队列取队尾数据
- 判断队列是否为空
- 判断队列长度
- 总结
队列的定义于性质
队列是一种数据结构,他储存数据的方式就和排队一样
先进入队列的先出队列
就和我们日常排队一样,后入队列的后出队列
如何实现
如何实现队列,实现队列的基础数据结构是什么?
有两种基础数据结构供我们选择,顺序表和链表
我们这里使用链表,因为出队列是将先入的数据弹出,若放在顺序表中就是顺序表前的数据,弹出需要将后方数据移动到前面,所以我们使用链表
如何用链表实现?
首先我们要先定义链表节点,然后用链表节点构造队列
typedef int STNodeData;
typedef struct STNode {
STNodeData val;
struct STNode* next;
}STNode;
typedef STNode STHead;
创建链表节点的函数
STNode* BuyNode(int a)
{
STNode* newnode = (STNode*)malloc(sizeof(STNode));
if (newnode == NULL)
{
perror("malloc failed");
exit(-1);
}
newnode->val = a;
newnode->next = NULL;
return newnode;
}
然后我们定义队列,包含队列的头,队列的尾,和队列的个数
为了方便实现一些功能
typedef struct List {
STNode* head;
STNode* tail;
int num;
}List;
现在我们就完成了队列的基本设计
队列的功能
队列和常见的数据结构一样,有以下功能
初始化队列
初始化队列我们需要做什么?
因为我们的参数只有 head tail 和 num
所以我们只要把这些参数安排还就可以了
void ListInit(List* pl)
{
pl->head = NULL;
pl->tail = NULL;
pl->num = 0;
}
入队列
入队列主要是增加新的节点
那就是区分两个情况
head 和 tail 为空
head 和 tail 不是空
当 head 为空的时候,我们就需要改变头结点,同时尾结点也是空的,因此两个都需要改为新的节点
当 head 不为空,这个时候只要在尾部链接新的节点,然后将尾结点修改即可
void ListPush(List* pl, ListData a)
{
assert(pl);
STNode* newnode = BuyNode(a);
if (pl->head == NULL)
{
pl->head = newnode;
pl->tail = newnode;
}
else {
pl->tail->next = newnode;
pl->tail = newnode;
}
pl->num++;
}
出队列
出队列要实现哪些功能?
首先是没有节点,直接报错,没得商量
其次是当头和尾都指向同一个节点的时候,这个时候弹出要同时修改头尾节点
最后才是头结点离尾结点很远,就释放头结点指向的空间,然后头结点不断向尾结点靠近就可以了
void ListPop(List* pl)
{
assert(pl);
assert(pl->head);//如果为空说明不能 pop
if (pl->head == pl->tail)
{
free(pl->head);
pl->head = NULL;
pl->tail = NULL;
}
else
{
STNode* cur = pl->head;
pl->head = pl->head->next;
free(cur);
}
pl->num--;
}
队列的销毁
队列的销毁,就是通过遍历将所有的节点都释放
和pop类似也要分成两种情况,最终当 pl->head == NULL 的时候停止
void ListDestroy(List* pl)
{
assert(pl);
while (pl->head != NULL)
{
if (pl->head == pl->tail)
{
free(pl->head);
pl->head = NULL;
pl->tail = NULL;
}
else
{
STNode* cur = pl->head;
pl->head = pl->head->next;
free(cur);
}
}
}
队列取队头数据
队列的数据,直接将head 的数据直接拿出来
STNodeData ListTop(List* pl)
{
assert(pl);
assert(pl->head);
return pl->head->val;
}
队列取队尾数据
和上面相似
判断如果队列非空,就能够将数据取出来
STNodeData ListTail(List* pl)
{
assert(pl);
assert(!ListEmpty(pl));
return pl->tail->val;
}
判断队列是否为空
当 个数为 0 的时候,就说明队列空了
bool ListEmpty(List* pl)
{
if (pl->num == 0)
return true;
return false;
}
判断队列长度
直接将 num 提取出来就可以了
int ListLong(List* pl)
{
assert(pl);
return pl->num;
}
总结
希望大家看完,能够有所收获
如果有错误,请指出我一定虚心改正
动动小手点赞
鼓励我输出更加优质的内容