数据结构 - 链队列的实行(C语言)
一、什么是链队列?
队列的链式存储结构,其实就是线性表的单链表,只不过它只能尾进头出而已,我们把它简称为链队列。为了操作上的方便,我们将队头指针指向链队列的头结点,而队尾指针指向尾结点,如下图所示:

空队列时,front和rear都指向头结点,如下图所示。

链队列的结构为:
typedef int QElemType; /* QElemType类型根据实际情况而定,这里假设为int */
/* 结点结构 */
typedef struct QNode
{
	ElemType data;
	struct QNode *next;
}QNode;
/* 队列的链表结构 */
typedef struct
{
	QNode *front; // 队头指针
	QNode *rear; // 队尾指针
}LinkQueue;
二、基本操作
2.1 初始化操作
实现代码如下:
// 初始化链队列操作
Status initQueue(LinkQueue *Q)
{
	Q->front = Q->rear = (Node *)malloc(sizeof(Node));
	if (!Q->front)
		return FALSE;
	Q->front->next = NULL;
	return TRUE;
}
2.1 入队操作
人队操作时,其实就是在链表尾部插入结点,如下图所示:

实现代码如下:
// 入队操作
Status enQueue(LinkQueue *Q, ElemType e)
{
	Node *s = (Node *)malloc(sizeof(Node));
	if (!s)
		return FALSE;
	s->data = e;
	s->next = NULL;
	Q->rear->next = s;	// 把拥有元素e的新结点s赋值给原队尾结点的后继
	Q->rear = s; // 把当前的s设置为队尾结点,rear指向s
	return TRUE;
}
2.3 出队操作
出队操作时,就是头结点的后继结点出队,将头结点的后继改为它后面的结点,若链表除头结点外只剩一个元素时,则需将rear指向头结点,如下图所示:

实现代码如下:
// 出队操作
Status deQueue(LinkQueue *Q, ElemType *e)
{
	Node *p;
	if (Q->front == Q->rear)
		return FALSE;
	p = Q->front->next; // 将欲删除的队头结点暂存给p,见图中①
	*e = p->data; // 将欲删除的队头结点的值赋值给e
	Q->front->next = p->next; // 将原队头结点的后继p->next赋值给头结点后继,见图中②
	if (Q->rear == p) // 若队头就是队尾,则删除后将rear指向头结点,见图中③
		Q->rear = Q->front;
	free(p);
	return TRUE;
}
2.4 遍历操作
实现代码如下:
// 遍历队列操作
Status tarverseQueue(const LinkQueue Q)
{
	Node *p;
	p = Q.front->next;
	while (p)
	{
		printf("%d ", p->data);
		p = p->next;
	}
	printf("\n");
	return TRUE;
}
三、完整程序
#include <stdio.h>
#include <stdlib.h>    
#define TRUE 1
#define FALSE 0
#define MAXSIZE 20 /* 存储空间初始分配量 */
typedef int Status;
typedef int ElemType; /* ElemType类型根据实际情况而定,这里假设为int */
/* 结点结构 */
typedef struct Node
{
	ElemType data;
	struct Node *next;
}Node;
/* 队列的链表结构 */
typedef struct
{
	Node *front; // 队头指针
	Node *rear; // 队尾指针
}LinkQueue;
Status initQueue(LinkQueue *Q); // 初始化链队列操作
Status enQueue(LinkQueue *Q, ElemType e); // 入队操作
Status deQueue(LinkQueue *Q, ElemType *e); // 出队操作
Status tarverseQueue(const LinkQueue Q); // 遍历队列操作
Status destroyQueue(LinkQueue *Q); // 销毁队列操作
Status clearQueue(LinkQueue *Q); // 清空队列操作
Status isEmpty(const LinkQueue Q); // 判断是否为空队列
Status getHead(const LinkQueue Q, ElemType *e); // 获得队头元素
int getLength(const LinkQueue Q); // 获得队列的长度
// 初始化链队列操作
Status initQueue(LinkQueue *Q)
{
	Q->front = Q->rear = (Node *)malloc(sizeof(Node));
	if (!Q->front)
		return FALSE;
	Q->front->next = NULL;
	return TRUE;
}
// 入队操作
Status enQueue(LinkQueue *Q, ElemType e)
{
	Node *s = (Node *)malloc(sizeof(Node));
	if (!s)
		return FALSE;
	s->data = e;
	s->next = NULL;
	Q->rear->next = s;	// 把拥有元素e的新结点s赋值给原队尾结点的后继,见图中①
	Q->rear = s; // 把当前的s设置为队尾结点,rear指向s,见图中②
	return TRUE;
}
// 出队操作
Status deQueue(LinkQueue *Q, ElemType *e)
{
	Node *p;
	if (Q->front == Q->rear)
		return FALSE;
	p = Q->front->next; // 将欲删除的队头结点暂存给p,见图中①
	*e = p->data; // 将欲删除的队头结点的值赋值给e
	Q->front->next = p->next; // 将原队头结点的后继p->next赋值给头结点后继,见图中②
	if (Q->rear == p) // 若队头就是队尾,则删除后将rear指向头结点,见图中③
		Q->rear = Q->front;
	free(p);
	return TRUE;
}
// 遍历队列操作
Status tarverseQueue(const LinkQueue Q)
{
	Node *p;
	p = Q.front->next;
	while (p)
	{
		printf("%d ", p->data);
		p = p->next;
	}
	printf("\n");
	return TRUE;
}
// 销毁队列操作
Status destroyQueue(LinkQueue *Q)
{
	while (Q->front)
	{
		Q->rear = Q->front->next;
		free(Q->front);
		Q->front = Q->rear;
	}
	return TRUE;
}
// 清空队列操作
Status clearQueue(LinkQueue *Q)
{
	Node *p;
	Node *q;
	Q->rear = Q->front;
	p = Q->front->next;
	Q->front->next = NULL;
	while (p)
	{
		q = p;
		p = p->next;
		free(q);
	}
	return TRUE;
}
// 判断是否为空队列
Status isEmpty(const LinkQueue Q)
{
	return Q.front == Q.rear ? TRUE : FALSE;
}
// 获得队头元素
Status getHead(const LinkQueue Q, ElemType *e)
{
	Node *p;
	if (Q.front == Q.rear)
		return FALSE;
	p = Q.front->next;
	*e = p->data;
	return TRUE;
}
// 获得队列的长度
int getLength(const LinkQueue Q)
{
	int i = 0;
	Node *p;
	p = Q.front;
	while (Q.rear != p)
	{
		i++;
		p = p->next;
	}
	return i;
}
int main()
{
	LinkQueue Q;
	// 初始化队列
	initQueue(&Q);
	// 入队操作
	for (int i = 0; i < 4; i++)
		enQueue(&Q, i);
	printf("入队操作(0、1、2、3)! \n\n");
	// 出队操作
	ElemType d;
	deQueue(&Q, &d);
	printf("删除的元素是%d \n\n", d);
	// 遍历队列
	printf("遍历队列: ");
	tarverseQueue(Q);
	printf("\n");
	// 判断是否为空队列
	printf("现在队列空否? %u (1:空 0:否)\n\n", isEmpty(Q));
	// 获得队列的长度
	printf("队列长度为: %d \n\n", getLength(Q));
	// 获得队头元素
	getHead(Q, &d);
	printf("队头元素是%d \n\n", d);
	return 0;
}
输出结果如下图所示:

参考:
《大话数据结构 - 第4章》 栈与队列
数据结构 - 链队列的实行(C语言)的更多相关文章
- 数据结构——链队列(linked queue)
		/* linkedQueue.c */ /* 链队列 */ #include <stdio.h> #include <stdlib.h> #include <stdboo ... 
- 数据结构 - 链栈的实行(C语言)
		数据结构-链栈的实现 1 链栈的定义 现在来看看栈的链式存储结构,简称为链栈. 想想看栈只是栈顶来做插入和删除操作,栈顶放在链表的头部还是尾部呢?由于单链表有头指针,而栈顶指针也是必须的,那干吗不让它 ... 
- 数据结构 - 顺序队列的实行(C语言)
		数据结构-顺序队列的实现 1 顺序队列的定义 线性表有顺序存储和链式存储,队列作为一种特殊的线性表,也同样存在这两种存储方式.我们先来看队列的顺序存储结构. 队列的顺序储存结构:用数组存储队列,为了避 ... 
