队列的顺序存储结构和链式存储结构

队列(queue)是只允许在一端进行插入操作,而在另一端进行删除操作的线性表(在队尾进行插入操作,在对头进行删除操作)。

与栈相反,队列是一种先进先出(First In First Out, FIFO)的线性表。

与栈相同的是,队列也是一种重要的线性结构,实现一个队列同样需要顺序表或链表作为基础。

队列的链式存储结构

队列既可以用链表实现,也可以用顺序表实现。跟栈相反的是,栈一般我们用顺序表来实现,而队列我们常用链表来实现,简称为链队列。

typedef struct QNode {
ElemType data;
struct QNode *next;
} QNode, *QueuePrt;</span>
<span style="font-family:KaiTi_GB2312;font-size:18px;"> typedef struct {
QueuePrt  front; //队头
QueuePrt  rear; //队尾指针
} LinkQueue;

将队头指针指向链队列的头结点,而队尾指针指向终端结点。(注:头结点不是必要的,但为了方便操作,我们加上了。)

队列的链式存储结构

空队列时,front和rear都指向头结点。

创建一个队列

创建一个队列要完成两个任务:一是在内存中创建一个头结点,二是将队列的头指针和尾指针都指向这个生成的头结点,因为此时是空队列。

initQueue(LinkQueue *q){
q->front=q->rear=(QueuePtr)malloc(sizeof(QNode));
if( !q->front )
exit(0);
q->front->next = NULL;
}

入队列操作

//入队列操作
InsertQueue(LinkQueue *q, ElemType e){
QueuePtr p;

p = (QueuePtr)malloc(sizeof(QNode));
if( p == NULL )
exit(0);

p->data = e;
p->next = NULL;
q->rear->next = p;
q->rear = p;
}

出队列操作

出队列操作是将队列中的第一个元素移出,队头指针不发生改变,改变头结点的next指针即可。

如果原队列只有一个元素,那么我们就应该处理一下队尾指针。

出队列操作

DeleteQueue(LinkQueue *q, ELemType *e){

QueuePtr p;

if( q->front == q->rear )
return;

p = q->front->next;
*e = p->data;
q->front->next = p->next;

if( q->rear == p )
q->rear = q->front;

free(p);
}

销毁一个队列

由于链队列建立在内存的动态区,因此当一个队列不再有用时应当把它及时销毁掉,以免过多地占用内存空间。

DestroyQueue(LinkQueue *q){
while( q->front )
{
q->rear = q->front->next;
free( q->front );
q->front = q->rear;
}
}

队列的顺序存储结构

我们假设一个队列有n个元素,则顺序存储的队列需建立一个大于n的存储单元,并把队列的所有元素存储在数组的前n个单元,数组下标为0的一端则是队头。

入队列操作其实就是在队尾追加一个元素,不需要任何移动,时间复杂度为O(1)。

出队列则不同,因为我们已经架设下标为0的位置是队列的队头,因此每次出队列操作所有元素都要向前移动。

在现实中也是如此,一群人在排队买火车票,前边的人买好了离开,后面的人就要全部向前一步补上空位。

可是我们研究数据结构和算法的一个根本目的就是要想方设法提高我们的程序的效率,按刚才的方式,出队列的时间复杂度是O(n),效率大打折扣!

如果我们不去限制队头一定要在下标为0的位置,那么出队列的操作就不需要移动全体元素。

但是这样也会出现一些问题,例如按下边的情形继续入队列,就会出现数组越界的错误。

可事实上我们有0和1两个下标还空着,这叫假溢出。

循环队列(在实际中应用相当广泛)

我们再想想,要解决假溢出的办法就是如果后面满了,就再从头开始,也就是头尾相接的循环。

循环队列它的容量是固定的,并且它的队头和队尾指针都可以随着元素入、出队列而发生改变,这样循环队列逻辑上就好像是一个环形存储空间。

