• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录

Sunshine_Lin

  • 博客园
  • 联系
  • 订阅
  • 管理

公告

View Post

顺序栈的表示、实现和应用

顺序栈的实现和应用、递归算法

  从数据结构角度看,栈和队列也是线性表,其特殊性在于栈和队列的基本操作是线性表操作的子集,它们是操作受限的线性表,因此,可称为限定性的数据结构。但从数据类型角度看,它们是和线性表大不相同的两类重要的抽象数据结构。(数据结构:是相互之间存在一种或多种特定关系的数据元素的集合,等于数据元素的有限集+前者关系的优先级(集合、线性结构、树形结构、图状结构或网状结构);数据类型:一个值的集合和定义在这个值集上的一组操作的总称。)

1 抽象数据类型栈的定义

栈:是限定仅在表尾进行插入和删除操作的线性表(表头称为栈底,表尾称为栈顶)。

//栈的抽象数据类型的定义(ADT:是指一个数学模型以及定义在该模型上的一组操作):
ADT Stack{
数据对象:D={ai|ai属于ElemSet,i=1,2,...,n,n>=0}
数据关系:R1={<ai-1,ai>|ai-1, ai属于D,i=2,...,n}
约定an端为栈顶,a1端为栈底。
基本操作:InitStack(&S)
操作结果:构造一个空栈S。
DestroyStack(&S)
初始条件:栈S已存在
操作结果:栈S被销毁
ClearStack(&S)
初始条件:栈S已存在
操作结果:将S清为空栈
StackEmpty(S)
初始条件:栈S已存在
操作结果:若栈S为空栈,则返回TRUE,否则FALSE
StackLength(S)
初始条件:栈S已存在
操作结果:返回S的元素个数,即栈的长度
GetTop(S, &e)
初始条件:栈S已存在且非空
操作结果:用e返回S的栈顶元素
Push(&S, e)
初始条件:栈S已存在
操作结果:插入元素e为新的栈顶元素
Pop(&S, &e)
初始条件:栈S已存在且非空
操作结果:删除S的栈顶元素,并用e返回其值
StackTraverse(S, visit())
初始条件:栈S已存在并非空
操作结果:从栈底到栈顶依次对S的每个数据元素调用函数visit(),一旦visit()失败,则返回操作失败。
}ADT Stack

2 栈的表示和实现

2.1 顺序栈

