数据结构学习笔记(特殊的线性表:栈与队列)

希希里之海 希希里之海     2022-08-30     758

关键词:

                            栈与队列

栈是限定仅在表尾(栈顶)进行插入和删除操作的线性表(后进先出)。
队列是只允许在一端进行插入操作,而在另一端进行删除操作的线性表(先进先出)。

 

栈(Stack):

1.下标为0的一端作为栈底比较好,因为首元素都存在栈底,变化最小,所以让它作为栈底。
定义一个top变量来指示栈顶元素在数组中的位置。栈顶位置top必须小于存储栈长度StackSize,把空栈的判定条件定位top等于-1。

 

2.进栈与出栈操作(顺序存储结构):

进栈操作push:
/*插入元素e为新的栈顶元素*/
Status Push(SqStack *S, SElemType e)
{
if (S->top == MAXSIZE - 1) /*栈满*/
return ERROR;
S->top++; /*栈顶指针增加一*/
S->data[S->top] = e; /*将新插入元素赋值给栈顶空间*/
return OK;
}


出栈操作pop:
/*若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERROR*/
Status Pop(SqStack *S, SElemType *e)
{
if (S->top == -1)
return ERROR;
*e = S->data[S->top]; /*将要删除的栈顶元素赋值给e*/
S->top--; /*栈顶指针减一*/
return OK;
}

*进栈与出栈两者的时间复杂度均是O(1)。


3.两栈共享空间:
数组有两个端点,两个栈有两个栈底,让一个栈的栈底为数组的始端,即下标为0处,另一个栈为栈的末端,即下标为数组长度n-1处。这样,两个栈如果增加元素,就是两端点向中间延伸。
栈1为空时,就是top1等于-1时;而当top2等于n时,即是栈2为空时。
两个栈见面知识,也就是两个指针之间相差1时,即top1 + 1 == top2 为栈满。


4.栈的链式存储结构:
栈顶放在单链表的头部。
对于链栈来说,是不需要头结点的。
对于链栈来说,基本不存在栈满的情况。
链栈的空其实就是top=NULL。

 

5.进栈与出栈操作(链式存储结构):

进栈操作:
/*插入元素e为新的栈顶元素*/
Status Push(LinkStack *S, SElemType e)
{
LinkStackPtr s = (LinkStackPtr)malloc(sizeof(StackNode));
s->data=e;
s->next=S->top; /*把当前的栈顶元素赋值给新结点的直接后继*/
S->top=s; /*将新的结点s赋值给栈顶指针*/
S->count++;
return OK;
}

 

出栈操作:
/*若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERROR*/
Status Pop(LinkStack *S, SElemType *e)
{
LinkStackPtr P;
if (StackEmpty(*S))
return ERROR;
*e=S->top->data;
p=S->top; /*将栈顶结点赋值给p*/
S->top=S->top->next; /*使得栈顶指针下移一位,指向后一结点*/
free(p); /*释放结点p*/
S->count--;
return OK;
}

 

*链栈的出栈push和出栈pop操作没有任何循环操作,时间负责度均为O(1)。
*顺序栈和链栈,它们在时间复杂度上是一样的,均为O(1)。
*如果栈的使用过程中元素变化不可预料,有时很小,有时非常大,那么最好是用链栈;反之,如果它的变化在可控范围内,建议使用顺序栈会更好一些。


6.栈的应用:递归
递归定义:把一个直接调用自己或者通过一系列的调用语句间接地调用自己的函数,称作递归函数。
每个递归定义必须至少有一个条件,满足时递归不再进行,即不再引用自身二十返回值退出。
*迭代和递归的区别是:迭代使用的是循环结构,递归使用的是选择结构。递归能使程序的结构更清晰,更简洁,更容易让人理解,从而减少读懂代码的时间。但是大量的递归调用会建立函数的副本,会耗费大量的时间和内存。迭代则不需要反复调用函数和占用额外的内存。
递归过程退回的顺序是它前行顺序的逆袭。