但要注意的是,在实际的内存当中,不可能有真正的环形存储区,我们只是用顺序表模拟出来的逻辑上的循环。

于是我们发觉了,似乎循环队列的实现只需要灵活改变front和rear指针即可。

也就是让front或rear指针不断加1,即使超出了地址范围,也会自动从头开始。我们可以采取取模运算处理:(这个运算在数据结构中特别常见,也特别重要!)

(rear+1) % QueueSize

(front+1) % QueueSize

取模就是取余数的意思,他取到的值永远不会大于除数。

定义一个循环队列

#define MAXSIZE 100
typedef struct{
ElemType *base; // 用于存放内存分配基地址,这里你也可以用数组存放
int front;
int rear;
}
初始化一个循环队列
initQueue(cycleQueue *q){
q->base = (ElemType *) malloc (MAXSIZE * sizeof(ElemType));
if( !q->base )
   exit(0);
q->front = q->rear = 0;
}
入队列操作
InsertQueue(cycleQueue *q, ElemType e){
if( (q->rear+1)%MAXSIZE == q->front )
return; // 队列已满

q->base[q->rear] = e;
q->rear = (q->rear+1) % MAXSIZE;
}
出队列操作
DeleteQueue(cycleQueue *q, ElemType *e){
if( q->front == q->rear )
return ; // 队列为空

*e = q->base[q->front];
q->front = (q->front+1) % MAXSIZE;
}
时间: 2024-08-08 00:54:49

队列的顺序存储结构和链式存储结构的相关文章

线性表的顺序存储结构和链式存储结构

前言 上一篇<栈>中提到了栈的顺序存储结构和链式存储结构,现在就对此做个简单的比较.因为栈是线性表的一种,顺序存储结构和链式存储结构实际是线性表的两种存储方式.而栈和队列都是两种重要的线性表结构.所以本文标题直接为线性表的顺序存储结构和链式存储结构. 开始比较两种不同的存储方式 一.顺序存储结构(也可称为顺序表) 顺序表的特点是逻辑上相邻的数据元素,物理存储位置也相邻,并且,顺序表的存储空间需要预先分配. 优点: (1)方法简单,各种高级语言中都有数组,容易实现. (2)不用为表示节点间的逻辑

简要比较线性表的顺序存储结构和链式存储结构

我们分别从存储分配方式.时间性能.空间性能三方面来做对比. 存储分配方式 顺序存储结构用一段连续的存储单元依次存储线性表的数据元素. 单链表采用链式存储结构,用一组任意的存储单元存放线性表的元素. 时间性能 <1>查找 顺序存储结构O(1) 单链表O(n) <2>插入和删除 顺序存储结构需要平均移动表长一半的元素,时间为O(n) 单链表在计算出某位置的指针后,插入和删除时间仅为O(1) 空间性能 顺序存储结构需要预分配存储空间,分大了,容易造成空间浪费,分小了,容易发生溢出. 单链

顺序存储结构与链式存储结构

上一篇博客简单讲述了一下两种结构的概念这一篇博客主要想讲述一下他们之间的区别 顺序存储结构与链式存储结构的优缺点 顺序存储结构 概念官方一点来说可以使用百度百科的介绍:顺序存储结构是存储结构类型中的一种,该结构是把逻辑上相邻的结点存储在物理位置上相邻的存储单元中,结点之间的逻辑关系由存储单元的邻接关系来体现. 当然不得不说一般这种官方的解释都是不太适合我的,所以用小甲鱼的方式来说这个概念的话,简单来说就是,用一段连续的地址存放数据元素,数据间的逻辑关系和物理关系相同. 优点1:存储密度大,空间利

java资料——顺序存储结构和链式存储结构(转)