栈的顺序存储结构是利用一组地址连续的存储单元依次存放自栈底到栈顶的数据元素,同时附设指针top指示栈顶元素在顺序栈中的位置。

 1 typedef struct{
 2     SElemType *base;    //栈底指针
 3     SElemType *top;        //栈顶指针
 4     int stackszie;        //栈的容量
 5 }SqStack;
 6 //==========================ADT Stack 的表现与实现===========================
 7 #define STACK_INIT_SIZE 100        //存储空间的初始分配量
 8 #define STACKINCREMENT 10        //存储空间分配增量
 9 typedef struct{
10     SElemType *base;    //在栈构造之前和销毁之后,base的值为NULL
11     SElemType *top;        //栈顶指针
12     int stacksize;        //当前已分配的存储空间,以元素为单位
13 }SqStack;
14 //----------------------------基本操作的函数原型说明-------------------------
15 Status InitStack(SqStack &S);//构造一个空栈S
16 Status DestroyStack(SqStack &S);//销毁S,S不再存在
17 Status ClearStack(SqStack &S);//把S置为空栈
18 Status StackEmpty(SqStack S);//若栈S为空栈,则返回TRUE,否则FALSE
19 int StackLength(SqStack S);//返回S的元素个数,即栈的长度
20 Status GetTop(SqStack S, SElemType &e);//用e返回S的栈顶元素
21 SElemType GetTop(SqStack S);//返回S的栈顶元素(重载)
22 Status Push(SqStack &S, SElemType e);//插入元素e为新的栈顶元素
23 Status Pop(SqStack &S, SElemType &e);//删除S的栈顶元素,并用e返回其值
24 Status StackTraverse(SqStack S, void (*visit)(SElemType));//从栈底到栈顶依次对S的每个数据元素调用函数visit(),一旦visit()失败,则返回操作失败。
25 //----------------------------基本操作的算法描述(部分)-----------------------
26 Status InitStack(SqStack &S){//构造一个空栈S
27     S.base=(SElemType *)malloc(STACK_INIT_SIZE*sizeof(SElemType));
28     if(!S.base) exit(OVERFLOW);    //分配存储空间失败
29     S.top=S.base;
30     S.stacksize=STACK_INIT_SIZE;
31     return OK;
32 }
33 
34 Status DestroyStack(SqStack &S){//销毁S,S不再存在
35     free(S.base);
36     S.base=S.top=NULL;
37     S.stacksize=0;
38     return OK;
39 }
40 
41 Status ClearStack(SqStack &S){//把S置为空栈
42     S.top=S.base;
43     return OK;
44 }
45 
46 Status StackEmpty(SqStack S){//若栈S为空栈,则返回TRUE,否则FALSE
47     if(S.base==S.top) return TRUE;
48     else return FALSE;
49 }
50 
51 int StackLength(SqStack S){//返回S的元素个数,即栈的长度
52     return (S.top-S.base);
53 }
54 
55 Status GetTop(SqStack S, SElemType &e){//用e返回S的栈顶元素
56     if(StackEmpty(S)) return ERROR;
57     e=*(S.top-1);
58     return OK;
59 }
60 
61 SElemType GetTop(SqStack S){//返回S的栈顶元素(重载)
62     if(!StackEmpty(S)) return *(S.top-1);
63 }
64 
65 Status Push(SqStack &S, SElemType e){//插入元素e为新的栈顶元素
66     if(S.top-S.base>=S.stacksize){
67         S.base=(SElemType *)realloc(S.base, (S.stacksize+STACKINCREMENT)*sizeof(SElemType));
68         if(!S.base) exit(OVERFLOW);
69         S.top=S.base+S.stacksize;
70         S.stacksize+=STACKINCREMENT;
71     }
72     *S.top++=e;
73     return OK;
74 }
75 
76 Status Pop(SqStack &S, SElemType &e){//删除S的栈顶元素,并用e返回其值
77     if(StackEmpty(S)) return ERROR;
78     e=*--S.top;
79     return OK;
80 }
81 
82 void visit(SElemType a){
83     printf("%d\n", a);
84 }
85 
86 Status StackTraverse(SqStack S, void (*visit)(SElemType)){//从栈底到栈顶依次对S的每个数据元素调用函数visit(),一旦visit()失败,则返回操作失败。
87     printf("Stack traverse:\n");
88     SElemType *p=S.base;
89     while(p!=S.top){
90         visit(*p++);
91     }
92     return OK;
93 }

3 栈的应用举例

3.1 数制转换

 1 void Conversion(){//对于输入的任意一个非负十进制整数,打印输出与其等值的八进制
 2     SqStack S; int e, Num;
 3     InitStack(S);
 4     scanf("%d", Num);
 5     while(Num){
 6         Push(S, Num%8);
 7         Num/=8;
 8     }
 9     while(!StackEmpty(S)){
10         Pop(S, e);
11         printf("%d", e);
12     }
13     printf("\n");
14 }

3.2 括号匹配的检验

 1 int Match(char ch, char str){//检查是否匹配
 2     if(ch=='(' && str==')')    return TRUE; 
 3     if(ch=='[' && str==']')    return TRUE; 
 4     if(ch=='{' && str=='}')    return TRUE; 
 5     return FALSE;
 6 }
 7 
 8 void BracketMatch(char *str){//str为输入的内容,检查括号是否匹配
 9     char ch;
10     SqStack S;
11     InitStack(S);
12     while(str[i]!='\0'){
13         switch str[i]{
14             case '(':
15             case '[':
16             case '{':Push(S, str[i]); break;
17             case ')':
18             case ']':
19             case '}':if(StackEmpty(S)){
20                         printf("括号不匹配!\n"); return;
21                     }else{
22                         GetTop(S, ch);
23                         if(Match(ch, str[i]))
24                             Pop(S, ch);
25                         else{
26                             printf("括号不匹配!\n");
27                             return;
28                         }
29                     }
30         }
31         i++;
32     }
33     if(StackEmpty(S)) printf("括号匹配\n");
34     else printf("括号不匹配!\n");
35 }

