第三章 栈与队列
This presentation is the property of its rightful owner.
Sponsored Links
1 / 47

第三章 栈与队列 PowerPoint PPT Presentation


  • 167 Views
  • Uploaded on
  • Presentation posted in: General

第三章 栈与队列. 栈 ( Stack ) 队列 ( Queue ). 3.1 栈 ( Stack ). 只允许在一端插入和删除的顺序表 允许插入和删除 的一端称为 栈顶 ( top ) ,另一端称 为 栈底 ( bottom ) 特点 后进先出 ( LIFO ). 退栈. 进栈. 基本操作. Push Q Push A Pop Pop. Push R Push D Push M Pop Push Q. 栈的抽象数据类型 p45. ADT Stack{

Download Presentation

第三章 栈与队列

An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -

Presentation Transcript


5705371

第三章 栈与队列

  • 栈 ( Stack )

  • 队列 ( Queue )


3 1 stack

3.1栈 ( Stack )

  • 只允许在一端插入和删除的顺序表

  • 允许插入和删除

    的一端称为栈顶

    (top),另一端称

    为栈底(bottom)

  • 特点

    后进先出 (LIFO)

退栈

进栈


5705371

基本操作

Push Q

Push A

Pop

Pop


5705371

Push R

Push D

Push M

Pop

Push Q


5705371

栈的抽象数据类型 p45

ADT Stack{

D = {ai | ai ElemSet, i = 1,2,…n }

R = {<ai-1, ai> | ai-1, ai D, i = 2,…n}

约定an端为栈顶, a1端为栈底

P:

InitStack(&S)

ClearStack(&S)

StackEmpty(S)

StackLength(S)

GetTop(S, &e)

Push(&S, e)

Pop(&S, &e)

StackTraverse(S, visit());

}ADT Stack


5705371

栈的表示和实现

栈是一种线性结构,有

顺序栈和链栈两种存储结构,

这两种存储结构的不同,则使得实现栈的基本运算的算法也有所不同。


5705371

如何存储栈?

进栈、出栈等操作如何实现?

3.1 栈

栈的顺序存储和实现

一、栈的顺序存储结构

1 栈的顺序存储结构

#define MAX 50

int stack[MAX];

int top=0;


5705371

an

an-1

a2

a1

MAX-1

n

n-1

n-2

1

0

top

当栈用顺序结构存储时,

栈的基本操作如建空栈、

进栈、出栈等操作如何实现?

顺序栈的图示

约定栈顶指针指向

栈顶元素的下一个位置


5705371

x

an

an-1

a2

a1

MAX-1

n

n-1

n-2

1

0

an

an-1

a2

a1

MAX-1

n

n-1

n-2

1

0

top

top

x 进栈后

x 进栈前

1 ) 进栈操作

viod Push( int x )

{if (top>=MAX) printf(“ overflow” );

else {stack[top]=x; top++; }

}


5705371

an

an-1

a2

a1

an

an-1

a2

a1

MAX-1

n

n-1

n-2

1

0

MAX-1

n

n-1

n-2

1

0

top

top

出栈操作前

出栈操作后

2)出栈操作

int pop( ){if (top==0) {printf(“underflow”); return(-1);}

top--; return(0);

}


P46 47

出栈

进栈

an

栈顶

a3

a2

栈底

a1

栈的表示和实现 顺序栈 P46-47

  • 在连续的存储单元内依次存放栈中的数据元素,并设指针top来指示栈顶元素的位置

  • top为0时表示空栈

#define STACK_INIT_SIZE 100;

#define STACKINCREMENT 10;

typedef struct{

SElemType *base; //栈底指针

SElemType *top; //栈顶指针

int stacksize; //栈的当前最大可用容量

}SqStack;

SqStack S;


5705371

顺序栈的实现

Status InitStack(SqStack &S){

S.base = (SElemType *)

malloc(STACK_INIT_SIZE * sizeof(ElemType));

if (!S.base) exit(OVERFLOW);

S.top = S.base;

S.stacksize = STACK_INIT_SIZE;

return OK;

}

Status GetTop(SqStack S, SElemType &e){

if (S.top == S.base) return ERROR;

e = *(S.top –1);

return OK;

}


5705371

顺序栈的实现

