第3章 栈和队列1
数据结构-Java语言描述 第三章 栈和队列
System.exit(1);
}
栈顶指针top的初始值决
top=-1;
定了后续其他方法的实现
stackArray=(T[])new Object[n];
}
【算法3-2】入栈
public void push(T obj)
{
if(top==stackArray.length-1){
T []p=(T[])new Object [top*2];
(b)元素a2入栈
an … … a2 a1
(c)元素an入栈
an-1 … a2 a1
(d)元素an出栈
a2 a1
(e)元素a3出栈
a1
(f)元素a2出栈
【例3-1】一个栈的输入序列是1、2、3、4、5,若在 入栈的过程中允许出栈,则栈的输出序列4、3、5、1、 2可能实现吗?1、2、3、4、5的输出呢?
型 正序遍历:依次访问栈中每个元素并输出
3.1.2 顺序栈
顺序栈泛型类的定义如下:
public class sequenceStack<T> {
顺序栈中一维数组 的初始长度
final int MaxSize=10;
private T[] stackArray; 存储元素的数组对象
private int top;
public void nextOrder() {
for(int i=top;i>=0;i--) System.out.println(stackArray[i]);
}
【算法3-8】清空栈操作
public void clear() {
top=-1; }
3.1.3 链栈
栈的链接存储结构称为链栈。结点类的定义,同 第二章Node类。
大学数据结构课件--第3章 栈和队列
栈满 top-base=stacksize
top
F
E
D C B
top top top top top top base
入栈PUSH(s,x):s[top++]=x; top 出栈 POP(s,x):x=s[--top]; top
base
4
A
3.1 栈
例1:一个栈的输入序列为1,2,3,若在入栈的过程中 允许出栈,则可能得到的出栈序列是什么? 答: 可以通过穷举所有可能性来求解:
3.2 栈的应用举例
二、表达式求值
“算符优先法”
一个表达式由操作数、运算符和界限符组成。 # 例如:3*(7-2*3) (1)要正确求值,首先了解算术四则运算的规则 a.从左算到右 b.先乘除后加减 c.先括号内,后括号外 所以,3*(7-2*3)=3*(7-6)=3*1=3
9
3.2 栈的应用举例
InitStack(S); while (!QueueEmpty(Q))
{DeQueue(Q,d);push(S,d);}
while (!StackEmpty(S)) {pop(S,d);EnQueue(Q,d);} }
第3章 栈和队列
教学要求:
1、掌握栈和队列的定义、特性,并能正确应用它们解决实 际问题;
用一组地址连续的存储单元依次存放从队头到队尾的元素, 设指针front和rear分别指示队头元素和队尾元素的位置。
Q.rear 5 4 Q.rear 3 2 3 2 5 4 Q.rear 3 3 5 4 5 4
F E D C
C B A
Q.front
2 1 0
C B
Q.front 2 1 0
第3章栈和队列-数据结构与算法(第2版)-汪沁-清华大学出版社
an
队头
队尾
队列示意图
入队
13
2、队列的基本运算
初始化队列 INIQUEUE(&Q)
将队列Q设置成一个空队列。
入队列
ENQUEUE(&Q,X)
将元素X插入到队尾中,也称“进队” ,“插入”。
出队列
DLQUEUE(&Q)
将队列Q的队头元素删除,也称“退队”、“删除”。
取队头元素 GETHEAD(Q)
也就是说,栈是一种后进先出(Last In First Out)的线性表,简称为LIFO表。
3
2、栈的运算
初始化栈:INISTACK(&S)
将栈S置为一个空栈(不含任何元素)。
进栈:PUSH(&S,X)
将元素X插入到栈S中,也称为 “入栈”、 “插入”、 “压 入”。
出栈: POP(&S)
删除栈S中的栈顶元素,也称为”退栈”、 “删除”、 “弹 出”。
9
三、链栈
typedef struct Lsnode { ElemType data;
struct Lsnode *next; } Lsnode *top;
一个链表栈由ቤተ መጻሕፍቲ ባይዱ顶指针top唯一确定。
10
1、链栈的主要运算
进栈操作 void Push(Lsnode *top; ElemType x)
{ p=(Lsnode *)malloc(sizeof(Lsnode)); p->data=x; p->next=top->next; top->next=p; }/*Push*/
第3章 栈和队列
1
栈和队列是二种特殊的线性表。是操作受 限的线 性表。 一、栈
ch03_1栈和队列1-栈PPT教学课件
while(ch!=EOF) {
while(ch!=EOF && ch!=‘\n’) {
switch(ch) {
case ‘#’: Pop(S, ch);
break;
case ‘@’: ClearStack(S); break;
default: Push(S, ch); break;
}
ch=getchar();
只须证明,若借助栈由输入序列(1,2,…,n)得到输出序列
(p1,p2,…,pn),那么在输出序列中,不可能出现这种情况:存 在i<j<k,使pj<pk<pi. 这里(p1,p2,…,pn)是(1,2,…,n)的一个全排 列,每个元素只能按1,2,…,n的次序进一次栈。
提示
2020/12/12
i<j<k说明进栈顺序为(…i…j…k…),它们的出 栈排列只有6种可能:
}
ClearStack(S);
if(ch!=EOF) ch=getchar();
}
DestroyStack(S);
} 2020/12/12
12
栈的应用:迷宫求解
东南西北 (顺时针)
演示
2020/12/12
13
迷宫求解策略
求迷宫中一条路径的算法的基本思想是:
若当前位置"可通",则纳入"当前路径",并继续朝"下一位置“
a2
栈底
a1
2020/12/12
2
栈的基本操作
1.初始化栈:IniStack(&S) 将栈S置为一个空栈(不含任何元素)。
注意这两个 操作的区别
2.进栈:Push(&S,X)
《数据结构(C语言)》第3章 栈和队列
栈
❖ 栈的顺序存储与操作 ❖ 1.顺序栈的定义
(1) 栈的静态分配顺序存储结构描述 ② top为整数且指向栈顶元素 当top为整数且指向栈顶元素时,栈空、入栈、栈满 及出栈的情况如图3.2所示。初始化条件为 S.top=-1。
(a) 栈空S.top==-1 (b) 元素入栈S.stack[++S.top]=e (c) 栈满S.top>=StackSize-1 (d) 元素出栈e=S.stack[S.top--]
/*栈顶指针,可以指向栈顶
元素的下一个位置或者指向栈顶元素*/
int StackSize; /*当前分配的栈可使用的以 元素为单位的最大存储容量*/
}SqStack;
/*顺序栈*/
Data structures
栈
❖ 栈的顺序存储与操作 ❖ 1.顺序栈的定义
(2) 栈的动态分配顺序存储结构描述 ① top为指针且指向栈顶元素的下一个位置 当top为指针且指向栈顶元素的下一个位置时,栈空 、入栈、栈满及出栈的情况如图3.3所示。初始化条 件为S.top=S.base。
…,n-1,n≥0} 数据关系:R={< ai-1,ai>| ai-1,ai∈D,i=1,2
,…,n-1 } 约定an-1端为栈顶,a0端为栈底 基本操作:
(1) 初始化操作:InitStack(&S) 需要条件:栈S没有被创建过 操作结果:构建一个空的栈S (2) 销毁栈:DestroyStack(&S) 需要条件:栈S已经被创建 操作结果:清空栈S的所有值,释放栈S占用的内存空间
return 1;
}
Data structures
栈
第3章_栈和队列
(Chapter 3. பைடு நூலகம்tack and Queue)
栈的概念、存储结构及其基本操作
栈的应用举例 队列的概念、存储结构及其基本操作
§3.1 栈
3.1.1 栈的定义及基本运算
• 定义:只能在表尾(栈顶)进行插入和删除操 作进行的线性表。 • 特点: 后进先出(LIFO—Last In First Out )
top 栈顶
an an-1
. . .
a1 ∧
栈底
空栈: top == NULL
16
入栈
LinkStack Push_LS (LinkStack top,datatype x) { StackNode *p ; top p = (StackNode *) malloc (sizeof( StackNode)); p->data = x; top p->next = top; top = p; return top; }
23
2
括号匹配的检验:
问题:两种括号,可以嵌套使用,但不能重叠 解决:使用栈。 {([ ][ ])} 左括号进栈, 右括号就从栈顶出栈一个左括号, 检查是否能够匹配。 算法开始和结束时,栈都应该是空的。
匹配一个字符串中的左、右括号。如
[ a * ( b + c ) + d ]
( 出栈
( )匹配
[ 出栈
3.1.2 栈的存储及运算实现
顺序栈 -- 栈的顺序存储表示 链栈 -- 栈的链式存储表示
4
1 顺序栈
顺序栈类型的定义 – 本质 顺序表的简化,唯一需要确定的是栈顶、栈底。 – 通常 栈底:下标为0的一端 栈顶:由top指示,空栈时top=-1
数据结构课件第3篇章栈和队列
循环队列实现原理
01
循环队列定义
将一维数组看作首尾相接的环形结构,通过两个指针(队头和队尾指针)
在数组中循环移动来实现队列的操作。当队尾指针到达数组末端时,再
回到数组起始位置,形成循环。
02
判空与判满条件
在循环队列中,设置一个标志位来区分队列为空还是已满。当队头指针
等于队尾指针时,认为队列为空;当队尾指针加1等于队头指针时,认
栈在函数调用中应用
函数调用栈
在程序执行过程中,每当发生函数调用时,系统会将当前函数的执行上下文压入一个专门的栈中,称为函数调用 栈。该栈用于保存函数的局部变量、返回地址等信息。当函数执行完毕后,系统会从函数调用栈中弹出相应的执 行上下文,并恢复上一个函数的执行状态。
递归调用实现
递归调用是一种特殊的函数调用方式,它通过在函数调用栈中反复压入和弹出同一函数的执行上下文来实现对问 题的分解和求解。在递归调用过程中,系统会根据递归深度动态地分配和管理函数调用栈的空间资源。
栈和队列的应用
栈和队列在计算机科学中有着广泛的应用,如函数调用栈、表达式求 值、缓冲区管理等。
常见误区澄清说明
误区一
栈和队列的混淆。虽然栈和队列都是线性数据结构,但它们的操作方式和应用场景是不同的。栈是后进先出,而队列 是先进先出。
误区二
认为栈和队列只能通过数组实现。实际上,栈和队列可以通过多种数据结构实现,如链表、循环数组等。具体实现方 式取决于应用场景和需求。
后缀表达式求值
利用栈可以方便地实现后缀表达式的求值。具体步骤 为:从左到右扫描表达式,遇到数字则入栈,遇到运 算符则从栈中弹出所需的操作数进行计算,并将结果 入栈,最终栈中剩下的元素即为表达式的结果。
中缀表达式转换为后缀表达式
大学《数据结构》第三章:栈和队列-第一节-栈
第一节栈
一、栈的定义及其运算
1、栈的定义
栈(Stack):是限定在表的一端进行插入和删除运算的线性表,通常将插入、删除的一端称为栈项(top),另一端称为栈底(bottom)。
不含元素的空表称为空栈。
栈的修改是按后进先出的原则进行的,因此,栈又称为后进先出(Last In First Out)的线性表,简称为LIFO表。
真题选解
(例题·填空题)1、如图所示,设输入元素的顺序是(A,B,C,D),通过栈的变换,在输出端可得到各种排列。
若输出序列的第一个元素为D,则输出序列为。
隐藏答案
【答案】DCBA
【解析】根据堆栈"先进后出"的原则,若输出序列的第一个元素为D,则ABCD入栈,输出序列为DCBA
2、栈的基本运算
(1)置空栈InitStack(&S):构造一个空栈S。
第3章 限定性线性表——栈和队列
两栈共享技术(双端栈):
主要利用了栈“栈底位置不变,而栈顶位置动态变
化”的特性。首先为两个栈申请一个共享的一维数 组空间S[M],将两个栈的栈底分别放在一维数组的 两端,分别是0,M-1。
共享栈的空间示意为:top[0]和top[1]分别为两个 栈顶指示器 。
Stack:0
M-1
top[0]
top[1]
(1)第i号栈的进栈操作 int pushi(LinkStack top[M], int i, StackElementType x) { /*将元素x进入第i号链栈*/
LinkStackNode *temp; temp=(LinkStackNode * )malloc(sizeof(LinkStackNode)); if(temp==NULL) return(FALSE); /* 申请空间失败 */ temp->data=x; temp->next=top[i]->next; top[i]->next=temp; /* 修改当前栈顶指针 */ return(TRUE); }
case 1:if(S->top[1]==M) return(FALSE);
*x=S->Stack[S->top[1]];S->top[1]++;break;
default: return(FALSE);
}
return(TRUE);
返回主目录
}
【思考题】
说明读栈顶与退栈顶的处理异同,并标明将已知 的退栈顶算法改为读栈顶算法时应做哪些改动。
返回主目录
链栈的进栈操作
int Push(LinkStack top, StackElementType x)
最完整的数据结构1800题包括完整答案第3章 栈和队列
第3章栈和队列一选择题1. 对于栈操作数据的原则是()。
A. 先进先出B. 后进先出C. 后进后出D. 不分顺序2. 在作进栈运算时,应先判别栈是否( ① ),在作退栈运算时应先判别栈是否( ② )。
当栈中元素为n个,作进栈运算时发生上溢,则说明该栈的最大容量为( ③ )。
为了增加内存空间的利用率和减少溢出的可能性,由两个栈共享一片连续的内存空间时,应将两栈的 ( ④ )分别设在这片内存空间的两端,这样,当( ⑤ )时,才产生上溢。
①, ②: A. 空 B. 满 C. 上溢 D. 下溢③: A. n-1 B. n C. n+1 D. n/2④: A. 长度 B. 深度 C. 栈顶 D. 栈底⑤: A. 两个栈的栈顶同时到达栈空间的中心点.B. 其中一个栈的栈顶到达栈空间的中心点.C. 两个栈的栈顶在栈空间的某一位置相遇.D. 两个栈均不空,且一个栈的栈顶到达另一个栈的栈底.3. 一个栈的输入序列为123…n,若输出序列的第一个元素是n,输出第i(1<=i<=n)个元素是()。
A. 不确定B. n-i+1C. iD. n-i4. 若一个栈的输入序列为1,2,3,…,n,输出序列的第一个元素是i,则第j个输出元素是()。
A. i-j-1B. i-jC. j-i+1D. 不确定的5. 若已知一个栈的入栈序列是1,2,3,…,n,其输出序列为p1,p2,p3,…,p N,若p N是n,则p i是( )。
A. iB. n-iC. n-i+1D. 不确定6. 有六个元素6,5,4,3,2,1 的顺序进栈,问下列哪一个不是合法的出栈序列?()A. 5 4 3 6 1 2B. 4 5 3 1 2 6C. 3 4 6 5 2 1D. 2 3 4 1 5 67. 设栈的输入序列是1,2,3,4,则()不可能是其出栈序列。
A. 1,2,4,3,B. 2,1,3,4,C. 1,4,3,2,D. 4,3,1,2,E. 3,2,1,4,8. 一个栈的输入序列为1 2 3 4 5,则下列序列中不可能是栈的输出序列的是()。
数据结构实用教程(C语言版) 第3章 栈和队列
3.1.1 栈的概念
假设有一个栈S=(a1,a2,…,an),栈 中元素按a1,a2,…,an的次序进栈后, 进栈的第一个元素a1为栈底元素,出栈的第 一个元素an为栈顶元素,也就是出栈的操作 是按后进先出的原则进行的,其结构如图31所示。
图3-1栈结构示意图
返回到本节目录
3.1.2栈的基本操作
3.1.3顺序栈
由于栈是操作受限制的线性表,因此与线性表类似,栈也 有两种存储结构,即顺序存储结构和链式存储结构。 1. 顺序栈的定义 栈的顺序存储结构称为顺序栈。类似于顺序表的类型定义,顺 序栈是用一个预设的足够长度的一维数组和一个记录栈顶元素 位置的变量来实现。顺序栈中栈顶指针与栈中数据元素的关1.3顺序栈
3. 顺序栈的基本操作实现
(3)进栈操作 进栈操作的过程如图3-3所示。先判断栈S如图3-3(a) 是否为满,若不满再将记录栈顶的下标变量top加1如 图3-3(b),最后将进栈元素放进栈顶位置上如图33(c)所示,算法描述见算法3.3。
图3-3 进栈操作过程图
返回到本节目录
栈除了在栈顶进行进栈与出栈外,还有初始化、判空 等操作,常用的基本操作有: (1)初始化栈InitStack(S)。其作用是构造一个空 栈 S。 (2)判断栈空EmptyStack(S)。其作用是判断是 否是空栈,若栈S为空,则返回1;否则返回0。 (3)进栈Push(S,x)。其作用是当栈不为满时,将 数据元素x插入栈S中,使其为栈S的栈顶元素。 (4)出栈Pop(S,x)。其作用是当栈S不为空时,将 栈顶元素赋给x,并从栈S中删除当前栈顶元素。 (5)取栈顶元素GetTop(S,x)。其作用是当栈S不 为空时,将栈顶元素赋给x并返回,操作结果只是 读取栈顶元素,栈S不发生变化。 返回到本节目录
第3章栈和队列
3.1.2 栈的表示和算法实现
1.顺序栈 2.链栈
第3章栈和队列
1. 顺序栈 顺序栈是用顺序存储结构实现的栈,即利 用一组地址连续的存储单元依次存放自栈 底到栈顶的数据元素,同时由于栈的操作 的特殊性,还必须附设一个位置指针top( 栈顶指针)来动态地指示栈顶元素在顺序 栈中的位置。通常以top=-1表示空栈。
第 3 章 栈和队列
3.1 栈 3.2 队列 3.3 栈和队列的应用
第3章栈和队列
3.1 栈
3.1.1 栈的抽象数据类型定义 3.1.2 栈的表示和算法实现
第3章栈和队列
3.1.1 栈的定义
1.栈的定义 栈(stack)是一种只允许在一端进行插入和删除的线 性表,它是一种操作受限的线性表。在表中只允许进
行插入和删除的一端称为栈顶(top),另一端称为 栈 底 (bottom) 。 栈 的 插 入 操 作 通 常 称 为 入 栈 或 进 栈 (push),而栈的删除操作则称为出栈或退栈(pop)。 当栈中无数据元素时,称为空栈。
栈是按照后进先出 (LIFO)的原则组 织数据的,因此, 栈也被称为“后进 先出”的线性表。
第3章栈和队列
(2)入栈操作
Status Push(SqStack &S, Elemtype e)
【算法3.2 栈的入栈操作】
{ /*将元素e插入到栈S中,作为S的新栈顶*/
if (S->top>= Stack_Size -1) return ERROR;
else { S->top++;
S->elem[S->top]=e;
return OK;}
Push(S,’you’)
数据结构与算法C版课件第三章栈和队列
不改变栈的状态。
4.栈的存储 (1)采用顺序方式存储的栈称为顺序栈(sequential stack) (2) 采用链接方式存储的栈称为链栈(linked stack)
3.1.2 顺序栈及运算的算法实现
用栈来实现括号匹配检查的原则是,对表达式从左到右扫描。 (1)当遇到左括号时,左括号入栈; (2)当遇到右括号时,首先检查栈是否空,若栈空,则表明该“右括弧”多余;否则比 较栈顶左括号是否与当前右括号匹配,若匹配,将栈顶左括号出栈,继续操作;否则,表明 不匹配,停止操作。 (3)当表达式全部扫描完毕,若栈为空,说明括号匹配,否则表明“左括弧”有多余的。
出队
a1 a2 a3 a4 a5
入队
队列图示
4.队列的应用
5. 在队列上进行的基本运算
(1)队列初始化initQueue(q):构造一个空队列。 (2)判队空emptyQueue(q):若q为空队则返回为1,否
则返回为0。
(3)入队enQueue(q,x):对已存在的队列q,插入一个元素x
到队尾,队发生变化。
队列中元素个数的计算公式。
(4)出队deQueue(q,x):删除队头元素,并通过x返回其值,
队发生变化。
(5)读队头元素frontQueue(q):读队头元素,并返回其值,
队不变。
3.2.2 顺序队列及运算的实现
采用顺序方法存储的队列称为顺序队列(sequential queue)
顺序队列的存储结构用c语言定义如下:
#define MAXSIZE 1024
运算受限的线性 表
表两端插删
数据结构第三章栈和队列
性能比较与选择依据
性能比较
栈和队列的时间复杂度均为O(1),空间复杂度均为O(n)。在实际应用中,栈通常用于 需要后进先出(LIFO)的场景,而队列则用于需要先进先出(FIFO)的场景。
选择依据
在选择使用栈还是队列时,应根据具体需求和应用场景进行判断。如果需要后进先出的 特性,应选择栈;如果需要先进先出的特性,则应选择队列。同时,还需要考虑数据结
栈中的元素只能在栈顶进行插入和删 除操作。
栈具有记忆功能,能保存数据元素进 入栈的先后顺序。
栈的基本操作
01
入栈(Push):在栈顶 插入一个元素。
02
出栈(Pop):删除栈 顶元素并返回其值。
03
查看栈顶元素(Top) :返回栈顶元素的值, 但不删除该元素。
04
判断栈是否为空( IsEmpty):检查栈中 是否还有元素。
回溯到上一个状态。
广度优先搜索中的队列应用
搜索队列
广度优先搜索使用队列来保存待 搜索的节点,按照先进先出的原
则进行搜索。
状态转移
在广度优先搜索中,队列用于保存 状态转移的信息,以便在搜索过程 中根据状态转移规则进行状态的扩 展和搜索。
最短路径问题
广度优先搜索可用于解决最短路径 问题,通过队列保存待访问的节点 ,并按照距离起始节点的远近进行 排序和访问。
其他算法中的栈和队列应用
深度优先搜索
在深度优先搜索中,栈用于保存当前路径的状态信息,以便在需要时 回溯到上一个状态。
括号匹配问题
栈可用于解决括号匹配问题,遇到左括号时将其压入栈中,遇到右括 号时从栈中弹出左括号并判断是否匹配。
表达式求值
栈可用于表达式求值中,保存操作数和运算符,并按照运算优先级进 行求值。
第3章 桟和队列
第3章桟和队列3.1 选择题1.一个栈的输入序列为123…n,若输出序列的第一个元素是n,输出第i(1≤i≤n)个元素是()A)不确定 B)n-i+1 C)i D)n-i【答案】B【解析】根据栈的性质(LIFO),若输出的第一个元素是n,则表明所有的元素已经入栈,则出栈顺序为n,n-1,…,3,2,1。
2.设栈S和队列Q的初始状态为空,元素e1,e2,e3,e4,e5和e6依次通过栈S,一个元素出栈后即进队列Q,若6个元素出队的序列是e2,e4,e3,e6,e5,e1则栈S的容量至少应该是()A)6 B)4 C)3 D)2【答案】C【解析】根据栈的性质(LIFO)得,e2出栈前,栈中存有e1和e2两个元素,e4出栈前,栈中存有e1、e3和e4三个元素,e4和e3出栈以后,e5和e6入栈,栈中同样存在e1、e5和e6三个元素,然后三个元素依次出栈,所以栈的容量至少应该为3。
3.若一个栈以向量V[1..n]存储,初始栈顶指针top为n+1,则下面x进栈的正确操作是()A)top=top+1; V[top]=x B)V[top]=x; top=top+1C)top=top-1; V[top]=x D)V[top]=x; top=top-1【答案】C【解析】栈式运算受限的线性表,只允许在栈顶进行插入和删除操作。
本题中栈顶指针为n+1,该数组将栈顶放在了下标大的一端,所以在进行入栈操作时top指针应该进行减一操作。
通常元素进栈的操作为:先移动栈顶指针后存入元素。
4.如果我们用数组A[1..100]来实现一个大小为100的栈,并且用变量top来指示栈顶,top的初值为0,表示栈空。
请问在top为100时,再进行入栈操作,会产生()A)正常动作 B)溢出 C)下溢 D)同步【答案】B【解析】当top为100时,表示栈已经满了,此时再进行入栈操作,则会造成溢出。
5.栈在()中应用。
A)递归调用 B)子程序调用 C)表达式求值 D)A,B,C【答案】D7.用链接方式存储的队列,在进行删除运算时()A)仅修改头指针 B)仅修改尾指针C)头、尾指针都要修改 D)头、尾指针可能都要修改【答案】D【解析】若队列中的元素多于一个,删除队列中的队尾元素,只需修改队尾指针;若队列中只有一个元素,删除该元素后,队头队尾指针都需要修改。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
第3章 栈和队列栈和队列是两种重要的线性结构。
它们的共同特点是:操作受限(插入元素和删除元素只能在端点处进行)的线性表。
3.1 栈3.1.1 抽象数据类型栈的定义什么是栈(Stack ):栈是限定仅在表尾进行插入或删除操作的线性表。
对栈来说,表尾端有其特殊的含义,称为栈顶(Top ),相应地,表头端称为栈底(Bottom )。
不含元素的栈称为空栈。
栈在生活中的例子:蒸小茏包,先放下去的最后才拿出来。
栈:是先进后出(First In Last Out ,FILO )的线性表,也可称为后进先出(Last in First Out ,LIFO )。
对应的一个名词:先进先出First In First Out (FIFO )。
通常栈可用下图来表示:假设插入元素的序列为:49,27,36,57,63,89,16,这个过程称为入栈。
其过程为:将元素放到当前栈顶指向的空间,然后,栈顶移动一个位置。
出栈:就是将元素从栈顶元素处删除。
其过程为:先将栈顶向下移动一个位置,再将该元素拷贝出来。
典型的题目:如果有4个元素:a b c d ,依次入栈,其中又陆续出栈,问有哪些合法的出栈顺序?1)a b c d ?可以 2)a b d c ?可以3)c b d a ?可以4)c a d b ?不可能抽象数据类型的定义:ADT Stack{数据对象:数据关系:基本操作:1)InitStack,初始化栈2)DestroyStack,销毁栈,栈的空间释放了3)ClearStack,将一个栈清空,栈的空间还在4)StackEmpty,判断一个栈是否是空栈,返回True或False5)StackLength,求栈的长度,也就是求栈中还有几个元素6)GetTop,返回栈顶元素,但该元素还在栈中7)Push,元素入栈8)Pop,栈顶元素出栈9)遍历:StackTraverse,从栈底到栈顶元素,依个进行访问。
3.1.2 栈的表示和实现栈有两种表示:顺序表示(顺序栈)、链式表示(链表栈)。
所谓顺序栈,就是用一个顺序表(数组)来存储栈的元素。
显然,我们需要这些数据:存储元素的空间的首地址、栈顶指针、栈的空间总大小。
就得到下列结构体:1、顺序栈的第一种实现:typedef struct{SElemType *base; //存储元素的空间的首地址,可用malloc函数申请空间,将地址赋给它SElemType *top; //栈顶指针,指的是当前栈顶元素的上面的那个位置,初始时,top指向baseint stacksize; //当前栈的最大空间大小,用来判断栈是否已经满了,从而可以采取必要的措施。
}SqStack;#define STACK_INIT_SIZE 100#define STACK_INCREMENT 10SqStack S; //定义一个栈的变量S1)初始化栈函数Status InitSqStack( SqStack &S){S.base=(SElemType*)malloc(STACK_INIT_SIZE *sizeof(SElemType)); //申请100个空间if(!S.base) exit(-1); //申请空间失败,直接退出程序S.top=S.base;S.stacksize= STACK_INIT_SIZE;return OK;2)判断一个栈是否是空栈Status SqStackEmpty( SqStack S ){if( S.top==S.base )return TRUE;elsereturn FALSE;}3)清空一个栈Status ClearSqStack( SqStack &S ){S.top=S.base;return OK;}4)销毁一个栈Status DestroySqStack( SqStack &S ){free( S.base );S.base=S.top=NULL;S.stacksize=0;return OK;}5)求栈的长度int SqStackLength( SqStack S ){return S.top-S.base;}6)入栈Status PushSqStack( SqStack &S, SElemType e ){if( S.top-S.base>=S.stacksize ) //栈的空间满了{S.base=(SElemType*)realloc( S.base, (S.stacksize+10)*sizeof(SElemType));if(!S.base) exit(-1);S.top=S.base+S.stacksize;S.stacksize+=10;}*(S.top)=e; //S.top++;return OK;}7)出栈Status PopSqStack( SqStack &S, SElemType &e )if( S.top==S.base ) //如果栈为空return ERROR;S.top- -;e=*(S.top);return OK;}8)取栈顶元素Status GetTopSqStack( SqStack S, SElemType &e ){if( S.top==S.base ) //如果栈为空return ERROR;e=*(S.top-1);return OK;}9)遍历:从栈底开始到栈顶依次访问栈中的元素Status TraveseSqStack( SqStack S ){SElemType* p=S.base;while( p<S.top ){printf( *p ); //访问当前元素pp++;}return OK;}2、顺序栈的第二种实现:typedef struct{SElemType *base;int top; //栈顶上面元素的相对位置,也表示当前栈中有多少个元素int stacksize; //当前栈的最大空间大小,用来判断栈是否已经满了}SqStack;1)初始化栈函数Status InitSqStack( SqStack &S){S.base=(SElemType*)malloc(STACK_INIT_SIZE *sizeof(SElemType)); //申请100个空间if(!S.base) exit(-1); //申请空间失败,直接退出程序S.top=0;S.stacksize= STACK_INIT_SIZE;return OK;}2)判断一个栈是否是空栈Status SqStackEmpty( SqStack S )if( S.top==0 )return TRUE;elsereturn FALSE;}3)清空一个栈Status ClearSqStack( SqStack &S ){S.top=0;return OK;}4)销毁一个栈Status DestroySqStack( SqStack &S ){free( S.base );S.base=NULL;S.top=0;S.stacksize=0;return OK;}5)求栈的长度int SqStackLength( SqStack S ){return S.top;}6)入栈Status PushSqStack( SqStack &S, SElemType e ){if( S.top==S.stacksize ) //栈的空间满了{S.base=(SElemType*)realloc( S.base, (S.stacksize+10)*sizeof(SElemType));if(!S.base) exit(-1);S.stacksize+=10;}S.base[S.top]=e; //*(S.base+S.top)=e;S.top++;return OK;}7)出栈Status PopSqStack( SqStack &S, SElemType &e ){if( S.top==0 ) //如果栈为空return ERROR;S.top- -;e=S.base[S.top] ; //e=*(S.base+S.top);return OK;}8)取栈顶元素Status GetTopSqStack( SqStack S, SElemType &e ) {if( S.top==0 ) //如果栈为空 return ERROR; e=S.base[S.top-1]; return OK; }9)遍历:从栈底开始到栈顶依次访问栈中的元素 Status TraveseSqStack( SqStack S ) {for(int i=0; i<S.top; i++) { printf( S.base[ i ] ); }return OK; }3、共享栈的实现其结构如下: typedef struct {int space[100]; //共享栈的存储空间,固定为100个元素 int top1, top2; //分别表示两个栈的top }ShareStack; ShareStack SS; 则各种操作: 1)初始化栈:Status InitStack_Share( ShareStack &SS ) {SS.top1=0; SS.top2=99; }0 1 2 3 4 5 6 7 8 9 a2)判断一个栈是否是空栈Status StackEmpty_Share( ShareStack SS, int n ) //判断第n个栈是否为空栈{if( n==1 ) //第一个栈{if(SS.top1==0 ) return TRUE;else return FALSE;}else //第二个栈{if(SS.top2==99 ) return TRUE;else return FALSE;}}3)清空一个栈Status ClearStack_Share( ShareStack &SS, int n ) //清空第n个栈{if(n==1){SS.top1=0;}else{SS.top2=99;}return OK;}4)销毁一个栈Status DestroyStack_Share( ShareStack &SS, int n) //销毁第n个栈{//此操作无意义return OK;}5)求栈长度int StackLength_Share( ShareStack SS, int n) //求第n个栈的长度{if( n==1 ){return SS.top1;}else{return 99-SS.top2;}}5)入栈Status Push( ShareStack &SS, int n, SElemType e) //入栈到第n个栈中{if( SS.top1>=SS.top2 ) //栈满 return ERROR; if( n==1 ) { SS.spase[SS.top1]=e; SS.top1++; }else { SS.space[SS.top2]=e; SS.top2--; }return OK; }6)出栈Status Pop( ShareStack &SS, int n, SElemType &e) //第n 个栈出栈 {if( n==1 ) { if( SS.top1==0 ) //第一个栈是空栈,错误 return ERROR; SS.top1--; e=SS.space[SS.top1]; }else { if( SS.top2==99 ) //第二个栈是空栈,错误 return ERROR; SS.top2++; e=SS.space[SS.top2];} }课后练习:写一个程序,实现上述共享栈,并进行测试 4、栈的链式表示与实现可以使用的链表有:单链表(最常用)、单循环链表、循环双链表。