复习数据结构---纯C编译栈及栈应用(迷宫)
2011-05-02 11:11
281 查看
这几天装了Ubuntu11.04,想试一下GCC编译C,以前也没试过在GCC编译一个像样的C程序。所以也挑了比较简单的栈来实现一下,在纯C的环境下编译,发现自己的问题还真是挺多的:
1. C没有bool这种类型,false和true不是C的关键字。在VC里面就是,那是VC自己加上去的。。。
2. 没有养成好习惯啊,指针、栈没有初始化就用。结果编译总是出现段错误,这是个悲剧,是数组越界还是非法使用指针抑或是指针没初始化?检查大半天,结果是没有初始化!!
3. 不得不说,指针还不能灵活使用啊!!!
4. 代码编排还有点乱。。。。
.............
废话少说,上代码,首先是一些状态的定义,考虑到以后要到,所以做成一个头文件<Status.h>:
栈的代码<Stack.h>:
用栈实现迷宫:
Ubuntu下用GCC纯C编译通过,绝无C++成分。。。。。现在才发现C++方便啊!!!!
1. C没有bool这种类型,false和true不是C的关键字。在VC里面就是,那是VC自己加上去的。。。
2. 没有养成好习惯啊,指针、栈没有初始化就用。结果编译总是出现段错误,这是个悲剧,是数组越界还是非法使用指针抑或是指针没初始化?检查大半天,结果是没有初始化!!
3. 不得不说,指针还不能灵活使用啊!!!
4. 代码编排还有点乱。。。。
.............
废话少说,上代码,首先是一些状态的定义,考虑到以后要到,所以做成一个头文件<Status.h>:
/*-----Status.h-----*/ #include<malloc.h> #define TRUE 1 #define FALSE 0 #define OK 1 #define ERROR 0 #define INFEASIBLE -1 #define OVERFLOW -2 typedef int Status;
栈的代码<Stack.h>:
/*-------Stack.h-----------*/ #include "Status.h" /******栈的数据结构定义********/ #define STACK_INIT_SIZE 100 //栈初始话的大小 #define STACKINCREMENT 10 //栈空间一次的增量 typedef struct{ StackElem *base; //栈底指针 StackElem *top; //栈顶指针 int stacksize; //栈空间的大小 }Stack; /******栈的基本操作********/ Status InitStack(Stack* s); //构造一个空栈 Status DestroyStack(Stack* s); //销毁一个空栈 Status ClearStack(Stack* s); //置空一个栈 Status StackEmpty(Stack const* s); //判断一个栈是否为空,参数也可以用Stack s,但是为了确保所有函数参数一致,用常量指针,下同 int StackLength(Stack const* s); //求栈的长度 Status Gettop(Stack const* s,StackElem *e); //获取栈顶元素 Status Push(Stack* s,StackElem e); //往栈添加一个元素 Status Pop(Stack* s,StackElem *e); //从栈取出一个元素 Status StackTra(Stack const* s,Status (*visit)(),int i); //用visit()函数遍历栈,每调用i次换一次行 /******栈的基本操作的实现********/ Status InitStack(Stack* s) { s->base=(StackElem*)malloc(STACK_INIT_SIZE*sizeof(StackElem)); if(!s->base) { printf("Out of memory!/n"); exit(OVERFLOW); } s->top=s->base; s->stacksize=STACK_INIT_SIZE; return OK; }//InitStack Status DestroyStack(Stack* s) { free(s->base); s->base=NULL; //注意就算free掉分配的空间,指针还是会指向哪里,为了不误用,干脆置为空指针。 s->stacksize=0; return OK; }//DestroyStack Status ClearStack(Stack* s) { if(!s->base) return ERROR; s->top=s->base; return OK; }//ClearStack Status StackEmpty(Stack const* s) { if(!s->base) return ERROR; return s->top==s->base?TRUE:FALSE; }//StakEmpty int StackLength(Stack const* s) { if(!s->base) return ERROR; return (s->top-s->base); }//StackLength Status Gettop(Stack const* s,StackElem *e) { if(!s->base||s->top==s->base) return ERROR; *e=*(s->top-1); return OK; }//Gettop Status Push(Stack* s,StackElem e) { if(!s->base) return ERROR; if((s->top-s->base)==s->stacksize) { s->base==(StackElem*)realloc(s->base,(STACK_INIT_SIZE+STACKINCREMENT)*sizeof(StackElem)); if(!s->base) { printf("Out of memory!/n"); exit(OVERFLOW); } s->top=s->base+s->stacksize; s->stacksize+=STACKINCREMENT; } *(s->top)++=e; return OK; }//Push Status Pop(Stack* s,StackElem *e) { if(!s->base||s->top==s->base) return ERROR; *e=*--s->top; return OK; }//POP Status StackTra(Stack const* s,Status (*visit)(StackElem e),int i) { if(!s->base||s->top==s->base) return ERROR; StackElem e; int j=0; StackElem *p=s->base; printf("/n"); while(p!=s->top) { e=*p++; if(!visit(e)) return ERROR; j++; if(j%i==0) printf("/n"); } printf("/n"); return OK; }//StackTra
用栈实现迷宫:
/*------maze.c-------*/ #include<stdio.h> #define BLOCK 0 #define THROUGH 1 #define ENTRY 2 #define OUT 3 #define UP 1 #define DOWN -1 #define LEFT -1 #define RIGHT 1 //迷宫一个点的数据 typedef struct { int x; //迷宫的横坐标 int y; //迷宫的纵坐标 int up; //标志是否走过迷宫这点向上的方向,下同 int down; int left; int right; }mazePoint; typedef struct { int** data; /*一个二维数组,储存迷宫的数据。 *0(BLOCK)表示有障碍,不可通行。 *1(THROUGH)表示可以通行。 *2(ENTRY)表示入口。 *3(OUT)表示出口。*/ int rowmax; //标志迷宫的行数 int colmax; //标志迷宫的列数 }maze; //下面的两句话的顺序一定不能变,而且一定是在这里的,具体为啥,自己想去 #define StackElem mazePoint #include"Stack.h" maze InitMaze(int (*),int row,int col); //初始化一个迷宫,用一维数据初始化迷宫数据 //为啥不用二维数组? //二维数组至少给出列数,限制迷宫列数,所以不用。 void PrintMaze(maze ma); //打印一个迷宫 Status FindWay(Stack* s,maze ma); //找一条可以通过迷宫的路。 //找到,返回TRUE,反之,返回ERROR。 Status PrintPoint(mazePoint mp); //打印一个点,配合StackTra打印出路径。 //这里只是示范StackTra函数怎么用,其实自己写个打印路径的函数更好点 int main() { //约定一下,迷宫最外层必须为0,主要是不想检测数据是否越界,偷懒^_^ int mazedata[9*10]={0,0,0,0,0,0,0,0,0,0, 0,2,0,1,1,0,1,0,3,0, 0,1,1,1,0,1,1,0,1,0, 0,1,0,0,0,0,1,0,1,0, 0,1,1,1,1,1,1,0,1,0, 0,1,1,1,0,1,0,1,1,0, 0,0,0,1,0,1,0,1,0,0, 0,0,0,1,0,1,1,1,0,0, 0,0,0,0,0,0,0,0,0,0,}; //初始话迷宫 maze ma=InitMaze(mazedata,9,10); //打印迷宫 printf("This is your maze:/n"); PrintMaze(ma); //定义栈,栈函数的参数必须为栈指针,指针必须要指向一个栈 Stack s,*sp; sp=&s; //不要忘了这一步!!!这步害我调试了N个hours!! InitStack(sp); //visit函数定义,及指向 Status (*visit)(mazePoint mp); visit=PrintPoint; if(FindWay(sp,ma)) { printf("This is a way out of your maze:/n"); StackTra(sp,visit,5); } //不想写一个DestroyMaze的函数了,释放空间 free(ma.data); DestroyStack(sp); return 0; } maze InitMaze(int *mazedata,int row,int col) { int i,j; maze ma; //分配迷宫的行数的空间 ma.data=(int **)malloc(row*sizeof(int)); if(!ma.data) { printf("Out of Memory!/n"); exit(OVERFLOW); } //为迷宫每一行申请col列空间 for(i=0;i<row;i++) { ma.data[i]=(int *)malloc(col*sizeof(int)); if(!ma.data[i]) { printf("Out of memory!/n"); exit(OVERFLOW); } } //从一维数组复制数据到迷宫 for(i=0;i<row;i++) for(j=0;j<col;j++) ma.data[i][j]=mazedata[i*col+j]; ma.rowmax=row; ma.colmax=col; return ma; } void PrintMaze(maze ma) { int i,j; printf("/n"); //把列数据横着打,更直观 for(j=ma.colmax-1;j>=0;j--) { printf("%3d",j); for(i=0;i<ma.rowmax;i++) { if(ma.data[i][j]==BLOCK) printf(" #"); else if(ma.data[i][j]==THROUGH) printf(" "); else if(ma.data[i][j]==ENTRY) printf(" E"); else printf(" O"); } printf("/n"); } printf(" "); for(i=0;i<ma.rowmax;i++) printf("%3d",i); printf("/n"); } Status FindWay(Stack* s,maze ma) { int i,j; mazePoint mp; mazePoint *sp=∓ //找出迷宫的入口 for(i=1;i<ma.rowmax;i++) for(j=1;j<ma.colmax;j++) if(ma.data[i][j]==ENTRY) { mp.x=i; mp.y=j; mp.up=mp.down=mp.left=mp.right=FALSE; Push(s,mp); goto outside; //goto语句比较少用,但是对于跳出多层循环挺好用的 } outside:; //找到入口,跳到这里了。 while(ma.data[mp.x][mp.y]!=OUT&&Pop(s,sp)) { //在栈里面取出一个点,分别验证它的上下左右是否可走,可以,两个点一起入栈 //取出的点这个方向没走过,而且这个方向上的点不是BLOCK if(mp.up!=TRUE&&ma.data[mp.x][mp.y+UP]!=BLOCK) { //这里其实可以分一个函数写,不想麻烦,看起来也直观 mp.up=TRUE; Push(s,mp); //新入栈的点的一个方向也必须标志尝试过 mp.y+=UP; mp.down=TRUE; mp.left=mp.right=mp.up=FALSE; Push(s,mp); } else if(mp.down!=TRUE&&ma.data[mp.x][mp.y+DOWN]!=BLOCK) { mp.down=TRUE; Push(s,mp); mp.y+=DOWN; mp.up=TRUE; mp.left=mp.right=mp.down=FALSE; Push(s,mp); } else if(mp.left!=TRUE&&ma.data[mp.x+LEFT][mp.y]!=BLOCK) { mp.left=TRUE; Push(s,mp); mp.x+=LEFT; mp.right=TRUE; mp.up=mp.down=mp.left=FALSE; Push(s,mp); } else if(mp.right!=TRUE&&ma.data[mp.x+RIGHT][mp.y]!=BLOCK) { mp.right=TRUE; Push(s,mp); mp.x+=RIGHT; mp.left=TRUE; mp.up=mp.down=mp.right=FALSE;; Push(s,mp); } //四个方向都不可走,而且回到了起点,那就是没路可走了 else if(i==mp.x&&j==mp.y) { printf("This is no way out of this maze!/n"); return ERROR; } } return OK; } Status PrintPoint(mazePoint mp) { printf("(%d,%d)-->",mp.x,mp.y); }
Ubuntu下用GCC纯C编译通过,绝无C++成分。。。。。现在才发现C++方便啊!!!!
相关文章推荐
- 一步一步复习数据结构和算法基础-栈的简单应用(1)
- 数据结构复习_栈和队列,应用_括号匹配&文件目录递归拷贝,
- 《数据结构》(C语言版)——栈的应用举例-迷宫求解
- 数据结构-stack栈应用(走迷宫)
- 数据结构应用实例#栈#迷宫寻路
- 一步一步复习数据结构和算法基础-栈的应用(2)
- 数据结构的应用——使用栈实现任意迷宫的求解
- 数据结构的应用------------迷宫求解
- 数据结构复习 队列(迷宫)
- 数据结构应用:利用栈破解迷宫游戏
- 重温数据结构-栈的应用:进制转换,括号匹配检测,行编辑,迷宫求解,求表达式的值
- 数据结构::迷宫(二)--栈的一个应用(求迷宫最短路径)
- 数据结构::迷宫(一)--栈的一个应用
- 数据结构:栈的应用(迷宫的求解)
- 数据结构(ZKNU OJ) 迷宫(栈的应用)解题报告
- 数据结构 栈的应用 -- 迷宫的实现
- 复习(数据结构:java):线性表(数组):泛型的写法
- 数据结构在.net加密解密反流程混淆中的应用[看雪学院2006金秋读书季]
- 数据结构常用算法复习---快速排序
- 数据结构 用栈解迷宫源代码