一、什么是链队列?

队列的链式存储结构,其实就是线性表的单链表,只不过它只能尾进头出而已,我们把它简称为链队列。为了操作上的方便,我们将队头指针指向链队列的头结点,而队尾指针指向尾结点,如下图所示:

空队列时,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语言)的更多相关文章

  1. 数据结构——链队列(linked queue)

    /* linkedQueue.c */ /* 链队列 */ #include <stdio.h> #include <stdlib.h> #include <stdboo ...

  2. 数据结构 - 链栈的实行(C语言)

    数据结构-链栈的实现 1 链栈的定义 现在来看看栈的链式存储结构,简称为链栈. 想想看栈只是栈顶来做插入和删除操作,栈顶放在链表的头部还是尾部呢?由于单链表有头指针,而栈顶指针也是必须的,那干吗不让它 ...

  3. 数据结构 - 顺序队列的实行(C语言)

    数据结构-顺序队列的实现 1 顺序队列的定义 线性表有顺序存储和链式存储,队列作为一种特殊的线性表,也同样存在这两种存储方式.我们先来看队列的顺序存储结构. 队列的顺序储存结构:用数组存储队列,为了避 ...

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

    1.数据结构-循环队列的实现-C语言 #define MAXSIZE 100 //循环队列的存储结构 typedef struct { int* base; //基地址 int _front; //头 ...

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

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

  6. 【Java】 大话数据结构(7) 循环队列和链队列

    本文根据<大话数据结构>一书,实现了Java版的循环队列.链队列. 队列:只允许在一端进行插入操作,而在另一端进行删除操作的线性表. 1.循环队列 队列的顺序储存结构:用数组存储队列,引入 ...

  7. javascript实现数据结构与算法系列:队列 -- 链队列和循环队列实现及示例

    1 队列的基本概念 队列(Queue):也是运算受限的线性表.是一种先进先出(First In First Out ,简称FIFO)的线性表.只允许在表的一端进行插入,而在另一端进行删除. 队首(fr ...

  8. java与数据结构(8)---java实现链队列

    链队列 实际上就是单链表,只是规定了删除在队头进行,添加在队尾进行. 链队列代码结构 package list.queue; public interface Queuable<T>; p ...

  9. C语言实现链队列的初始化&进队&出队

    /*链表实现队列的一系列操作*/ #include<stdio.h> #include<stdlib.h> #define OK 1 #define ERROR 0 typed ...

随机推荐

  1. centos 安装python2.7

    安装pip sudo yum -y install epel-release sudo yum -y install python-pip 下载解压Python-2.7.3 #wget http:// ...

  2. SqlServer 经常使用分页方法总结

    SqlServer 经常使用分页方法总结 以下演示样例总结了,SqlServer数据库 经常使用分页方法,仅供学习參考 A. 使用 RowNumber 和 Between And 组合分页: /*** ...

  3. js 终止执行的实现方法

    终止JS运行有如下几种可能: 1.终止函数的运行的方式有两种 (1)在函数中使用return,则当遇到return时,函数终止执行,控制权继续向下运行 (2)在函数中使用try-catch异常处理,需 ...

  4. MySQL基础笔记(五) 视图

    一.什么是视图 视图是一个虚拟表.也就是说,视图在外观和行为上都类似于表,但它不需要实际的物理存储,只保存了视图定义(查询语句). 视图由select查询所定义 -- 当创建一个视图时,实际上是在数据 ...

  5. qt之旅-1纯手写Qt界面

    通过手写qt代码来认识qt程序的构成,以及特性.设计一个查找对话框.以下是设计过程 1 新建一个empty qt project 2 配置pro文件 HEADERS += \ Find.h QT += ...

  6. web 开发之js---ajax 中的两种返回状态 xmlhttp.status和 xmlhttp.readyState

    (1)xmlhttp.status xmlHttp.status的值(HTTP状态表)0**:未被始化 1**:请求收到,继续处理 2**:操作成功收到,分析.接受 3**:完成此请求必须进一步处理 ...

  7. Linux的进程优先级NI和PR到底有什么区别

    Linux的进程优先级NI和PR到底有什么区别 - 51CTO.COM http://os.51cto.com/art/201605/511559.htm

  8. 【剑指offer】面试题42:单词翻转顺序&左右旋转字符串

    这里尽可能的不去用语言本身提供的函数. 将string逆置 def reverse(string): #return string[::-1] reversedStr = '' for i in xr ...

  9. XMU 1613 刘备闯三国之三顾茅庐(一) 【并查集】

    1613: 刘备闯三国之三顾茅庐(一) Time Limit: 1000 MS  Memory Limit: 128 MBSubmit: 99  Solved: 29[Submit][Status][ ...

  10. VA市场高烧已退,逐渐降温

    本周市场国产VA报价在175元/公斤左右,较上周滑落.因前期停报的厂家均已报价,个别国产厂家报价较低,各厂家间报价价差较大,彰显不同态度.国内厂家供应依然偏紧,但较前期已缓解.中小饲料企业库存偏低,近 ...