栈和队列数据结构的特点是什么

栈和队列数据结构的特点是什么,第1张

1队列先进先出,栈先进后出。

2对插入和删除 *** 作的"限定"。

栈是限定只能在表的一端进行插入和删除 *** 作的线性表。 队列是限定只能在表的一端进行插入和在另一端进行删除 *** 作的线性表。

从"数据结构"的角度看,它们都是线性结构,即数据元素之间的关系相同。但它们是完全不同的数据类型。除了它们各自的基本 *** 作集不同外,主要区别是对插入和删除 *** 作的"限定"。

栈和队列是在程序设计中被广泛使用的两种线性数据结构,它们的特点在于基本 *** 作的特殊性,栈必须按"后进先出"的规则进行 *** 作,而队列必须按"先进先出"的规则进行 *** 作。和线性表相比,它们的插入和删除 *** 作受更多的约束和限定,故又称为限定性的线性表结构。

3遍历数据速度不同。栈只能从头部取数据

也就最先放入的需要遍历整个栈最后才能取出来,而且在遍历数据的时候还得为数据开辟临时空间,保持数据在遍历前的一致性队列怎不同,他基于地址指针进行遍历,而且可以从头或尾部开始遍历,但不能同时遍历,无需开辟临时空间,因为在遍历的过程中不影像数据结构,速度要快的多

栈(Stack)是限定只能在表的一端进行插入和删除 *** 作的线性表。

队列(Queue)是限定只能在表的一端进行插入和在另一端进行删除 *** 作的线性表。

从"数据结构"的角度看,它们都是线性结构,即数据元素之间的关系相同。但它们是完全不同的数据类型。除了它们各自的基本 *** 作集不同外,主要区别是对插入和删除 *** 作的"限定"。

栈和队列是在程序设计中被广泛使用的两种线性数据结构,它们的特点在于基本 *** 作的特殊性,栈必须按"后进先出"的规则进行 *** 作,而队列必须按"先进先出"的规则进行 *** 作。和线性表相比,它们的插入和删除 *** 作受更多的约束和限定,故又称为限定性的线性表结构。可将线性表和栈及队列的插入和删除 *** 作对比如下:

Insert(L,n+1,x)

Delete(L,n)

而栈只允许在表尾一端进行插入和删除

队列

Insert(L,n+1,x)

Delete(L,1)

队列只允许在表尾一端进行插入,在表头一端进行删除

队列和栈一样,也是一种 *** 作受一定规则限制的数据结构。队列简单理解就是平常生活中的排队。队列在结构上分为队头和队尾,只能在队头执行出队 *** 作,在队尾执行入队 *** 作。队列的这种结构其实就类似于我们现实世界中的排队,队伍只能从前往后排,新来的排在队尾,排在队伍最前面的可以最先出队,队列实际上就是一种符合“先进先出”规则的顺序集合。

和栈的结构不同的是,队列的两头都开口,而且数据元素只能从队尾入队,从队头出队。数据元素A首先入队,接着是B和C入队,根据“先进先出”的规则,首先出队的是数据元素A,接着是B和C。队列的这种结构在程序中可以控制一些事务性的 *** 作,例如一件事务包括几个步骤,而且这几个步骤有严格的先后顺序,即必须先完成前面的步骤才能进行后面的步骤。当遇到这种情况时,我们就可以考虑使用队列。队列可以保证一个 *** 作的原子性和顺序性,所以在处理一些事务性的 *** 作时常用到队列结构。

传智播客入学时的基础课程讲解过。

队列 一种特殊的 线性表 ,也是常见的一种数据类型。特殊之处在于它只能在表的前端(front)进行删除,而在表的后端(rear)进行插入 *** 作。进行插入 *** 作的端称为 队尾 ,进行删除 *** 作的端称为 队头

队列 又称为先进先出(FIFO—first in first out)线性表。

线性表 分为 顺序存储 链式存储 ,栈是线性表,所以也有这两种存储方式。同样,队列作为一种特殊的线性表,也同样存在这两种存储方式。

顾名思义,顺序存储采用数组的方式,而链式存储采用链表的方式。

顺序存储的队列 又分为 顺序队列 循环队列

首选说一下顺序队列的坏话,顺序队列在 入队列 的时候可以保持O(1)的时间复杂度,而在 出队列 的时候队头后边的元素需要依次往前移动,以保证队头不为空,时间复杂度就变成了O(n);

为什么出队列时一定要全部移动呢,那么我们是否可以解决 出队列 所带来的问题呢,当然可以。

如果不去限制队列的元素必须存储在数组的前n个单元这一条件,出队的性能就会大大增加。这也就意味着队头不一定位于index=0的位置了。

假设是长度为5的数组,初始状态,空队列如所示,front与 rear指针均指向下标为0的位置。然后入队a1、a2、a3、a4, front指针依然指向下标为0位置,而rear指针指向下标为4的位置。

出队a1、a2,则front指针指向下标为2的位置,rear不变,如下图所示,再入队a5,此时front指针不变,rear指针移动到数组之外。嗯?数组之外,那将是哪里?

如上图所示,添加a5元素之后,rear已经无家可归了,于此同时0和1位置的空间却被拜拜浪费了,这个中情况被称之为 假溢出