- C语言数据结构-循环队列的实现-初始化、销毁、清空、长度、队列头元素、插入、删除、显示操作
		1.数据结构-循环队列的实现-C语言 #define MAXSIZE 100 //循环队列的存储结构 typedef struct { int* base; //基地址 int _front; //头 ... 
- C语言数据结构-链式队列的实现-初始化、销毁、清空、长度、队列头元素、插入、删除、显示操作
		1.数据结构-链式队列的实现-C语言 typedef struct QNode { int data; struct QNode *next; }QNode,*QueuePtr; typedef st ... 
- 【Java】 大话数据结构(7) 循环队列和链队列
		本文根据<大话数据结构>一书,实现了Java版的循环队列.链队列. 队列:只允许在一端进行插入操作,而在另一端进行删除操作的线性表. 1.循环队列 队列的顺序储存结构:用数组存储队列,引入 ... 
- javascript实现数据结构与算法系列:队列 -- 链队列和循环队列实现及示例
		1 队列的基本概念 队列(Queue):也是运算受限的线性表.是一种先进先出(First In First Out ,简称FIFO)的线性表.只允许在表的一端进行插入,而在另一端进行删除. 队首(fr ... 
- java与数据结构(8)---java实现链队列
		链队列 实际上就是单链表,只是规定了删除在队头进行,添加在队尾进行. 链队列代码结构 package list.queue; public interface Queuable<T>; p ... 
- C语言实现链队列的初始化&进队&出队
		/*链表实现队列的一系列操作*/ #include<stdio.h> #include<stdlib.h> #define OK 1 #define ERROR 0 typed ... 
随机推荐
- win8,win10里面内置的IE浏览器网银无法输入密码
			win8,win10里面内置的IE浏览器网银无法输入密码,安装控件也没效果,部分网银直接导致IE崩溃,只需要简单设置即可解决. 方法/步骤 1 打开IE浏览器,点击右上角的小齿轮图标,在下拉菜单中 ... 
- delphi 的结构体对齐关键字
			Align fields (Delphi) Go Up to Delphi Compiler Directives (List) Index Type Switch Syntax {$A+}, { ... 
- windows下 sqlplus / as sysdba 报ora-12560的终极解决方法
			windows下 sqlplus / as sysdba 报ora-12560的终极解决方法 本文是原创文章.转载请注明出处:http://blog.csdn.net/msdnchina/articl ... 
- activiti自己定义流程之自己定义表单(二):创建表单
			注:环境配置:activiti自己定义流程之自己定义表单(一):环境配置 在上一节自己定义表单环境搭建好以后,我就正式開始尝试自己创建表单,在后台的处理就比較常规,主要是针对ueditor插件的功能在 ... 
- 【ios系列】-数据储存
			第一:plist属性列表 适用对象:仅仅是Foundation框架自带的一些类比如:NString\NSarry\NSDictionary\NSset\NSnumber\NSdata 使用: 1:调用 ... 
- spring的PROPAGATION_REQUIRES_NEW事务,下列说法正确的是(D)
			A:内部事务回滚会导致外部事务回滚 B:内部事务回滚了,外部事务仍可以提交 C:外部事务回滚了,内部事务也跟着回滚 D:外部事务回滚了,内部事务仍可以提交 PROPAGATION_REQUIRES_N ... 
- pymssql.connect(server='.', user='', password='', database='', timeout=0, login_timeout=60, charset='UTF-8', as_dict=False, host='', appname=None, port='1433', conn_properties, autocommit=False, tds_
			http://pymssql.org/en/stable/ref/pymssql.html """ This is an effort to convert the py ... 
- GET 与 POST 的理解
			1 HTTP请求 超文本传输协议(HTTP)的设计目的是保证客户机与服务器之间的通信. HTTP 的工作方式是客户机与服务器之间的请求-应答协议. 比如,客户端(浏览器) ... 
- windows安装SVN服务器并设置开机启动
			1.安装SVN服务器,到http://subversion.apache.org/packages.html上下载windows版的SVN,并安装,在命令行下运行svn命令,如下所以,则svn服务器安 ... 
- apache配置访问限制
			1.禁止访问某些文件/目录 增加Files选项来控制,比如要不允许访问 .txt扩展名的文件,保护php类库: <Files ~ "\.txt$"> Order all ... 
