您的位置:首页 > 理论基础 > 数据结构算法

数据结构之链队列

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;

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: