This presentation is the property of its rightful owner.
1 / 46

# 第三章 栈和队列 PowerPoint PPT 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 - - - - - - - - - - - - - - - - - - - - - - - - - -

• 栈的应用举例

• 队列

### 栈

㈠栈： 在表的某一端进行插入和删除操作的

an

an

:

:

a2

a2

a1

a1

InitStack (&s)

DestroyStack(& s)

ClearStack(& s)

StackEmpty(s )

StackLength(s)

GetTop(S, &e)

Push(&s, e)

Pop (&s ,&e)

StackTraverse(S,visit())

⑴顺序存储结构

⑵链式存储结构

1.顺序存储结构：利用一组地址连续的存储单元

SElemType *base;

SElemType *top;

int stacksize;

}SqStack;

top

top

top

top

base

base

base

base

#define STACK_INIT_SIZE 100; //存储空间初始分配量

#define STACKINCREMENT 10; //存储空间分配增量

Typedef struct {

SElemType * base; //在栈构造之前和销毁之后，

base的值为NULL

SElemType * top; //栈顶指针

int stacksize;

//当前已分配的存储空间，以元素为单位

}SqStack;

Status InitStack (SqStack &s);

//构造一个空栈S

Status DestroyStack (SqStack &s);

//销毁栈S，S不再存在

Status ClearStack(SqStack &s);

//把S置为空栈

Status StacjEmpty(SqStack s);

//若栈S为空栈，则返回TRUE,否则返回FALSE

Int StackLength(SqStack s);

StatusGetTop(SqStack s,SElemType &e);

//若栈 不为空，则用e返回S的栈顶元素，并返回OK;否则返回ERROR

Status PUSH(SqStack &s,SElemType &e);

//插入元素e为新的栈顶元素

Status POP(SqStack &s,SElemType &e);

//若栈不空，则删除S的栈顶元素，用e返回其值，并返回OK;否则返回ERROR

Status StackTraverse(SqStack &s,Status(*visit)());

//从栈底到栈顶依次对栈中的每个元素调用函数visit()。一旦visit()失败，则操作失败

//------基本操作的算法描述（部分)------

Status InitStack(SqStack &s){

//构造一个空栈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;

}//InitStack

StatusGetTop(SqStack s,SElemType &e){

//若栈 不为空，则用e返回S的栈顶元素，并返回OK;否则返回ERROR

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

e=*(S.top-1);

return OK;

} //GetTop

Status PUSH(SqStack &s,SElemType &e){

//插入元素e为新的栈顶元素

if (S.top-s.base>=s.stacksize){//栈满，追加存储空间

S.base=(ElemType *) realloc (s.base,(s.stacksize+CREMENT)*sizeof(elemtype) );

If(!S.base) exit (OVERFLOW);//存储分配失败

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

s.stacksize+=STACKINCREMENT;

}

*S.top++=e;

Return OK;

}//Push

Status POP(SqStack &s,SElemType &e);

//若栈不空，则删除S的栈顶元素，用e返回其值，并返回OK;否则返回ERROR

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

e=*--s.top;

return OK;

}//Pop

data

next

S

### 栈的应用举例

