您的位置:首页 > 理论基础 > 数据结构算法

复习数据结构---纯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>:

/*-----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++方便啊!!!!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: