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);
}
}
帮你转的,我觉得他描述的很清楚。希望对你有帮助。
以上就是关于栈和队列数据结构的特点是什么全部的内容,包括:栈和队列数据结构的特点是什么、什么是队列、数据结构之-队列等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)