顺序存储结构 主要优点 节省存储空间,随机存取表中元素 缺    点 插入和删除操作需要移动元素 在计算机中用一组地址连续的存储单元依次存储线性表的各个数据元素,称作线性表的顺序存储结构. 顺序存储结构是存储结构类型中的一种,该结构是把逻辑上相邻的节点存储在物理位置上相邻的存储单元中,结点之间的逻辑关系由存储单元的邻接关系来体现.由此得到的存储结构为顺序存储结构,通常顺序存储结构是借助于计算机程序设计语言(例如c/c++)的数组来描述的. 顺序存储结构的主要优点是节省存储空间,因为分配给数据的存

数据结构第六篇——顺序存储结构与链式存储结构的特点

?注:未经博主同意,不得转载. 两者特点: 顺序表的特点是逻辑上相邻的数据元素,物理存储位置也相邻,并且,顺序表的存储空间需要预先分配. 它的优点: (1)方法简单,各种高级语言中都有数组,容易实现. (2)不用为表示节点间的逻辑关系而增加额外的存储开销. (3)顺序表具有按元素序号随机访问的特点. 缺点: (1)在顺序表中做插入.删除操作时,平均移动表中的一半元素,因此对n较大的顺序表效率低. (2)需要预先分配足够大的存储空间,估计过大,可能会导致顺序表后部大量闲置:预先分配过小,又会造成溢

线性表的顺序存储结构和链式存储结构的比较

一:顺序表的特点是逻辑上相邻的数据元素,物理存储位置也相邻,并且,顺序表的存储空间需要预先分配. 它的优点是: (1)方法简单,各种高级语言中都有数组,容易实现. (2)不用为表示节点间的逻辑关系而增加额外的存储开销. (3)顺序表具有按元素序号随机访问的特点. 缺点: (1)在顺序表中做插入.删除操作时,平均移动表中的一半元素,因此对n较大的顺序表效率低. (2)需要预先分配足够大的存储空间,估计过大,可能会导致顺序表后部大量闲置:预先分配过小,又会造成溢出. 二.在链表中逻辑上相邻的数据元素

顺序存储结构与链式存储结构的比较

一:顺序表的特点是逻辑上相邻的数据元素,物理存储位置也相邻,并且,顺序表的存储空间需要预先分配. 它的优点是: (1)方法简单,各种高级语言中都有数组,容易实现. (2)不用为表示节点间的逻辑关系而增加额外的存储开销. (3)顺序表具有按元素序号随机访问的特点. 缺点: (1)在顺序表中做插入.删除操作时,平均移动表中的一半元素,因此对n较大的顺序表效率低. (2)需要预先分配足够大的存储空间,估计过大,可能会导致顺序表后部大量闲置:预先分配过小,又会造成溢出. 二.在链表中逻辑上相邻的数据元素

顺序存储结构和链式存储结构

顺序存储结构特点:数据元素的存储对应一块连续的存储空间,数据元素之间的前驱和后续关系通过数据元素在存储器的相对位置来反映. 链式存储结构特点:数据元素的存储对应的是不连续的存储空间,每个存储节点对应一个需要存储的元素,,元素之间的逻辑关系通过存储节点之间的链接关系反映出来. java中是以一维数组和对象的引用的基础上去讨论和实现数据的存储结构. 线性表和数组的逻辑结构是不一样的:线性表是数据元素之间具有1对1的线性关系的数据元素的集合:而数组是一组数据元素到数据下标的一一映射.线性表是一种抽象数

数据结构之线性表(链式存储结构)

线性表的实现分顺序存储结构和链式存储结构 上一节我们主要介绍了顺序存储结构,在最后我们还分别总结了顺序存储结构的优缺点, 对于顺序结构的缺点,我们有没有什么好的解决方法呢? 我们今天要介绍的线性表的链式存储结构就可以很好的解决顺序结构的缺点,一起来看. 顺序结构最大的缺点就是在进行插入和删除操作的时候,如果插入位置不理想,那么我们需要移动大量的元素,那产生这一问题的原因是什么呢? 仔细分析后,我们可以发现在顺序存储结构中,他们相邻的元素的存储位置也是相邻的,我们在申请内存的的时候,是一次性申请一