3.3 行编辑程序

 1 //在终端窗口有一新行,没有输入内容,输入Ctrl+D表示EOF
 2 //在终端窗口有一新行,有输入内容,输入两次Ctrl+D表示EOF
 3 void LineEdit(){
 4     SqStack S;
 5     InitStack(S);
 6     char c, ch=getchar();
 7     while(ch!=EOF){
 8         while(ch!=EOF && ch!='\n'){
 9             switch(ch){
10                 case '#':Pop(S, c);    break;
11                 case '@':ClearStack(S);    break;
12                 default :Push(S, ch);    break;
13             }
14             ch=getchar();
15         }
16         StackTraverse(S);
17         ClearStack(S);
18         if(ch!=EOF) ch=getchar();
19     }
20     DestroyStack(S);
21 }

3.4 迷宫求解

求迷宫中一条从入口到出口的路径的算法描述如下:
设定当前位置的初值为入口位置;
do{
    若当前位置可通;
    则{
        将当前位置插入栈顶;
        若当前位置是出口位置,则结束;
        否则切换当前位置的东邻方块为新的当前位置;
    }
    否则{
        若栈不空且栈顶位置尚有其他方向未经探索,
            则设定新的当前位置为沿顺时针方向旋转找到的栈顶位置的下一相邻块;
        若栈不空但栈顶位置的四周均不可通,
            则{
                删去栈顶位置;
                若栈不空,则重新测试新的栈顶位置,
                    直到找到一个可通的相邻块或出栈至栈空;
            }
    }
}while(栈不空);
 1 typedef struct{
 2     int ord;        //通道块在路径上的"序号"
 3     PosType seat;    //通道块在迷宫中的"坐标位置"(二维数组)
 4     int di;            //从此通道块走向下一通道块的"方向"
 5 }SElemType;
 6 
 7 Status MazePath(MazeType maze, PosType start, PosType end){
 8 //若迷宫maze中存在从入口start到出口end的通道,则求得一条存放在栈中(从栈底到栈顶),并返回TRUE;否则返回FALSE
 9     SqStack S;
10     InitStack(S);
11     SElemType e;
12     PosType curpos=start;    //设定"当前位置"为"入口位置"
13     int curstep=1;    //探索第一步
14     do{
15         if(Pass(curpos)){//当前位置可以通过,即是未走到过的通道块
16             FootPrint(curpos);    //留下足迹
17             e=(curstep, curpos, 1);
18             Push(S, e);    //加入路径
19             if(curpos==end) return TRUE;    //到达终点
20             curpos=NextPos(curpos, 1);    //下一位置是当前位置的东邻
21             curstep++;
22         }else{//当前位置不能通过
23             if(!StackEmpty(S)){
24                 Pop(S, e);
25                 while(e.di==4 && !StackEmpty(S)){
26                     MarkPrint(e.seat); Pop(S, e);//留下不能通过的标记,并退一步
27                 }
28                 if(e.di<4){
29                     e.di++;    Push(S, e);    //换下一个方向探索
30                     curpos=NextPos(e.seat, e.di);
31                 }
32             }
33         }
34     }while(!StackEmpty(S));
35     return FALSE;
36 }

3.5 表达式求值

为实现算符优先算法,可以使用两个工作栈。一个称做OPTR,用以寄存运算符;另一个称做OPND,用以寄存操作数或运算结果。算法的基本思想如下:
(1) 首先置操作数栈OPND为空栈,表达式起始符"#"为运算符栈OPTR的栈底元素;
(2) 依次读入表达式中每个字符,若是操作数则进OPND栈,若是运算符则和OPTR的栈顶元素符比较优先权后作相应操作,直至整个表达式求值完毕(即OPTR栈的栈顶元素和当前读入的字符均为"#")。

 1 int OperandType EvaluateExpression(){
 2 //算术表达式求值得算符优先算法。设OPTR和OPND分别为运算符栈和运算数栈,OP为运算符集合
 3     SqStack OPTR, OPND;
 4     InitStack(OPTR); InitStack(OPND);
 5     Push(OPTR, '#');
 6     char c=getchar();
 7     while(c!='#' || GetTop(OPTR)!='#'){
 8         if(!In(c, OP)){Push(OPND, c); c=getchar();}//不是运算符则进栈
 9         else{
10             switch(Precede(GetTop(OPTR), c)){
11                 case '<'://栈顶元素优先权低
12                         Push(OPTR, c); c=getchar();
13                         break;
14                 case '='://脱括号并接收下一字符
15                         Pop(OPTR, x); c=getchar();
16                         break;
17                 case '>'://退栈并将运算结果入栈
18                         Pop(OPTR, theta);
19                         Pop(OPND, b); Pop(OPND, a);
20                         Push(OPND, Operate(a, theta, b));
21                         break;
22             }
23         }
24     }
25     return GetTop(OPND);
26 }

4 栈与递归的实现

递归函数:一个直接调用自己或通过一系列的调用语句间接地调用自己的函数。
(1) 很多数学函数是递归定义的;
(2) 有的数据结构,如二叉树、广义表等,由于结构本身固有的递归特性,则它们的操作可递归地描述;
(3) 虽然问题本身没有明显的递归结构,但用递归求解比迭代求解更简单,如八皇后问题、Hanoi塔问题等。

4.1 n阶Hanoi塔

假设有3个分别命名为X、Y和Z的塔座,在塔座X上插有n个直径大小各不相同、依小到大编号1,2,...,n的圆盘。现要求将X轴上的n个圆盘移至塔座Z上并仍按同样顺序叠排,圆盘移动时必须遵循下列规则:
(1) 每次只能移动一个圆盘;
(2) 圆盘可以查在X、Y和Z中的任一塔座上;
(3) 任何时刻都不能将一个较大的圆盘压在较小的圆盘之上。

算法实现如下:

 1 void hanoi(int n, char x, char y, char z){
 2 //将塔座x上按直径由小到大且自上而下编号为1至n的n个圆盘按规则搬到塔座z上,y可做辅助塔座
 3 //搬动操作move(x, n, z)可定义为(c是初值为0的全局变量,对搬动计数);
 4 //printf("%i. Move disk %i from %c to %c\n", ++c, n, x, z);
 5     if(n==1) move(x, 1, z);//将编号为1的圆盘从x移动到z
 6     else{
 7         hanoi(n-1, x, z, y);//将x上编号从1到n-1的圆盘移至y,z作辅助塔
 8         move(x, n, z);//将编号为n的圆盘从x移到z
 9         hanoi(n-1, y, x, z);//将y上编号从1到n-1的圆盘移至z,x作辅助塔
10     }
11 }

5 source code

5.1 顺序栈的实现和应用(数值转换、括号匹配、行编辑程序、表达式求值、迷宫求解)

  1 #include <stdio.h>
  2 #include <malloc.h>
  3 #include <stdlib.h>
  4 #include <string.h>
  5 #include <time.h>
  6 
  7 #define TRUE         1
  8 #define FALSE         0
  9 #define OK            1
 10 #define ERROR        0
 11 #define INFEASSIBLE    -1
 12 #define OVERFLOW    -2
 13 
 14 typedef int Status;
 15 
 16 #define STACK_INIT_SIZE 100        //存储空间的初始分配量
 17 #define STACKINCREMENT 10        //存储空间分配增量
 18 
 19 // #define Int_Stack
 20 #define Char_Stack
 21 // #define Maze
 22 
 23 #ifdef Maze
 24 #define Maze_Size_X 5
 25 #define Maze_Size_Y 6
 26 typedef int MazeType[Maze_Size_X][Maze_Size_Y];
 27 typedef struct{
 28     int Pos_x;
 29     int Pos_y;
 30 }PosType;
 31 typedef struct{
 32     int ord;        //通道块在路径上的"序号"
 33     PosType seat;    //通道块在迷宫中的"坐标位置"(二维数组)
 34     int di;            //从此通道块走向下一通道块的"方向"
 35 }SElemType;
 36 #endif
 37 
 38 #ifdef Int_Stack
 39 typedef int SElemType;
 40 #endif
 41 
 42 #ifdef Char_Stack
 43 typedef char SElemType;
 44 #endif
 45 
 46 typedef struct{
 47     SElemType *base;    //在栈构造之前和销毁之后,base的值为NULL
 48     SElemType *top;        //栈顶指针
 49     int stacksize;        //当前已分配的存储空间,以元素为单位
 50 }SqStack;
 51 //----------------------------基本操作的函数原型说明-------------------------
 52 Status InitStack(SqStack &S);//构造一个空栈S
 53 Status DestroyStack(SqStack &S);//销毁S,S不再存在
 54 Status ClearStack(SqStack &S);//把S置为空栈
 55 Status StackEmpty(SqStack S);//若栈S为空栈,则返回TRUE,否则FALSE
 56 int StackLength(SqStack S);//返回S的元素个数,即栈的长度
 57 Status GetTop(SqStack S, SElemType &e);//用e返回S的栈顶元素
 58 SElemType GetTop(SqStack S);//返回S的栈顶元素(重载)
 59 Status Push(SqStack &S, SElemType e);//插入元素e为新的栈顶元素
 60 Status Pop(SqStack &S, SElemType &e);//删除S的栈顶元素,并用e返回其值
 61 Status StackTraverse(SqStack S, void (*visit)(SElemType));//从栈底到栈顶依次对S的每个数据元素调用函数visit(),一旦visit()失败,则返回操作失败。
 62 //----------------------------基本操作的算法描述(部分)-----------------------
 63 Status InitStack(SqStack &S)
 64 {//构造一个空栈S
 65     S.base=(SElemType *)malloc(STACK_INIT_SIZE*sizeof(SElemType));
 66     if(!S.base) exit(OVERFLOW);    //分配存储空间失败
 67     S.top=S.base;
 68     S.stacksize=STACK_INIT_SIZE;
 69     return OK;
 70 }
 71 
 72 Status DestroyStack(SqStack &S)
 73 {//销毁S,S不再存在
 74     free(S.base);
 75     S.base=S.top=NULL;
 76     S.stacksize=0;
 77     return OK;
 78 }
 79 
 80 Status ClearStack(SqStack &S)
 81 {//把S置为空栈
 82     S.top=S.base;
 83     return OK;
 84 }
 85 
 86 Status StackEmpty(SqStack S)
 87 {//若栈S为空栈,则返回TRUE,否则FALSE
 88     if(S.base==S.top) return TRUE;
 89     else return FALSE;
 90 }
 91 
 92 int StackLength(SqStack S)
 93 {//返回S的元素个数,即栈的长度
 94     return (S.top-S.base);
 95 }
 96 
 97 Status GetTop(SqStack S, SElemType &e)
 98 {//用e返回S的栈顶元素
 99     if(StackEmpty(S)) return ERROR;
100     e=*(S.top-1);
101     return OK;
102 }
103 
104 SElemType GetTop(SqStack S){//返回S的栈顶元素(重载)
105     if(!StackEmpty(S)) return *(S.top-1);
106 }
107 
108 Status Push(SqStack &S, SElemType e)
109 {//插入元素e为新的栈顶元素
110     if(S.top-S.base>=S.stacksize){
111         S.base=(SElemType *)realloc(S.base, (S.stacksize+STACKINCREMENT)*sizeof(SElemType));
112         if(!S.base) exit(OVERFLOW);
113         S.top=S.base+S.stacksize;
114         S.stacksize+=STACKINCREMENT;
115     }
116     *(S.top++)=e;
117     return OK;
118 }
119 
120 Status Pop(SqStack &S, SElemType &e)
121 {//删除S的栈顶元素,并用e返回其值
122     if(StackEmpty(S)) return ERROR;
123     e=*--S.top;
124     return OK;
125 }
126 
127 #ifdef Int_Stack
128 void visit(SElemType a)
129 {
130     printf("%d\n", a);
131 }
132 
133 Status StackTraverse(SqStack S, void (*visit)(SElemType))
134 {//从栈底到栈顶依次对S的每个数据元素调用函数visit(),一旦visit()失败,则返回操作失败。
135     printf("Stack traverse:\n");
136     SElemType *p=S.base;
137     while(p!=S.top){
138         visit(*p++);
139     }
140     return OK;
141 }
142 #endif
143 
144 #ifdef Char_Stack
145 void visit(SElemType a)
146 {
147     printf("%c", a);
148 }
149 
150 Status StackTraverse(SqStack S, void (*visit)(SElemType))
151 {//从栈底到栈顶依次对S的每个数据元素调用函数visit(),一旦visit()失败,则返回操作失败。
152     printf("Stack traverse(Stack Length: %d):\n", StackLength(S));
153     SElemType *p=S.base;
154     while(p!=S.top){
155         visit(*p++);
156     }
157     printf("\n");
158     return OK;
159 }
160 #endif
161 
162 #ifdef Maze
163 void visit(SElemType a)
164 {
165     printf("ord: %d\t(x, y):(%d, %d)\t%d\n", a.ord, a.seat.Pos_x, a.seat.Pos_y, a.di);
166 }
167 
168 Status StackTraverse(SqStack S, void (*visit)(SElemType))
169 {//从栈底到栈顶依次对S的每个数据元素调用函数visit(),一旦visit()失败,则返回操作失败。
170     printf("Stack traverse(Stack Length: %d):\n", StackLength(S));
171     SElemType *p=S.base;
172     while(p!=S.top){
173         visit(*p++);
174     }
175     printf("\n");
176     return OK;
177 }
178 #endif
179 //---------------------------------数制转换算法实现(部分)-----------------------
180 #ifdef Int_Stack
181 void Conversion(){//对于输入的任意一个非负十进制整数,打印输出与其等值的八进制
182     int e, Num;
183     SqStack S;
184     InitStack(S);
185     printf("请输入十进制数:");
186     scanf("%d", &Num);
187     while(Num){
188         Push(S, Num%8);
189         Num/=8;
190     }
191     printf("转换得到的八进制数:");
192     while(!StackEmpty(S)){
193         Pop(S, e);
194         printf("%d", e);
195     }
196     printf("\n");
197 }
198 #endif
199 
200 #ifdef Char_Stack
201 //----------------------------括号匹配的检验算法实现(部分)-----------------------
202 int Match(char ch, char str){//检查是否匹配
203     if(ch=='(' && str==')')    return TRUE; 
204     if(ch=='[' && str==']')    return TRUE; 
205     if(ch=='{' && str=='}')    return TRUE; 
206     return FALSE;
207 }
208 
209 void BracketMatch(){//str为输入的内容,检查括号是否匹配
210     int i=0;
211     char ch;
212     char *str;
213     printf("请输入括号序列:");
214     scanf("%s", str);
215     SqStack S;
216     InitStack(S);
217     while(str[i]!='\0'){
218         switch (str[i]){
219             case '(':
220             case '[':
221             case '{':Push(S, str[i]); break;
222             case ')':
223             case ']':
224             case '}':if(StackEmpty(S)){
225                         printf("括号不匹配!\n"); return;
226                     }else{
227                         GetTop(S, ch);
228                         if(Match(ch, str[i]))
229                             Pop(S, ch);
230                         else{
231                             printf("括号不匹配!\n");
232                             return;
233                         }
234                     }
235         }
236         i++;
237     }
238     if(StackEmpty(S)) printf("括号匹配!\n");
239     else printf("括号不匹配!\n");
240 }
241 
242 //---------------------------------行编辑程序算法实现(部分)-----------------------
243 // 在终端窗口有一新行,没有输入内容,输入Ctrl+D表示EOF
244 // 在终端窗口有一新行,有输入内容,输入两次Ctrl+D表示EOF
245 void LineEdit(){//利用字符栈,从终端接收一行并传送至调用过程的数据区
246     SqStack S;
247     InitStack(S);
248     char c, ch=getchar();
249     while(ch!=EOF){
250         while(ch!=EOF && ch!='\n'){
251             switch(ch){
252                 case '#':Pop(S, c);    break;
253                 case '@':ClearStack(S);    break;
254                 default :Push(S, ch);    break;
255             }
256             ch=getchar();
257         }
258         StackTraverse(S, visit);
259         ClearStack(S);
260         if(ch!=EOF) ch=getchar();
261     }
262     DestroyStack(S);
263 }
264 
265 //-----------------------------------表达式求值算法实现(部分)-----------------------
266 char oper[7]={'+', '-', '*', '/', '(', ')', '#'};//优先级由低到高
267 char PreResult[7][7]={
268 //     +      -    *    /    (      )    #
269     '>', '>', '<', '<', '<', '>', '>',    // +
270     '>', '>', '<', '<', '<', '>', '>',    // -
271     '>', '>', '>', '>', '<', '>', '>',    // *
272     '>', '>', '>', '>', '<', '>', '>',    // /
273     '<', '<', '<', '<', '<', '=', ' ',    // (
274     '>', '>', '>', '>', ' ', '>', '>',    // )
275     '<', '<', '<', '<', '<', ' ', '='    // #
276 };
277 
278 Status In(char ch, char *oper){//判断是否是运算符,是返回TRUE,否则FALSE
279     int i;
280     for(i=0; i<7; i++){
281         if(ch==oper[i]) break;
282     }
283     if(i<7 && i>=0) return TRUE;
284     else return FALSE;
285 }
286 
287 char Precede(char ch, char c, char *oper){
288     int i=0, j=0;
289     while(ch!=oper[i] || c!=oper[j]){
290         if(ch!=oper[i]) i++;
291         if(c !=oper[j]) j++;
292     }
293     return PreResult[i][j];
294 }
295 
296 int char2int(char a){
297     return (a-'0');
298 }
299 
300 char Operate(char a, char theta, char b){
301     int na=char2int(a);
302     int nb=char2int(b);
303     switch(theta){
304         case '+': return na+nb+'0';
305         case '-': return na-nb+'0';
306         case '*': return na*nb+'0';
307         case '/': return na/nb+'0';
308     }
309 }
310 
311 int EvaluateExpression(){
312 //算术表达式求值得算符优先算法。设OPTR和OPND分别为运算符栈和运算数栈,OP为运算符集合
313     printf("Please enter Expression(end with '#'):"); //例如3-2*1#  (注意操作数是一位十进制数)
314     SqStack OPTR, OPND;
315     InitStack(OPTR); InitStack(OPND);
316     Push(OPTR, '#');
317     char theta, b, a, x, c=getchar();
318     while(c!='#' || GetTop(OPTR)!='#'){
319         if(!In(c, oper)){//不是运算符则进栈
320             Push(OPND, c);    c=getchar();
321         }
322         else{
323             switch(Precede(GetTop(OPTR), c, oper)){
324                 case '<'://栈顶元素优先权低
325                         Push(OPTR, c); c=getchar();
326                         break;
327                 case '='://脱括号并接收下一字符
328                         Pop(OPTR, x); c=getchar();
329                         break;
330                 case '>'://退栈并将运算结果入栈
331                         Pop(OPTR, theta);
332                         Pop(OPND, b); Pop(OPND, a);
333                         Push(OPND, Operate(a, theta, b));
334                         break;
335             }
336         }
337     }
338     printf("Result: %d\n", GetTop(OPND)-'0');
339     return (GetTop(OPND)-'0');
340 }
341 #endif
342 
343 #ifdef Maze
344 //------------------------------------迷宫求解算法实现(部分)-----------------------
345 void ViewMaze(MazeType maze){
346     int i, j;
347     printf("Maze:\n");
348     for(i=0; i<Maze_Size_X; i++){
349         for(j=0; j<Maze_Size_Y; j++){
350             printf("%d\t", maze[i][j]);
351         }
352         printf("\n");
353     }
354 }
355 
356 Status CreateMaze(MazeType maze, PosType &start, PosType &end){//创建迷宫,可通过通道块为0,不可通过通道块为1,足迹为2, 不能走的通道块为3
357     int i, j, start_x, start_y, end_x, end_y;
358     srand(time(NULL));
359     for(i=0; i<Maze_Size_X; i++){
360         for(j=0; j<Maze_Size_Y; j++){
361             maze[i][j]=rand()%2;
362         }
363     }
364     printf("sizeof(MazeType):%d\n", sizeof(MazeType));
365     start_x=rand()%Maze_Size_X;
366     start_y=rand()%Maze_Size_Y;
367     do{
368         end_x=rand()%Maze_Size_X;
369         end_y=rand()%Maze_Size_Y;
370     }while(end_x==start_x && end_y==start_y);
371     start={start_x, start_y};    //设置起点和终点
372     end={end_x, end_y};
373     maze[start_x][start_y]=0;
374     maze[end_x][end_y]=0;
375     ViewMaze(maze);
376     return OK;
377 }
378 
379 Status Pass(MazeType maze, PosType curpos){//当前位置可以通过,即是未走到过的通道块
380     if(curpos.Pos_x>=0 && curpos.Pos_y>=0 && curpos.Pos_x<Maze_Size_X && curpos.Pos_y<Maze_Size_Y){
381         if(maze[curpos.Pos_x][curpos.Pos_y]==0) return TRUE;
382     }
383     return FALSE;
384 }
385 
386 Status FootPrint(MazeType maze, PosType curpos){//留下足迹
387     maze[curpos.Pos_x][curpos.Pos_y]=2;
388     return OK;
389 }
390 
391 PosType NextPos(PosType curpos, int di){//1:东邻  2:南邻  3:西邻  4:北邻
392     switch(di){
393         case 1:curpos.Pos_y++; return curpos;
394         case 2:curpos.Pos_x++; return curpos;
395         case 3:curpos.Pos_y--; return curpos;
396         case 4:curpos.Pos_x--; return curpos;
397     }
398 }
399 
400 Status MarkPrint(MazeType maze, PosType curpos){
401     maze[curpos.Pos_x][curpos.Pos_y]=3;
402 }
403 
404 Status MazePath(SqStack &S, MazeType maze, PosType start, PosType end){
405 //若迷宫maze中存在从入口start到出口end的通道,则求得一条存放在栈中(从栈底到栈顶),并返回TRUE;否则返回FALSE
406     printf("start:(%d, %d)\n", start.Pos_x, start.Pos_y);
407     printf("end:(%d, %d)\n", end.Pos_x, end.Pos_y);
408     SElemType e;
409     PosType curpos=start;    //设定"当前位置"为"入口位置"
410     int curstep=1;    //探索第一步
411     do{
412         if(Pass(maze, curpos)){//当前位置可以通过,即是未走到过的通道块
413             FootPrint(maze, curpos);    //留下足迹
414             e={curstep, curpos, 1};
415             Push(S, e);    //加入路径
416             if(curpos.Pos_x==end.Pos_x && curpos.Pos_y==end.Pos_y) return TRUE;    //到达终点
417             curpos=NextPos(curpos, 1);    //下一位置是当前位置的东邻
418             curstep++;
419         }else{//当前位置不能通过
420             if(!StackEmpty(S)){
421                 Pop(S, e);
422                 while(e.di==4 && !StackEmpty(S)){
423                     MarkPrint(maze, e.seat); Pop(S, e);//留下不能通过的标记,并退一步
424                 }
425                 if(e.di<4){
426                     e.di++;    Push(S, e);    //换下一个方向探索
427                     curpos=NextPos(e.seat, e.di);
428                 }
429             }
430         }
431     }while(!StackEmpty(S));
432     return FALSE;
433 }
434 #endif
435 
436 int main(int argc, char *argv[])
437 {
438     /* SqStack S;
439     SElemType tmp;
440     InitStack(S);
441     for(int i=0; i<10; i++){
442         Push(S, rand()%10);
443     }
444     StackTraverse(S, visit);
445     printf("Pop:\n");
446     for(int i=0; i<5; i++){
447         Pop(S, tmp);
448         printf("%d\n", tmp);
449     }
450     printf("After Pop:\n");
451     StackTraverse(S, visit);
452     printf("StackLength:%u\n", StackLength(S));
453     ClearStack(S);
454     printf("After ClearStack:\n");
455     StackTraverse(S, visit);
456      */
457 #ifdef Int_Stack
458     Conversion();
459 #endif
460 #ifdef Char_Stack
461     // BracketMatch();
462     // LineEdit();
463     EvaluateExpression();
464 #endif
465 #ifdef Maze
466     SqStack S;
467     InitStack(S);
468     MazeType maze;
469     PosType start, end;
470     CreateMaze(maze, start, end);
471     if(MazePath(S, maze, start, end)){
472         printf("MazePath exist!\n");
473     }else{
474         printf("MazePath does not exist!\n");
475     }
476     StackTraverse(S, visit);
477     ViewMaze(maze);
478 #endif
479     return 0;
480 }
View Code