7.栈的应用:四则运算表达式求值
后缀表达式:所有的符号都是在要运算数字的后面出现。
中缀表达式:标准四则运算表达式。
*后缀表达式运算规则:从左到右遍历表达式的每个数字和符号,遇到数字就进栈,遇到是符号,就将处于栈顶两个数字出栈,进行运算(后出栈的那个数字是“被”的,比如“被减数”,前面那个比如“减数”,运算结果出栈,一直到最终获得结果。

*中缀表达式转后缀表达式:
规则:从左到右遍历中缀表达式的每个数字和符号,若是数字就输出,即成为后缀表达式的一部分;若是符号,则判断其与栈顶符号的优先级,是右括号或优先级低于栈顶符号(乘除优先加减)则栈顶元素依次出栈并输出,并将当前符号出栈,一直到最终输出后缀表达式为止。

 

队列(Queue):
1.队列定义:队列是只允许在一端进行插入操作,而在另一端进行删除操作的线性表。
队列是一种先进先出的线性表。允许插入的一端称为队尾,允许删除的一端称为队头。

 

2.把队列的这种头尾相接的顺序存储结构称为循环对列。


3.判断队列究竟是空还是满?
*办法一是设置一个标志变量flag,当front == rear,且flag = 0 时为队列空,当front == rear,且 flag = 1时为队列满。
*办法二是当队列空时,条件就是front = rear,当队列满时,我们修改其条件,保留一个元素空间:
设队列的最大尺寸为QueueSize,队列满的条件是(rear+1)% QueueSize == front(取模“%”的母的就是为了整合rear与front大小为一个问题)。
通用的计算队列长度公式为:
(rear - front + QueueSize) % QueueSize

 

4.循环队列操作:

循环队列的顺序存储结构代码如下:
typedef int QElemType; /*QElemType类型根据实际情况而定,这里假设为int*/
/*循环队列的顺序存储结构*/
typedef struct
{
QElemType data[MAXSIZE];
int front; /*头指针*/
int rear; /*尾指针,若队列不空,指向队列尾元素的下一位置*/
}SqQueue;

 

循环队列的初始化代码如下:
/*初始化一个空队列Q*/
Status InitQueue(SqQueue *Q)
{
Q->front = 0;
Q->rear = 0;
return OK;
}

 

循环队列求队列长度代码如下:
/*返回Q的元素个数,也就是队列的当前长度*/
int QueueLength(SqQueue Q)
{
return (Q.rear - Q.front + MAXSIZE) % MAXSIZE;
}

 

循环队列的入队列操作代码如下:
/*若队列未满,则插入元素e为Q新的队尾元素*/
Status EnQueue(SqQueue *Q, QElemType e)
{
if((Q->rear+1)%MAXSIZE == Q->front) /*队列满的判断*/
return ERROR;
Q->data[Q->rear]=e; /*将元素e赋值给队尾*/
Q->rear=(Q->rear+1)%MAXSIZE; /*rear指针后移一位置*/
return OK;
}

 

循环队列的出队列操作代码如下:
/*若队列不空,则删除Q中队头元素,用e返回其值*/
Status DeQueue(SqQueue *Q, QElemType *e)
{
if (Q->front == Q->rear) /*队列空的判断*/
return ERROR;
*e = Q->data[Q->front]; /*将队头元素赋值给e*/
Q->front = (Q->front + 1) % MAXSIZE; /*front指针向后移一位置*/
/*若到最后则转到数组头部*/
return OK;
}

数据结构系列栈与队列

栈定义栈是一种特殊的线性表 操作  存储结构从存储结构来看,分为顺序栈和链栈,同线性表的划分 应用递归-菲波那切数列后缀表达式-逆波兰表示   队列定义队列也是一种特殊的线性表 操作队列... 查看详情

栈与队列

...和队列都属于线性结构,是两种在运算上受到某些限制的特殊线性表,他们比一般线性表更简单,被广泛应用于类型的程序设计中,可以用来存放许多中间信息,在系统软件设计以及递归问题处理方面都离不开堆栈和队列。栈&nb... 查看详情

栈与队列

...:零个或多个数据元素的有限序列线性表_(linearlist)_是数据结构的一种,一个线性表是n个具有相同特性的数据元素的有限序列是一个有限序列,元素之间是有顺序的,若元素存在多个,第一个元素无前驱,最后一个元素无后继,其他... 查看详情

3)数据结构之线性表(栈与队列)(代码片段)

目录栈与队列的本质栈的基本概念栈的物理结构栈的顺序存储结构(用数组实现)静态栈的实现: Stack.h中Test/c中Stack.c中输出结果动态栈的实现 Stac.h中Test.c中Stack.c中栈的链式存储结构(使用链表实现) Stack... 查看详情

数据结构与算法学习笔记栈和队列ⅰ(代码片段)

数据结构与算法学习笔记(5)栈和队列文章目录数据结构与算法学习笔记(5)栈和队列一.栈和队列的定义和特点1.栈的定义和特点相关概念示意图栈与一般线性表的不同2.队列的定义和特点相关概念二.案例引入1.栈的典型案例进制转... 查看详情

栈与队列,各有异同。

...先被拿出来,被称为先进后出、后进先出。队列也是一种特殊的线性表。不同于栈所服从的先进后出的原则,队列的原则是先进先出。队列在队头做删除操作,在队尾做插入操作。  然后是两者的异同点不同点:1.删除数据... 查看详情

栈与队列的区别

...的一端进行插入和在另一端进行删除操作的线性表。从"数据结构"的角度看,它们都是线性结构,即数据元素之间的关系相同。但它们是完全不同的数据类型。除了它们各自的基本操作集不同外,主要区别是对插入和删除操作的"... 查看详情

数据结构回顾之顺序存储结构中的线性表(栈与队列顺序线性表实现)

  说到数据结构呢,对于一个Coder来说还是蛮重要的啦,每次看数据结构的东西都有新的收获,这两天在回顾数据结构的知识。当然啦,虽然数据结构有些是理论的东西,如果好好的理解数据结构的东西还是少不了的代码的支... 查看详情

栈与队列(代码片段)

最近一直在看数据结构与算法,下面是对有线性结构的栈与队列的总结:栈相关的内容定义:栈是限定仅在表尾进行插入和删除操作的线性表。(后进先出的线性表)操作:在可以插入与删除的一端称为栈顶,另外一端称为栈底... 查看详情

大话数据结构4之栈与队列

1. 栈是限定仅在表尾进行插入和删除操作的线性表。  队列是只允许在一端进行插入操作、而在另一端进行删除操作的线性表。2.我们把允许插入和删除的一端称为栈顶(top),另一端称为栈底(bottom),不含任何数据元素的栈... 查看详情

栈与队列

异同栈(Stack)和队列(Queue)是两种操作受限的线性表。这种受限表现在:栈的插入和删除操作只允许在表的尾端进行(在栈中成为“栈顶”),满足“FIFO:FirstInLastOut”;队列只允许在表尾插入数据元素,在表头删除数据元... 查看详情

大话数据结构栈与队列(代码片段)

栈是限定仅在表尾进行插入和删除操作的线性表。我们把允许插入和删除的一端称为栈顶,另一端称为栈底,不含任何数据元素的栈称为空栈。栈又称为后进先出的线性表,简称LIFO结构。栈的插入操作,叫作进栈,也称压栈、... 查看详情

第4章栈与队列-----队列

...只允许在一端进行插入操作,而在另一端进行删除操作的线性表。 队列是一种先进先出(FirstINFirstOut)的线性表,简称FIFO。允许插入的一端称为队尾,允许删除的一端称为对头。  队列的抽象数据类型  队列顺... 查看详情

第三章:1.栈和队列--栈的表示及实现

前言:  栈和队列是两种重要的线性结构。从数据结构角度来看,栈和队列也是线性表,它的特殊性在于其操作是线性表的子集,是操作受限的线性表,因此可以称作限定性的数据结构。  (限定性:如、人为的规定线性表... 查看详情

顺序表栈与队列(代码片段)

一、顺序表引入1什么是线性表1在程序中,经常需要将一组数据元素作为整体管理和使用,需要创建这种元素组,用变量记录它们,传进传出函数等。2一组数据中包含的元素个数可能发生变化(增加或删除元素)。3对于这种需... 查看详情

栈与队列的区别

栈(Stack)队列(Queue)线性表链表先进后出先进先出top(front,rear)(data,link)(prior,next)只能在表的一端进行插入和删除操作的线性表只能在表的一端进行插入和在另一端进行删除操作的线性表允许在表内任一位置进行插入和删... 查看详情

栈与队列

...;inttop;}SqStack;对于一个顺序栈st,一共有4个要素,包括两个特殊的状态和两个操作:两个状态栈空状态st.top==-1;栈满状态st.top==MaxSize-1;两个操作元素x进栈++(st.top);st.data[top]= 查看详情

栈与队列

...;inttop;}SqStack;对于一个顺序栈st,一共有4个要素,包括两个特殊的状态和两个操作:两个状态栈空状态st.top==-1;栈满状态st.top==MaxSize-1;两个操作元素x进栈++(st.top);st.data[top]= 查看详情