栈和队列的详细讲解
22
退栈算法(算法 ) 退栈算法(算法4.9)
void pop_link( PLinkStack plstack ) { PNode p; if( isEmptyStack_link( plstack ) ) printf( "Empty stack pop.\n" ); else { p = plstack->top; plstack->top = plstack->top->link; free(p); } }
19
pLinkstack plstack; plstack top
/*变量声明 变量声明*/ 变量声明 info link
^
栈的链接表示
3.1.3 链栈
进栈 相当于链表在 top 结点前插入 出栈 相当于链表在将 相当于链表在将top 结点删除
21
进栈算法(算法 ) 进栈算法(算法4.8)
void push_link( PLinkStack plstack, DataType x ) /* 在栈中压入一元素 */ 在栈中压入一元素x { PNode p; p = (PNode)malloc( sizeof( struct Node ) ); if ( p == NULL ) printf("Out of space!\n"); else { p->info = x; p->link = plstack->top; plstack->top = p; } }
4
3.1.2 顺序栈
栈的顺序存储结构简称为顺序栈, 栈的顺序存储结构简称为顺序栈,它是运算受限 的顺序表。 的顺序表。 #define MAXNUM 100 /* 栈中能达到的最大容量 栈中能达到的最大容量*/
typedef int DataType; /* 定义栈元素的数据类型 / 定义栈元素的数据类型* struct SeqStack /* 顺序栈类型定义 */ { DataType s[MAXNUM]; int t; /*栈顶 栈顶*/ 栈顶 }; ; typedef struct SeqStack, *PSeqStack; PSeqStack pastack; /*指向顺序栈的指针变量 指向顺序栈的指针变量*/ 指向顺序栈的指针变量
算法4.4 4.4) 4. 退栈(算法4.4)
pop_seq(pastack)
PSeqStack pastack; { if (pastack->t==-1 ) (pastack->t==print(“underflow ); print( underflow”); underflow else pastack->t--; pastack->t--; -} /* pop_seq */
27
例3.2
栈与递归
递归函数的特点:在函数内部可以直接或间接地 递归函数的特点: 调用函数自身。如阶乘函数: 调用函数自身。如阶乘函数: 1 n!= n*(n-1)! n*(n, n>0 , n=0
28
阶乘的递归计算(算法 阶乘的递归计算(算法4.11 ) int fact (int n) { if (n = = 0) return 1; else return(n*fact(n-1)); }; r2 main( ) { int n; scanf(“%d\n”,&n); printf(“%8d%8d\n”,n,fact(n)); } r1
25
设计一个简单的文字编辑器, 例3.1 设计一个简单的文字编辑器,使其具有删除打 错字符的功能。 错字符的功能。 /*顺序栈 是全程变量* PSeqStack str; /*顺序栈 str 是全程变量*/ /*编辑好的字符串在 EDIT( ) /*编辑好的字符串在 str 中*/ { char c; str=createEmptyStack(); c=getchar( ); while(c!=‘* ) /*字符 字符‘ 为编辑结束符* while(c!= *’) /*字符‘*’为编辑结束符*/ (c==‘# ) { if (c== #’) POP(str); else (c==‘@ ) if (c== @’) str=createEmptyStack(); else PUSH(str,c); ); c=getchar( ); } 26 } /*EDIT*/
5
注意: 注意
t是 int型简单变量 ,指向栈顶元素在栈中 是 型简单变量 指向栈顶元素在栈中 的位置(序号 序号) 的位置 序号
约定: 约定
1、栈空时,t=-1 、栈空时, 2、栈满时,t=MAXNUM-1 、栈满时, 3、栈顶元素:S[t] 、栈顶元素: 4、若t=-1时,执行 产生“ 、 时 执行pop,产生“下溢” 产生 下溢” 5、若t=MAXNUM-1时,执行 产生“ 、 时 执行push,产生“上溢 产生 6 ”
push_seq(pastack,x)
先修改 t 值,再放入数据
t++
s[t]=x
(*pastack).t++ (*pastack).s[(*pastack).t]=x
11
进栈(算法4.3 4.3) 3. 进栈(算法4.3)
push_seq(pastack,x)
PSeqStack pastack; datatype { if else pastack{ pastack->t++; pastack->s[pastackpastack->s[pastack->t]=x;} } /* push_seq */
23
3.2
栈的应用
栈的应用非常之广,只要问题满足LIFO 原则, 栈的应用非常之广,只要问题满足LIFO 原则,
均可使用栈做数据结构。我们先看几个例子。 均可使用栈做数据结构。我们先看几个例子。 例3.1 例3.2 例3.3 例3.4 例3.5 文字编辑器 栈与递归 数制转换 括号匹配的检验 表达式求值 表达式求值
24
设计一个简单的文字编辑器, 例3.1 设计一个简单的文字编辑器,使其具有删除打 错字符的功能。 错字符的功能。 每读入一个字符 ‘#’ # ‘@’ ‘*’ —— —— —— 删除前面一个字符 删除前面所有字符 输入结束 退栈 置空栈 编辑结束
“abc#d@efg*” 我们用栈来实现这种功能的文字编辑器
14
栈顶元素(算法4.5 4.5) 5. 取栈顶元素(算法4.5) datatype top_seq(pastack) PSeqStack pastack; { if (pastack->t==-1 ) { print(“stack is empty”); return NULL; } else return(pastack->s[pastack->t]; } /* top_seq */
3.1.2 顺序栈
进栈和退栈
6 5 4 3 2 1 0 -1
D C B A
7
3.1.2 顺序栈
在顺序栈下实现栈的五种基本运算 (1)置空栈 (2)判栈空 (3)进栈 (4)退栈 (5)取栈顶 当程序中同时使用两个栈时, 当程序中同时使用两个栈时, 共享存储空间 存储空间。 可共享存储空间。
8
置空栈(算法4.1 4.1) 1. 置空栈(算法4.1) PSeqStack createEmptyStack_seq(void) { PSeqStack pastack; pastack=malloc(sizeof(struct SeqStack)); if(pastack==NULL) printf(“out space!\ ); printf( out of space!\n”); else pastack->t= -1; pastackreturn pastack; } /*SETNULL*/
12
x;
(pastack->t==MAXNUM-1) (pastack->t==MAXNUMprint(“overflow ); print( overflow”); overflow
算法4.4 4.4) 4. 退栈(算法4t 值
t-pastack->t - 13
9
判栈空(算法4.2 4.2) 2. 判栈空(算法4.2)
int { if
isEmptyStack_seq(pastack) (pastack(pastack->t>=0) return FALSE; TRUE; return
PSeqStack pastack;
else }
10
进栈(算法4.3 4.3) 3. 进栈(算法4.3)
15
多个栈共享存储空间 栈1 栈2
…
栈1顶
…
栈2顶
...
栈2底
栈1底
让多个栈共享存储空间,可以相互调节余缺, 让多个栈共享存储空间,可以相互调节余缺, 节约存储空间,降低发生上溢的概率。 节约存储空间,降低发生上溢的概率。
16
多个栈共享存储空间 Typedef struct { datatype s[MAXNUM]; int top1,top2; }DStack;
例3.2
栈与递归
递归的定义 如果一个对象部分的由自己组成, 如果一个对象部分的由自己组成,或者 是按它自己定义的,则称为递归 递归的 是按它自己定义的,则称为递归的。 一个递归定义必须一步比一步简单, 一个递归定义必须一步比一步简单,最 后是有终结的,决不能无限循环下去。 后是有终结的,决不能无限循环下去。在n 阶乘的定义中, 时定义为1 阶乘的定义中,当n为0时定义为1,它不再 用递归来定义,称为递归定义的出口, 递归定义的出口 用递归来定义,称为递归定义的出口,简称 递归出口。 为递归出口。
an
...
a2 a1
3