链式队列----用链表实现,链式队列就是一个操作受限的单向链表,如果读者了解单向链表的建立过程,那理解链式队列就很容易了,先回顾一下单向链表的建立过程

(不熟悉单向链表的可以先看看另一片随笔,再回来看链式队列理解起来更容易☺链表(单向链表的建立、删除、插入、打印)

单向链表

单向链表节点的组成部分

 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语言的更多相关文章

  1. C语言 队列 链式结构 实现

    一个C语言链式结构实现的队列 mQueue (GCC编译). /** * @brief C语言实现的链式队列 * @author wid * @date 2013-10-31 * * @note 若代 ...

  2. C语言数据结构-链式队列的实现-初始化、销毁、清空、长度、队列头元素、插入、删除、显示操作

    1.数据结构-链式队列的实现-C语言 typedef struct QNode { int data; struct QNode *next; }QNode,*QueuePtr; typedef st ...

  3. C语言实现链式队列

    链式队列,简称"链队列",即使用链表实现的队列存储结构. 链式队列的实现思想同顺序队列类似,只需创建两个指针(命名为 top 和 rear)分别指向链表中队列的队头元素和队尾元素, ...

  4. C语言链表全操作(增,删,改,查,逆序,递增排序,递减排序,链式队列,链式栈)

    一,数据结构——链表全操作: 链表形式: 其中,每个节点(Node)是一个结构体,这个结构体包含数据域,指针域,数据域用来存放数据,指针域则用来指向下一个节点: 特别说明:对于单链表,每个节点(Nod ...

  5. 顺序队列与链式队列--C语言实现

    关于队列,因为我自己在平时使用不多,所以在这里直接将队列的两种存储方式放在一起,作为一篇随笔,这两份代码均可直接运行,亲测.注释写的应该也算比较详细了,就不过多的解释了 顺序队列 #include&l ...

  6. C ~ 链式队列与循环队列

          此处的链式与循环队列可以应用于BFS和树的层序遍历.下面是对其结构和基本操作的程序描述. 1.循环队列 解决循环队列的队空和队满的方法: [1].增加一个参数count,用来记录数组中当前 ...

  7. 数据结构Java实现07----队列:顺序队列&顺序循环队列、链式队列、顺序优先队列

    一.队列的概念: 队列(简称作队,Queue)也是一种特殊的线性表,队列的数据元素以及数据元素间的逻辑关系和线性表完全相同,其差别是线性表允许在任意位置插入和删除,而队列只允许在其一端进行插入操作在其 ...

  8. 队列链式存储 - 设计与实现 - API函数

    队列相关基础内容参我的博文:队列顺序存储 - 设计与实现 - API函数 队列也是一种特殊的线性表:可以用线性表链式存储来模拟队列的链式存储. 主要代码: // linkqueue.h // 队列链式 ...

  9. 循环队列和链式队列(C++实现)

    循环队列: 1.循环队列中判断队空的方法是判断front==rear,队满的方法是判断front=(rear+1)%maxSize.(我曾经想过为什么不用一个length表示队长,当length==m ...

随机推荐

  1. DNA motif 搜索算法总结

    DNA motif 搜索算法总结 2011-09-15 ~ ADMIN 翻译自:A survey of DNA motif finding algorithms, Modan K Das et. al ...

  2. OSGi 系列(六)之服务的使用

    OSGi 系列(六)之服务的使用 1. 为什么使用服务 降低服务提供者和服务使用者直接的耦合,这样更容易重用组件 隐藏了服务的实现细节 支持多个服务的实现.这样你可以互换这实现 2. 服务的使用 2. ...

  3. oracle 表分区例子

    oracle表分区详解-一步一步教你oracle分区表详解   .创建三个不同的表空间,模拟在不同磁盘上的保存不同范围的数据    create tablespace test01 datafile ...

  4. centos6.5 redis 安装配置及java调用

    1.安装gcc 执行命令  yum install gcc 2. 安装ruby环境 yum install ruby yum install rubygems gem install redis 下载 ...

  5. sci-hub 下载地址更新

    #  2017-12-14 可用 http://www.sci-hub.tw/ 文献共享平台

  6. c++中如何定义编译期间常量,即这个常量可以用于定义数组下标

    在c++中,类里面的成员变量不仅仅可以被const修饰,还可以被static const修饰,此时一个内建类型(如int ,char ,long等)的static const 可以看做是一个编译期间的 ...

  7. Check time of different search methods

    https://github.com/Premiumlab/Python-for-Algorithms--Data-Structures--and-Interviews/blob/master/Moc ...

  8. 2018.08.04 洛谷P3380 【模板】二逼平衡树(树套树)

    传送门 技不如人,写的权值线段树套线段树在bzoj上无论如何都卡不过空间. 这是一道树套树简单题,感觉没什么好说的. 直接权值线段树套平衡树就行了. 代码: #include<bits/stdc ...

  9. [MySQL]变更数据库字符集

    my.cnf [mysqld] character-set-server=utf8 [mysqld_safe] default-character-set=utf8 -- 创建数据库时,设置数据库的编 ...

  10. 基础的linux学习

    学习了这几个命令分享一下: 文本文件内搜索数据 grep -n -e pattern1 -e pattern2 file1 -n 搜索到的数据显示行号展示 -e pattern1 多个匹配模式下可以通 ...