为了解决 假溢出 的情况也就引出了我们接下来要讲的 循环队列

接着上图的来讲,为了把无家可归的rear有个好的落脚点,我们就把它放置在index=0的位置。

但是如果继续进行入队 *** 作的话,比如继续插入a6、a7,则rear指针就与front指针重合,同时指向下标为2的位置。

此时问题又出来了,我们刚才说,空队列时,等于rear,现在当队列满时,也是from等于rear,那么如何判断此时的队列究竟是空还是满呢?

办法一 是设置一个标志变量flag,当front == rear,且flag = 0时为队列空,当front == rear,且flag= 1时为队列满。

办法二 是当队列空时,条件就是from = rear,当队列满时,我们修改其条件,保留一个元素空间。也就是说,队列满时,数组中还有一个空闲单元。 如下图所示,我们就认为此队列已经满了,也就是说,我们不允许上图情况出现。

在第二种情况下,由于rear可能比front大,也可能比front小,所以尽管它们只相差一个位置时就是满的情况,但也可能是相差整整一圈。所以若队列的最大尺寸为QueueSize,那么队列满的条件是(rear+1) %QueueSize == front (取模“%的目的就是为了整合rear与front大小为一个问题)。

比如上面这个例子, QueueSize = 5,当 front=0,而 rear=4, (4+1) %5 = 0,所以此时队列满。再比如,front = 2而rear =1。(1 + 1) %5 = 2,所以此时 队列也是满的。而对于下图, front = 2而rear= 0, (0+1) %5 = 1,1!=2,所以此时队列并没有满。

另外,当rear > front时,此时队列的长度为rear—front。但当rear < front时,队列长度分为两段,一段是QueueSize-front,另一段是0 + rear,加在一起,队列长度为rear-front + QueueSize,因此通用的计算队列长度公式为:

(rear—front + QueueSize) % QueueSize

从上面的图我们不难看出顺序存储存在着数组可能会溢出的问题,所以也就引出了链式存储结构。

在链队列中,队头指针指向头结点,队尾指针指向终端结点,一个普通的链队列如下图所示:

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

链式队列

链式存储结构的队列称作链式队列。

链式队列的队头指针指在队列的当前队头结点位置,队尾指针指在队列的当前队尾结点位置。不带头结点的链式队列时可直接删除队头指针所指的结点。

链式队列中结点的结构体可定义如下:

typedef struct qnode

{

DataType datal;

Struct qnode next;

}LQNode;

为了方便参数调用,通常把链式队列的队头指针front和队尾指针rear也定义为如下的结构体类型LQueue:

typedef struct

{

LQNode front;

LQNode rear;

}LQueue;

链式队列 *** 作的实现

(1) 初始化QueueInitiate(LQueue Q)

void QueueInitiate(LQueue Q)

{

Q->rear=NULL;

Q->front=NULL;

}

(2)非空否QueueNotEmpty(LQueue Q)

int QueueNotEmpty(LQueue Q)

/判断链式队列Q非空否,非空返回1,否则返回0/

{

if(Qfront==NULL)return 0;

else return 1;

}

(3)入队列QueueAppend(LQueue Q,DataType x)

int QueueAppend(LQueue Q,DataType x)

/把数据元素x插入链式队列Q队列的队尾,入队列成功返回1,否则返回0/

{

LQNode p;

if((p=(LQNode)malloc(sizeof(LQNode)))==NULL)

{

printf(“内存不足无法插入!\n);

return 0;

}

p->data=x;

p->next=NULL;

if(Q->rear!=NULL)Q->rear->next=p;

Q->rear=p;

if(Q->front==NULL)Q->front=p;

return 1;

}

(4)出队列QueueDelete(LQueue Q,DataType d)

int QueueDelete(LQueue Q,DataType d)

/删除链式队列Q的队头数据元素值到d,出队列成功返回1,否则返回0/

{

LQNode p;

if(Q->front==NULL)

{

printf(“队列已空无数据元素出队列!\n”);

return 0;

}

else

{

d=Q->front->data;

p=Q->front;

Q->front=Q->front->next;

if(Q->front==NULL)Q->rear=NULL;

free(p);

return 1;

}

}

(5)取队头数据元素QueueGet(LQueue Q,DataType d)

int QueueGet(LQueue Q,DataType d)

/取链式队列Q的当前队头数据元素值到d,成功返回1,否则返回0/

{

if(Qfront==NULL)

{

printf(“队列已空无数据元素出队列!\n);

return 0;

}

else

{

d=Qfront->data;

return 1;

}

}

(6)撤销动态申请空间Destory(LQueue head)

int Destory(LQueue head)

{

LQNode p,p1;

p=Qfront;

while(p!=NULL)

{

p1=p;

p=p->next;

free(p1);

}

}

帮你转的,我觉得他描述的很清楚。希望对你有帮助。

以上就是关于栈和队列数据结构的特点是什么全部的内容,包括:栈和队列数据结构的特点是什么、什么是队列、数据结构之-队列等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zz/10036932.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-04
下一篇 2023-05-04

发表评论

登录后才能评论

评论列表(0条)

保存