N=(N div d) ×d + N mod d (其中：div为整除运算，mod

N N div 8 N mod 8

1348 168 4

168 21 0

21 2 5

2 0 2

void conversion （ ）{

//对于输入的任意一个非负十进制整数，打印输出与其等值的八进制

InitStack( s); //构造空栈

scanf (“% d”,N);

While (N) {

push (s, n% 8);

N=N/8;

}

While (! StackEmpty ) {

pop(s,e);

printf( “% d”, e);

}

}//conversion

Void LinEdit ( ) {

//利用字符栈S，从终端接收一行并传送至调用过程的数据区

InitStack( S);//

Ch=getchar( ); //从终端接收第一个字符

While (ch !=EOF) {//EOF 为全文结束符

while (ch!=EOF &&ch !=‘\n’) {

switch (ch) {

case ‘#’: Pop (s,c); break; //仅当栈非空时退栈

case ‘@’:ClearStack (s); break;//重置S为空栈

default :push(S, ch);break;//有效字符进栈，未考虑栈满情况

}

ch=getchar( );//从终端接收下一个字符

}

ClearStack (S);//重置S为空栈

if (ch !=EOF) ch=getchar();

}

DestroyStack(S);

}//LineEdit

⑵从左算到右

⑶先括号内，后括号外，算符优先

⑴首先置操作数栈为空栈，表达式起始符“#”为运算符栈的栈底元素

⑵依次读入表达式中每个字符，若是操作数则进OPND栈，

⒈栈顶运算符<输入运算符优先级，输入运算符入栈，读下一个字符

⒉栈顶运算符=输入运算符优先级，是( ) 脱()，‘(’ 出栈并抛弃

3.栈顶运算符>输入运算符，从OPND栈中出两个操作运算符出栈，对栈顶运算符进行运算，将结果入OPND栈

θ1 <θ2 θ1 的优先权低于θ2

θ1 =θ2 θ1 的优先权等于θ2

θ1 >θ2 θ1 的优先权高于θ2

θ 2

+ - * / ( ) #

θ 1

.

OperandType EvaluateExpression() {

//算术表达式求值的算符优先算法

//OP为运算符集合

InitStack (OPND); push (OPTR,’#’);

InitStack (OPND); c=getchar( );

While(c!=‘#’||GetTop(OPND)!=‘#’) {

if (! In(c,Op)) {Push ((OPND, c); c=getchar( ); }

//不是运算符则进栈

}//while

return GetTop(OPND);

}//EvaluateExpression

else

switch (Precede(GetTop(OPND),c) {

case ‘<‘: //栈顶元素优先权低

push (OPTR,c); c=getchar();

break;

Case ‘=‘ : //脱括号并接收下一字符

Pop(OPTR,x); c=getchar();

break;

case ‘>’ //退栈并将运算结果入栈

Pop(OPTR,theta);

pop(OPND,b); pop(OPND,a);

push(OPND, operate(a,theta,b));

break;

}//switch

### 队列（Queue)

a1

a2

a3

an

,n}约定其中ai端为队列头,an端为队列尾。

Initqueue(&Q)

DestroyQueue(&Q)

ClearQueue(&Q)

QueueEmpty(Q)

FALSE。

QueueLength(Q)

EnQueue(&Q,e)

DeQueue(&Q,&e)

QueueTraverse(Q,visit())

a1

a2

a3

an

data

next

Q.front

⑴链队列—队列的链式表示和实现

⑵循环队列—队列的顺序表示和实现

Q.rear

Q.front

Q.rear

Q.front

Q.rear

Q.front

Q.rear

Q.front

Q.rear

Typedef struct QNode{

QElemType data;

struct Qnode *next;

}Qnode , *QueuePtr;

Typedef struct{

QueuePtr front;

QueuePtr rear;

//---------------基本操作的函数原型说明--------------------

//构造一个空队列Q

//销毁队列Q,Q不再存在

//将Q清为空队列

//若队列Q为空队列，则返回TRUE,否则返回FALSE

//返回Q的元素个数，即为队列的长度

//若队列不空，则用e返回Q的队头元素，并返回OK;否则返回ERROR

//插入元素e为Q的新的队尾元素

//若队列不空，则删除Q的队头元素，用e 返回其值，并返回OK;

//否则返回ERROR

//从队头到队尾依次对队列Q中每个元素调用函数visit()。一旦visit失败，则操作失败。

//---------基本操作的算法描述（部分）-----------------

//构造一个空队列Q

Q.front = Q.rear = (QueuePtr)malloc(sizeof(Qnode));

if (!Q.front) exit(OVERFLOW);

Q.front —> next = NULL;

return OK;

}

//销毁队列Q

while (Q.front) {

Q.rear = Q.front -> next;

free (Q.front);

Q.front = Q.rear;

}

return OK;

}

//插入元素e为Q的新的队尾元素

p = (QueuePtr) malloc (sizeof(Qnode));

if (!p) exit (OVERFLOW); //存储分配失败

p -> data = e; p->next = NULL;

Q.rear->next = p;

Q.rear = p;

return OK;

}

//若队列不空，则删除Q的队头元素，用e返回其值，

//并返回OK;否则返回ERROR

if (Q.front = = Q.rear) return ERROR;

p = Q.front -> next;

e = p -> data;

Q.front -> next = p -> next;

if (Q.rear = = p) Q.rear = Q.front;

free(p);

return OK;

}

Q.rear表示指向队尾元素下一个位置

“队列头指针在队列尾指针的下一

Q.rear=(Q.rear+1) % maxsize

Q.front=(Q.front+1) % maxsize

Maxsize-1

0

1

Q.rear

Q.front

Q.rear

5

Q.front

4

Q.rear

Q.rear

3

Q.front

2

1

Q.rear

0

Q.front

Q.front

J1,J2,J3

J1,J2

J4,J5,J6

J4被删除

Q.front

Q.rear

5

0

Q.rear

4

1

J5

3

2

5

0

J4

4

1

2

3

J3

J5

5

J6

J4

0

4

3

1

2

J7

J3

Q.front

Q.front

J8

Q.rear

//-----------循环队列——队列的顺序存储结构---------

#define MAXQSIZE 100 //最大队列长度

Typedef struct {

QElemType *base; //初始化的动态分配存储空间

int front; //头指针，若队列不空，指向队列头元素

int rear; // 尾指针，若队列不空，指向队列尾元素的下一个位置

}SqQueue;

//--------------循环队列的基本操作的算法描述-----------

Status InitQueue(SqQueue &Q) {

// 构造一个空队列Q

Q.base = (ElemType * ) malloc (MAXQSIZE * sizeof

(ElemType));

if (!Q.base) exit (OVERFLOW); //存储分配失败

Q.front = Q.rear = 0;

return OK;

}

Int QueueLength (SqQueue Q) {

//返回Q的元素个数，即队列的长度

return (Q.rear – Q.front +MAXSIZE) % MAXSIZE;

}

Status EnQueue (SqQueue &Q,QElemType e){

//插入元素e为Q的新的队尾元素

if (( Q.rear +1) % MAXQSIZE = = Q.front)

return ERROR; //队列满

Q.base[Q.rear] = e;

Q.front = (Q.front + 1) % MAXQSIZE;

return OK;

}

Statue DeQueue (SqQueue &Q,QElemType &e) {

//若队列不空，则删除Q的队头元素，用e返回其值，

//并返回OK; 否则返回ERROR

if (Q.front = = Q.rear) return ERROR;

e = Q.base[Q.front];

Q.front = (Q.front + 1) % MAXQSIZE;

return OK;

}