队列(链式队列)----C语言

链式队列----用链表实现,链式队列就是一个操作受限的单向链表,如果读者了解单向链表的建立过程,那理解链式队列就很容易了,先回顾一下单向链表的建立过程
(不熟悉单向链表的可以先看看另一片随笔,再回来看链式队列理解起来更容易☺链表(单向链表的建立、删除、插入、打印)
单向链表
单向链表节点的组成部分
struct link
{
int data;
struct link *next;
};
数据域:data----用来存储节点数据
指针域:struct link *next----用来存储下一个节点的地址
链式队列和单向链表比就多了两个指针,头指针和尾指针(这里我多加了一个length来记录队列的长度)
typedef struct QNode /* 声明链式队列的结点 */
{
int data;
struct QNode *next;
}Node;
typedef struct QueuePoint /* 声明链式队列的首尾指针 */
{
Node *front;
Node *rear;
int length; /* 记录链式队列长度 */
}Queue;
后面就是单向链表的建立了,这里就不再赘述了,重点分析下头指针的尾指针的移动,为了方便理解先附上main函数部分的代码
main()
{
int i = ;
char c;
Queue q; //链式队列首尾指针 和 长度 q.front = q.rear = NULL; /* 首尾指针初始化 */
q.length = ; /* 链式队列长度初始化 */
q = init(q); /* 初始化队列 */
printf("Do you want to append a new node(Y/N)?");
scanf_s(" %c", &c);
while (c == 'Y' || c == 'y')
{
q = AppendNode(q); /* 入队*/
DisplyNode(q); /* 按先进先出对队列进行打印 */
printf("Do you want to append a new node(Y/N)?");
scanf_s(" %c", &c);
}
printf("Do you want to delete node(Y/N)?");
scanf_s(" %c", &c);
while (c == 'Y' || c == 'y')
{
q = DeletNode(q);
DisplyNode(q);
printf("Do you want to delete node(Y/N)?");
scanf_s(" %c", &c);
} return ;
}
下面上图

(灵魂画手已上线)
简单描述一下上图的步骤
第一步:初始化队列(就是添加一个头节点在队列中),头结点不存储数据,使队首指针和队尾指针都指向头结点
第二步:入队(添加节点),使队尾指针指向头新建的节点,队首指针不变仍然指向头结点
初始化队列和入队----实现代码
//函数功能:初始化队列(其实就是搞个头结点放在队列里面)
//单独弄个子函数来初始化队列是为了方便入队的时候判断队列是否为空
Queue init (Queue p)
{
p.front = p.rear = (Node *)malloc(sizeof(Node));
if (p.front == NULL && p.rear == NULL)
{
printf("initialization failed");
exit();
}
p.front->next = NULL; return p;
}
//函数功能:新建节点并添加到队列中,记录队列长度
Queue AppendNode (Queue p)
{
int data;
Node *q; q = (Node *)malloc(sizeof(Node));
if (q == NULL) /* 判断分配内存是否失败 */
{
printf("No enough memory to allocate");
exit();
}
p.rear->next = q; /* 最后一个节点的指针指向新建节点*/
p.rear = q; /* 队尾指针指向新建节点*/ printf("Input node data\n");
scanf("%d", &data);
p.rear->data = data;
p.rear->next = NULL;
p.length++;
return p; }
后面来分析下出队时首尾指针的变化,因为后面出队时要用到判断队列是否为空的一个子函数,这里先附上子函数代码
int IsemptyQueue(Queue p)
{
if (p.front == p.rear) /* 队首指针和队尾指针重合队列为空 */
{
return Empty;
}
else
{
return NoEmpty;
}
}
出队时队首指针的位置是不变的,队首指针始终指向头节点,出队时头节点的指针域指向出队节点的后一节点,并将出队的节点用free()函数释放掉,为了方便读者理解下面上图

出队实现代码
Queue DeletNode (Queue p)
{
Node *del; if (IsemptyQueue(p) == Empty) /* 判断队列是否为空*/
{
printf("队列为空,无法出队 ");
return p;
}
else /* 队列不为空 */
{
if (p.front->next == p.rear) /* 如果出队的节点为最后一个节点 */
{
printf("出队节点的数据为%d----", p.rear->data);
free(p.rear); /* 释放最后一一个节点*/
p.rear = p.front; /* 队首指针和队尾指针都指向头节点 */
p.front->next = NULL;
p.length--;
}
else
{
del = p.front->next;
printf("出队节点的数据为%d----", del->data);
p.front->next = p.front->next->next; /* 使头节点的指针域指向出队节点的下一个节点 */
free(del); /* 释放出队的节点 */
p.length--;
} return p;
}
}
顺序队列和链式队列首尾指针的比较
1.顺序队列是用数组实现的,首指针在出队的时候移动,尾指针在入队的时候移动,需要考虑队列为空和队列为满的两种情况
2.链式队列是用链表实现的,首指针不移动始终指向头节点,尾指针在入队的时候移动,只考虑队列为空的情况(不用考虑满是因为链表长度在程序运行过程中可以不断增加,只要存储空间够malloc就能申请内存空间来存放节点)
下面附上完整代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define Empty 0 /* 队列为空 */
#define NoEmpty 1 /* 队列不为空*/ typedef struct QNode /* 声明链式队列的结点 */
{
int data;
struct QNode *next;
}Node;
typedef struct QueuePoint /* 声明链式队列的首尾指针 */
{
Node *front;
Node *rear;
int length; /* 记录链式队列长度 */
}Queue; void DisplyNode (Queue p); /* 打印队列 */
Queue init (Queue p); /* 初始化队列 */
Queue AppendNode (Queue p); /* 入队 */
Queue DeletNode (Queue p); /* 出队 */
int IsemptyQueue (Queue p); /* 判断队列是否为空*/
main()
{
int i = ;
char c;
Queue q; //链式队列首尾指针 和 长度 q.front = q.rear = NULL; /* 首尾指针初始化 */
q.length = ; /* 链式队列长度初始化 */
q = init(q); /* 初始化队列 */
printf("Do you want to append a new node(Y/N)?");
scanf_s(" %c", &c);
while (c == 'Y' || c == 'y')
{
q = AppendNode(q); /* 入队 */
DisplyNode(q); /* 按先进先出对队列进行打印 */
printf("Do you want to append a new node(Y/N)?");
scanf_s(" %c", &c);
}
printf("Do you want to delete node(Y/N)?");
scanf_s(" %c", &c);
while (c == 'Y' || c == 'y')
{
q = DeletNode(q); /* 出队 */
DisplyNode(q); /* 按先进先出对队列进行打印 */
printf("Do you want to delete node(Y/N)?");
scanf_s(" %c", &c);
} return ;
}
int IsemptyQueue(Queue p)
{
if (p.front == p.rear) /* 队首指针和队尾指针重合队列为空 */
{
return Empty;
}
else
{
return NoEmpty;
}
}
Queue DeletNode (Queue p)
{
Node *del; if (IsemptyQueue(p) == Empty) /* 判断队列是否为空*/
{
printf("队列为空,无法出队 ");
return p;
}
else /* 队列不为空 */
{
if (p.front->next == p.rear) /* 如果出队的节点为最后一个节点 */
{
printf("出队节点的数据为%d----", p.rear->data);
free(p.rear); /* 释放最后一一个节点*/
p.rear = p.front; /* 队首指针和队尾指针都指向头节点 */
p.front->next = NULL;
p.length--;
}
else
{
del = p.front->next;
printf("出队节点的数据为%d----", del->data);
p.front->next = p.front->next->next; /* 使头节点的指针域指向出队节点的下一个节点 */
free(del); /* 释放出队的节点 */
p.length--;
} return p;
}
}
//函数功能:初始化队列(其实就是搞个头结点放在队列里面)
//单独弄个子函数来初始化队列是为了方便入队的时候判断队列是否为空
Queue init (Queue p)
{
p.front = p.rear = (Node *)malloc(sizeof(Node));
if (p.front == NULL && p.rear == NULL)
{
printf("initialization failed");
exit();
}
p.front->next = NULL; return p;
}
//函数功能:新建节点并添加到队列中,记录队列长度
Queue AppendNode (Queue p)
{
int data;
Node *q; q = (Node *)malloc(sizeof(Node));
if (q == NULL) /* 判断分配内存是否失败 */
{
printf("No enough memory to allocate");
exit();
}
p.rear->next = q; /* 最后一个节点的指针指向新建节点*/
p.rear = q; /* 队尾指针指向新建节点*/ printf("Input node data\n");
scanf("%d", &data);
p.rear->data = data;
p.rear->next = NULL;
p.length++;
return p; }
//函数功能:按照先进先出原则对队列进行打印
void DisplyNode (Queue p)
{
if (IsemptyQueue(p) == Empty)
{
printf("队列为空,无法打印\n");
}
else
{
p.front = p.front->next;
printf("当前队列中的%d个节点[", p.length);
while (p.front != NULL)
{
printf("%d->", p.front->data);
p.front = p.front->next;
}
putchar(']');
putchar('\n');
}
}
程序试运行结果:

思考:上面说出队的时候链式队列的头指针是不移动的,始终指向头节点,其实也可以像顺序队列那样头指针在出队的时候也相应的移动,也能正常完成入队、出队、先进先出打印的操作
下面附上链式队列链接:队列(链式队列)----C语言
队列(链式队列)----C语言的更多相关文章
- C语言 队列 链式结构 实现
一个C语言链式结构实现的队列 mQueue (GCC编译). /** * @brief C语言实现的链式队列 * @author wid * @date 2013-10-31 * * @note 若代 ...
- C语言数据结构-链式队列的实现-初始化、销毁、清空、长度、队列头元素、插入、删除、显示操作
1.数据结构-链式队列的实现-C语言 typedef struct QNode { int data; struct QNode *next; }QNode,*QueuePtr; typedef st ...
- C语言实现链式队列
链式队列,简称"链队列",即使用链表实现的队列存储结构. 链式队列的实现思想同顺序队列类似,只需创建两个指针(命名为 top 和 rear)分别指向链表中队列的队头元素和队尾元素, ...
- C语言链表全操作(增,删,改,查,逆序,递增排序,递减排序,链式队列,链式栈)
一,数据结构——链表全操作: 链表形式: 其中,每个节点(Node)是一个结构体,这个结构体包含数据域,指针域,数据域用来存放数据,指针域则用来指向下一个节点: 特别说明:对于单链表,每个节点(Nod ...
- 顺序队列与链式队列--C语言实现
关于队列,因为我自己在平时使用不多,所以在这里直接将队列的两种存储方式放在一起,作为一篇随笔,这两份代码均可直接运行,亲测.注释写的应该也算比较详细了,就不过多的解释了 顺序队列 #include&l ...
- C ~ 链式队列与循环队列
此处的链式与循环队列可以应用于BFS和树的层序遍历.下面是对其结构和基本操作的程序描述. 1.循环队列 解决循环队列的队空和队满的方法: [1].增加一个参数count,用来记录数组中当前 ...
- 数据结构Java实现07----队列:顺序队列&顺序循环队列、链式队列、顺序优先队列
一.队列的概念: 队列(简称作队,Queue)也是一种特殊的线性表,队列的数据元素以及数据元素间的逻辑关系和线性表完全相同,其差别是线性表允许在任意位置插入和删除,而队列只允许在其一端进行插入操作在其 ...
- 队列链式存储 - 设计与实现 - API函数
队列相关基础内容参我的博文:队列顺序存储 - 设计与实现 - API函数 队列也是一种特殊的线性表:可以用线性表链式存储来模拟队列的链式存储. 主要代码: // linkqueue.h // 队列链式 ...
- 循环队列和链式队列(C++实现)
循环队列: 1.循环队列中判断队空的方法是判断front==rear,队满的方法是判断front=(rear+1)%maxSize.(我曾经想过为什么不用一个length表示队长,当length==m ...
随机推荐
- CFR - another java decompiler批量反编译jar文件
jd-gui众所周知,业界公认的反编译必备工具. 笔者目前遇到一个java项目,社区版,想做一个本地化的版本,询问官方,官方说闭源,无奈之下只能反编译了. 面对那么多jar,jd-gui一个个去反编译 ...
- php用get方式传json数据 变成null了
$data = I('param.data'); $data=stripslashes(html_entity_decode($data));//$data为传过去的json字符串
- DNS/BIND in Debian
Debian official document:http://www.debian.org/doc/manuals/network-administrator/ch-bind.html Buildi ...
- 社交类APP原型模板分享——微信
微信是一款社交类的APP应用——聊天软件,支持多人群聊. 交互效果主要有滚动内容界面.选择组件触发按钮状态变化.点击下拉展开列表.点击弹出面板等交互操作. 本原型由国产原型工具-Mockplus制作完 ...
- 5条面经,助你成功拿到UX设计师Offer
为什么成为 UX设计师? 如果你经常逛推酷, 知乎, 设计达人或者一些专业的设计师论坛,博客,你会发现,第一批成为UX设计师的人,其实是误打误撞地落入这个行业的.那时候人们并不清楚UX设计师是什么 ...
- 在命令提示符(cmd)下怎样复制粘贴
我们把鼠标放在面板的上方,右击,界面显示如下: 我们选择“属性”,单击,界面显示如下: 我们点选“快速编辑模式”,再点击“确定”,这样设置就完成了,界面显示如下: 我们在面板中随意选择 ...
- Devexpress VCL Build v2013 vol 14.1.5 发布
What's New in 14.1.5 (VCL Product Line) New Major Features in 14.1 What's New in VCL Products 14.1 ...
- 2018.08.10 atcoder Median Sum(01背包)
传送门 题意简述:输入一个数组an" role="presentation" style="position: relative;">anan. ...
- (并查集)The Suspects --POJ --1611
链接: http://poj.org/problem?id=1611 http://acm.hust.edu.cn/vjudge/contest/view.action?cid=82830#probl ...
- 好用的SHELL小编程
1>判断输入为数字,字符或其他 脚本代码: 检测结果: 2>求平均数: 测试效果: 3>自减输出: 脚本代码: 测试效果: 4>在文件 ...