顺序栈的表示、实现和应用
从数据结构角度看,栈和队列也是线性表,其特殊性在于栈和队列的基本操作是线性表操作的子集,它们是操作受限的线性表,因此,可称为限定性的数据结构。但从数据类型角度看,它们是和线性表大不相同的两类重要的抽象数据结构。(数据结构:是相互之间存在一种或多种特定关系的数据元素的集合,等于数据元素的有限集+前者关系的优先级(集合、线性结构、树形结构、图状结构或网状结构);数据类型:一个值的集合和定义在这个值集上的一组操作的总称。)
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 }
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 }
posted on 2015-07-05 17:36 Sunshine_Lin 阅读(2408) 评论(0) 收藏 举报