5.2 n阶Hanoi塔的实现

 1 #include <stdio.h>
 2 
 3 void move(char x, int n, char z){//将编号为n的圆盘从x移到z
 4     static int c=0;
 5     printf("%i. Move disk %i from %c to %c\n", ++c, n, x, z);
 6 }
 7 
 8 void hanoi(int n, char x, char y, char z){
 9 //将塔座x上按直径由小到大且自上而下编号为1至n的n个圆盘按规则搬到塔座z上,y可做辅助塔座
10 //搬动操作move(x, n, z)可定义为(c是初值为0的全局变量,对搬动计数);
11 //printf("%i. Move disk %i from %c to %c\n", ++c, n, x, z);
12     if(n==1) move(x, 1, z);//将编号为1的圆盘从x移动到z
13     else{
14         hanoi(n-1, x, z, y);//将x上编号从1到n-1的圆盘移至y,z作辅助塔
15         move(x, n, z);//将编号为n的圆盘从x移到z
16         hanoi(n-1, y, x, z);//将y上编号从1到n-1的圆盘移至z,x作辅助塔
17     }
18 }
19 
20 int main(int argc, char *argv[]){
21     unsigned int n;
22     printf("Please enter the level number of the hanoi:");
23     scanf("%u", &n);
24     hanoi(n, 'a', 'b', 'c');
25     return 0;
26 }
View Code

 

posted on 2015-07-05 17:36  Sunshine_Lin  阅读(2408)  评论(0)    收藏  举报

刷新页面返回顶部
 
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3