Status Push(SqStack &S, SElemType e){

if (S.top – S.base >= S.stacksize){ //栈满,追加空间

S.base = (ElemType *)realloc(S.base,

(S.stacksize + STACKINCREMENT) * sizeof(ElemType));

if (!S.base) exit(OVERFLOW);

S.top = S.base + S.stacksize;

S.stacksize += STACKINCREMENT;

}

*S.top ++ = e; //进栈

return OK;

}


5705371

Status Pop(SqStack &S, SElemType &e){

if (S.top == S.base) return ERROR;

e = * -- S.top; //出栈

return OK;

}


5705371

顺序栈的实现

void ClearStack(&S) {

S.top = S.base;

}

int StackLength(S) {

return (S.top –S.base);

}

int StackEmpty(S) {

if (S.top == S.base)

return TRUE

else

return FALSE;

}


5705371

进栈示例


5705371

退栈示例


5705371

两个栈共享一个数组


5705371

栈的链接表示 — 链式栈

  • 链式栈无栈满问题,空间可扩充

  • 插入与删除仅在栈顶处执行

  • 链式栈的栈顶在链头

  • 适合于多栈操作


5705371

data

next

S

栈顶

栈底

栈的表示和实现

typedef struct{

SElemType data;

struct StackNode *next;

}StackNode, *StackPtr;

StackPtr S;


5705371

链栈的实现

Status InitStack(StackPtr &S){

S = (StackPtr)malloc(sizeof(StackNode));

if (!S) exit(OVERFLOW);

S.next = NULL;

return OK;

}

Status GetTop(StackPtr S, SElemType &e){

if (!S) return ERROR;

e = S->data;

return OK;

}


5705371

p

e

S

链栈的实现

Status Push(StackPtr &S, SElemType e){

p = (StackPtr)malloc(sizeof(StackNode));

p->data = e;

p->next = S;

S = p;

return OK;

}

Status Pop(StackPtr &S, SElemType &e){

if (!S) return ERROR; //空栈

p = S;

e = S->data;

S = S->next;

free(p);

return OK;

}

S


5705371

  • 在顺序栈中有“上溢”和“下溢”的概念。顺序栈好比一个盒子,我们在里头放了一叠书,当我们要用书的话只能从第一本开始拿,那么当我们把书本放到这个栈中超过盒子的顶部时就放不下了,这时就是"上溢","上溢"也就是栈顶指针指出栈的外面,显然是出错了。反之,当栈中已没有书时,我们再去拿,看看没书,把盒子拎起来看看盒底,还是没有,这就是"下溢"。"下溢"本身可以表示栈为空栈,因此可以用它来作为控制转移的条件。

  • 链栈则没有上溢的限制,它就象是一条一头固定的链子,可以在活动的一头自由地增加链环(结点)而不会溢出,


5705371

3.2栈的应用举例

  • 数制转换

  • 括号匹配的检验[( [ ] [ ] )]

  • 行编辑程序p49


5705371

3.2.1 数制转换

十进制N和其它进制数的转换是计算机实现计算的基本问题,其解决方法很多,其中一个简单算法基于下列原理:

N=(n div d)*d+n mod d

( 其中:div为整除运算,mod为求余运算)

例如 (1348)10=(2504)8,其运算过程如下:


5705371

n n div 8 n mod 8

1348 168 4

168 21 0

21 2 5

2 0 2


5705371

void conversion( ) {

initstack(s);

scanf (“%”,n);

while(n){

push(s,n%8);

n=n/8;

}

while(! Stackempty(s)){

pop(s,e);

printf(“%d”,e);

}

}


5705371

3.2.4 迷宫求解

入口

出口


5705371

迷宫问题 示例

4

3

5

2

1

7

6


5705371

小型迷宫

迷宫问题

4

3

5

2

1

7

6

路口 动作结果

1 (入口) 正向走 进到 2

2左拐弯 进到 3

3右拐弯 进到 4

4 (堵死) 回溯 退到 3

3 (堵死) 回溯 退到 2

2正向走 进到 5

5 (堵死) 回溯 退到 2

2右拐弯 进到 6

6左拐弯 进到7

(出口)

6

左 0 直 2右 0

行 3 5 6

0 0 4

0 0 0

0 0 0

7 0 0

7

小型迷宫的数据


5705371

设计算法判断一个算术表达式的圆括号是否正确配对

  • 提示: 对表达式进行扫描,凡遇到‘(’就进栈,遇‘)’就退掉栈顶的‘(’,表达式被扫描完毕,栈应为空。

  • 根据提示,可以设计算法如下:#include <string.h>#include “stack.h”int PairBracket( char *S){//检查表达式中括号是否配对int i;SeqStack openings; //定义一个栈InitStack (&T);for (i=0; i<strlen(S) ; i++){ if ( S[i]==‘(’ ) Push(& openings, S[i]); //遇‘(’时进栈if ( S[i]==‘)’ ) Pop(& openings); //遇‘)’时出栈 }return !EmptyStack(&T); // 由栈空否返回正确配对与否}


5705371

  • int main( )

    {Seq_Stack openings; InitStack (&openings);

    char symbol;

    bool is matched = true;

    while (is matched && (symbol = cin.get( )) != ‘\n’) {

    if (symbol == ‘{‘ || symbol ==‘(‘ || symbol == ‘[‘)

    Push(&openings, symbol);

    if (symbol == ‘}’ || symbol == ‘)’ || symbol == ‘]’) {

    if (EmptyStack(&openings )) {

    cout << "Unmatched closing bracket " << symbol

    << " detected." << endl;

    is matched = false;

    }

    else ……


5705371

else {

char match;

Get_top(openings, match);

Pop(openings);

is matched = (symbol == ‘}’ && match ==‘{‘)

|| (symbol == ‘)’ && match == ‘(‘)

|| (symbol == ‘]’ && match == ‘[‘);

if (!is matched)

cout << "Bad match " << match << symbol << endl;

}

}

}

if (!openings.empty( ))

cout << "Unmatched opening bracket(s) detected." << endl;

}


5705371

3.3 栈与递归的实现


5705371

递归的概念

  • 递归的定义 若一个对象部分地包含它自己, 或用它自己给自己定义, 则称这个对象是递归的;若一个过程直接地或间接地调用自己, 则称这个过程是递归的过程。

  • 在以下三种情况下,常常用到递归方法。

    • 定义是递归的

    • 数据结构是递归的

    • 问题的解法是递归的


5705371

定义是递归的

例如,阶乘函数

求解阶乘函数的递归算法

long Factorial (long n ) {

if ( n == 0 )return 1;

else return n*Factorial (n-1);

}


5705371

求解阶乘 n! 的过程


5705371

计算斐波那契数列的函数Fib(n)的定义

求解斐波那契数列的递归算法

longFib (longn ) { if ( n <= 1 )return n;else returnFib (n-1) + Fib (n-2);

}


5705371

数据结构是递归的

例如,单链表结构


Towers of hanoi

Towers of Hanoi

Rules: Move only one disk at a time.

No larger disk can be on top of a smaller disk.


5705371

问题的解法是递归的

汉诺塔(Tower of Hanoi)问题 (64)

规则:


5705371

求解方法


Program for hanoi main program

Program for HanoiMain program:

const int disks = 64; // Make this constant much smaller to run program.

void move(int count, int start, int nish, int temp);

main( )

{

move(disks, 1, 3, 2);

}


5705371

递归函数

void move(int count, int start, int finish, int temp)

{

if (count > 0) {

move(count - 1, start, temp, finish);

cout << "Move disk " << count << " from " << start<< " to " << nish << "." << endl;

move(count - 1, temp, finish, start);

}

}


5705371

Ackerman 函数定义如下:请写出递归算法。

n+1    当m=0时

AKM ( m , n ) = AKM( m-1 ,1) 当m≠0 ,n=0时

AKM( m-1, AKM( m,n-1)) 当m≠0, n ≠ 0时

解:算法如下

int AKM( int m, int n){ if ( m== 0) return n+1; if ( m<>0 && n==0 ) return AKM( m-1, 1); if ( m<>0 && n<>0 ) return AKM( m-1, AKM( m,

n-1));}


5705371

习题

1、设将整数1、2、3、4依次进栈,但只要出栈时栈非空,则可将出栈操作按任何次序夹入其中,请回答下有问题:

(1)若入栈次序为push(1),pop(),push(2,push(3),pop(),pop( ),push(4),pop( ),则出栈的数字序列为什么?

(2)能否得到出栈序列为1423和1432?并说明为什么不能得到或如何得到。

(3)请分析1、2、3、4的24种排列中,哪些序列可以通过相应的入出栈得到。


  • Login