数据结构之链队列
2015-07-19 17:04
363 查看
4.13 队列的链式存储结构及实现
队列的链式存储结构,其实就是线性表的单链表,只不过它只能尾进头出而已,我们简称为链队列。我们将队头指针指向链队列的头结点,而队尾指针指向终端节点。
头结点 队头 队尾
front a1 an NULL
rear
空队列时,front和rear都指向头结点。
头结点
front NULL
rear
4.13.4 循环队列和链队列
时间上 基本操作都是常数时间,即都为0(1)的,不过循环队列是事先申请好的 空间,使用期间不释放。 而对于链队列,每次申请和释放结点也会存在一些
时间开销。
空间上 循环队列必须有一个固定的长度,所以就有了存储元素个数和空间浪费的 问题。而链队列不存在这个问题,尽管它需要一个指针域,会产生一些空间上
的开销。空间上,链队列更加灵活。
总之,在可以确定队列长度最大值的情况下,建议用循环队列
无法预估队列的长度时,则用链队列。
链队列程序如下所示:
#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>
//定义结点数据类型
typedef struct Node
{
int data;
struct Node *next;
} node,*pnode;
//队列的链表结构
typedef struct Queue
{
pnode front;
pnode rear; //队头队尾指针
} queue,*pqueue;
//函数声明
//构造空队列
void init_queue(pqueue list);
//入队
void en_queue(pqueue list,int val);
//遍历
void traverse(pqueue list);
//出队
bool de_queue(pqueue list,int *val);
//队列为空
bool empty_queue(pqueue list);
int main(void)
{
queue list;
int val;
init_queue(&list);
en_queue(&list,1);
en_queue(&list,2);
en_queue(&list,3);
en_queue(&list,4);
en_queue(&list,5);
en_queue(&list,6);
traverse(&list);
if(de_queue(&list,&val))
{
printf("出队成功,出队的元素是:%d.\n",val);
}
else
{
printf("出队失败!\n");
}
traverse(&list);
return 0;
}
//构造空队列
void init_queue(pqueue list)
{
list->front = (pnode)malloc(sizeof(node));
if(list->front == NULL)
{
printf("分配内存失败!\n");
exit(-1);
}
else
{
list->rear = list->front;
list->front->next = NULL;
list->rear->next = NULL;
}
}
//插入元素val为新的队尾元素 入队
/**********************************************************
front
头结点 a1 a2 a3 a4.............an s
e NULL
rear
**********************************************************/
void en_queue(pqueue list,int val)
{
pnode p;
p = (pnode)malloc(sizeof(node));
if(p == NULL)
{
printf("分配内存失败!\n");
exit(-1);
}
p->data = val;
p->next = NULL;
list->rear->next = p; //把拥有元素e新结点p赋值给原队尾结点的后继
list->rear = p; //把当前的p设置为队尾结点,rear指向p
return ;
}
//遍历输出
void traverse(pqueue list)
{
pnode p;
p = list->front->next;
while(p != NULL)
{
printf("%d ",p->data);
p = p->next;
}
printf("\n");
return ;
}
//队列为空
bool empty_queue(pqueue list)
{
if(list->front == list->rear)
{
return true;
}
else
{
return false;
}
}
//出队
/**************************************************************
出队操作时,就是头结点的后继结点出队,将头结点的后继改为它后面的结点
若链表除过头结点外只剩一个元素时,则需要将rear指向头结点。
**************************************************************/
bool de_queue(pqueue list,int *val)
{
if(empty_queue(list))
{
return false;
}
else
{
pnode p;
p = list->front->next; //头结点不能丢,将欲删除的队头结点暂存给p
*val = p->data; //将欲删除的队头结点的值赋值给e
list->front->next = p->next; //将原队头结点后继p->next赋值给头结点后继
if(list->rear == p) //若队头是队尾,则删除后将rear指向头结点。
{
list->rear = list->front;
}
free(p);
return true;
}
}
队列的链式存储结构,其实就是线性表的单链表,只不过它只能尾进头出而已,我们简称为链队列。我们将队头指针指向链队列的头结点,而队尾指针指向终端节点。
头结点 队头 队尾
front a1 an NULL
rear
空队列时,front和rear都指向头结点。
头结点
front NULL
rear
4.13.4 循环队列和链队列
时间上 基本操作都是常数时间,即都为0(1)的,不过循环队列是事先申请好的 空间,使用期间不释放。 而对于链队列,每次申请和释放结点也会存在一些
时间开销。
空间上 循环队列必须有一个固定的长度,所以就有了存储元素个数和空间浪费的 问题。而链队列不存在这个问题,尽管它需要一个指针域,会产生一些空间上
的开销。空间上,链队列更加灵活。
总之,在可以确定队列长度最大值的情况下,建议用循环队列
无法预估队列的长度时,则用链队列。
链队列程序如下所示:
#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>
//定义结点数据类型
typedef struct Node
{
int data;
struct Node *next;
} node,*pnode;
//队列的链表结构
typedef struct Queue
{
pnode front;
pnode rear; //队头队尾指针
} queue,*pqueue;
//函数声明
//构造空队列
void init_queue(pqueue list);
//入队
void en_queue(pqueue list,int val);
//遍历
void traverse(pqueue list);
//出队
bool de_queue(pqueue list,int *val);
//队列为空
bool empty_queue(pqueue list);
int main(void)
{
queue list;
int val;
init_queue(&list);
en_queue(&list,1);
en_queue(&list,2);
en_queue(&list,3);
en_queue(&list,4);
en_queue(&list,5);
en_queue(&list,6);
traverse(&list);
if(de_queue(&list,&val))
{
printf("出队成功,出队的元素是:%d.\n",val);
}
else
{
printf("出队失败!\n");
}
traverse(&list);
return 0;
}
//构造空队列
void init_queue(pqueue list)
{
list->front = (pnode)malloc(sizeof(node));
if(list->front == NULL)
{
printf("分配内存失败!\n");
exit(-1);
}
else
{
list->rear = list->front;
list->front->next = NULL;
list->rear->next = NULL;
}
}
//插入元素val为新的队尾元素 入队
/**********************************************************
front
头结点 a1 a2 a3 a4.............an s
e NULL
rear
**********************************************************/
void en_queue(pqueue list,int val)
{
pnode p;
p = (pnode)malloc(sizeof(node));
if(p == NULL)
{
printf("分配内存失败!\n");
exit(-1);
}
p->data = val;
p->next = NULL;
list->rear->next = p; //把拥有元素e新结点p赋值给原队尾结点的后继
list->rear = p; //把当前的p设置为队尾结点,rear指向p
return ;
}
//遍历输出
void traverse(pqueue list)
{
pnode p;
p = list->front->next;
while(p != NULL)
{
printf("%d ",p->data);
p = p->next;
}
printf("\n");
return ;
}
//队列为空
bool empty_queue(pqueue list)
{
if(list->front == list->rear)
{
return true;
}
else
{
return false;
}
}
//出队
/**************************************************************
出队操作时,就是头结点的后继结点出队,将头结点的后继改为它后面的结点
若链表除过头结点外只剩一个元素时,则需要将rear指向头结点。
**************************************************************/
bool de_queue(pqueue list,int *val)
{
if(empty_queue(list))
{
return false;
}
else
{
pnode p;
p = list->front->next; //头结点不能丢,将欲删除的队头结点暂存给p
*val = p->data; //将欲删除的队头结点的值赋值给e
list->front->next = p->next; //将原队头结点后继p->next赋值给头结点后继
if(list->rear == p) //若队头是队尾,则删除后将rear指向头结点。
{
list->rear = list->front;
}
free(p);
return true;
}
}
相关文章推荐
- 数据结构之栈
- 数据结构之线性结构的离散存储(循环列表和双向链表)
- 数据结构之线性结构的离散存储(单链表)
- 数据结构之线性结构的顺序存储(数组)
- 数据结构概述
- 数据结构—二叉树的四种遍历
- 数据结构之图(存储结构、遍历)
- 数据结构之图(存储结构、遍历)
- 数据结构和设计模式01(数据结构的基础)
- 求最大子序列的四种算法,数据结构与算法分析(C语言版)第二章
- 数据结构-线性表
- Java数据结构-线性表之单链表LinkedList
- Java数据结构-线性表之顺序表ArrayList
- 数据结构学习总结(四)队列和栈
- 数据结构复习之查找算法的总结回顾
- 教你透彻了解红黑树
- 《大话数据结构》样章试读
- 《大话数据结构》简体中文版勘误
- 《大话数据结构》第9章 排序 9.10 总结回顾
- 《大话数据结构》第9章 排序 9.9 快速排序(下)