一需求分析
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
一.需求分析:
(1)迷宫:以二维数组mzae[m+2][n+2]表示迷宫,其中:maze[0][j]和maze[m+1][j](0=<j=<n+1)及maze[i][0]和maze[i][n+1](0=<i=<m+1)为添加的一个外围墙。
数组中以元素值为’$’表示通道块,以’#’表示非通道块,限定迷宫的大小m,n=<10。
迷宫输入的时候由于每一行的输入是用一个字符数组接收所以输入的字符每行要输入长度为n+1的字符数组共输入m+1行,而且由于外围墙的原因所以输入的每一行第一个元素可随意输入。
迷宫的入口位置和出口位置的设定在本程序中只能通过在主函数中设定。
建立迷宫进行迷宫路径寻找后如找到路径则会按照从上至下一次输出路径出口至入口通道块的行竖坐标。
(2)二叉树:以二叉链表存储表示。
输入树的各个结点,并能够输出用不同方法遍历的遍历序列;分别建立建立二叉树存储结构的的输入函数、输出层序遍历序列的函数、输出先序遍历序列的函数。
二.概要设计:
迷宫:
typedef struct {
int x;//下标
int y;//下标
} DataType;
struct SeqStack { //序栈类型定义
int t; //示栈顶位置
DataType s[MAXNUM];
};
typedef struct SeqStack *PSeqStack; //序栈类型的指针类型
/***************建立迷宫****************/
void initmaze(maze[][N])
//建立迷宫
/*******************栈函数**********************/
PSeqStack createEmptyStack_seq()
//建立空栈
//若创建成功则返回栈的首地址,否则输出Out of space!!
int isEmptyStack_seq( PSeqStack pastack )
//判栈是否空
//若栈空则返回1,否则返回0
void push_seq( PSeqStack pastack, DataType x )
//在栈中压入一元素x,y,d
void pushtostack(PSeqStack st, x, y)
void pop_seq( PSeqStack pastack )
//删除栈顶元素
DataType top_seq( PSeqStack pastack )
//当pastack所指的栈不为空栈时,返回栈顶元素的值
void printpath(PSeqStack st)
//打印路径上的每一点
/*********************求迷宫的路径********************/
void mazePath(maze[][N], direction[4][2], x1, y1, x2, y2)
//求迷宫的路径如找到路径则调用printpath()输出路径,否则输出The path has not been found!
/***********************主函数********************/
int main(){
创建迷宫
求迷宫路径
return 0
}
(2)二叉树:
typedef struct node{
char data;
struct node *lchild,*rchild;
}BinTNode; //自定义二叉树的结点类型
typedef BinTNode *BinTree; //定义二叉树的指针
//==========基于先序遍历算法创建二叉树==============
//=====要求输入先序序列,其中加入虚结点"#"以示空指针的位置========== BinTree CreatBinTree(void)
//创建二叉树如果创建成功则返回二叉链表首地址,否则返回空指针
//========NLR 先序遍历=============
void Preorder(BinTree T)
//基于二叉链表对二叉树进行先序遍历
//=====采用后序遍历求二叉树的深度、结点数的递归算法========
int TreeDepth(BinTree T)
//基于二叉链表求树深算法求二叉树节点数目
//====利用"先进先出"(FIFO)队列,按层次遍历二叉树==========
void Levelorder(BinTree T)
//基于二叉链表对二叉树进行层序遍历
//==========主函数=================
void main()
{
建立二叉树
do { //从菜单中选择遍历方式,输入序号。
switch (i){
i为1时先序遍历
i为2时层序遍历
i为0时退出整个循环体
}
} while(i!=0)
}
三.详细设计:
迷宫:
#include <stdio.h>
#include <stdlib.h>
#define MAXNUM 100//栈中最大元素个数
#define N 10 //图的第一维长度
typedef struct {
int x;//下标
int y;//下标
} DataType;
struct SeqStack { //序栈类型定义
int t; //示栈顶位置
DataType s[MAXNUM];
};
typedef struct SeqStack *PSeqStack; //序栈类型的指针类型
/***************建立迷宫****************/
void initmaze(char maze[][N])
{
int i,j;
int m,n; //迷宫行,列
printf("请输入迷宫的行数 m=(m的值不能大于8):\n");
scanf("%d",&m);
printf("请输入迷宫的列数 n=(m的值不能大于8):\n");
scanf("%d",&n);
printf("\n请输入迷宫的各行各列(用空格隔开):\n <注意>:\n 1.输入$代表路.\n 2.输入#代表墙.\n");
for(i=1;i<=m;i++)
scanf("%s\n",&maze[i]);
printf("建立的迷宫为:\n");
for(i=0;i<=m+1;i++) //加一圈围墙
{
maze[i][0]='#';
maze[i][n+1]='#';
}
for(j=0;j<=n+1;j++)
{
maze[0][j]='#';
maze[m+1][j]='#';
}
for(i=0;i<=m+1;i++) //输出迷宫
{
for(j=0;j<=n+1;j++)
printf("%c ",maze[i][j]);
printf("\n");
}
}
/*******************栈函数**********************/
PSeqStack createEmptyStack_seq() {//建立空栈
PSeqStack pastack;
pastack = (PSeqStack)malloc(sizeof(struct SeqStack));
if (pastack == NULL)
printf("Out of space!! \n");
else
pastack->t = -1;
return pastack;
}
int isEmptyStack_seq( PSeqStack pastack ) {//判栈是否空
return pastack->t == -1;
}
void push_seq( PSeqStack pastack, DataType x ) {//在栈中压入一元素x,y,d
if( pastack->t >= MAXNUM - 1 )
printf( "Overflow! \n" );
else {
pastack->t++;
pastack->s[pastack->t] = x;
}
}
void pushtostack(PSeqStack st, int x, int y) {
DataType element;
element.x = x;
element.y = y;
push_seq(st, element);
}
void pop_seq( PSeqStack pastack ) {//删除栈顶元素
if (pastack->t == -1 )
printf( "Underflow!\n" );
else
pastack->t--;
}
DataType top_seq( PSeqStack pastack ) {//当pastack所指的栈不为空栈时,求栈顶元素的值
return (pastack->s[pastack->t]);
}
void printpath(PSeqStack st) {//打印路径上的每一点
DataType element;
printf("迷宫的一条符合要求的路径如下所示:\n");
while(!isEmptyStack_seq(st)) {
element = top_seq(st);
pop_seq(st);
printf("the node is: %d %d \n", element.x, element.y);
}
}
//*********************求迷宫的路径************************
void mazePath(char maze[][N], int direction[4][2], int x1, int y1, int x2, int y2) {
int i, j, k, g, h;
PSeqStack st;
DataType element;
st = createEmptyStack_seq( );
maze[x1][y1] = '#'; //从入口开始进入,作标记
pushtostack(st, x1, y1); //入口点进栈
while ( !isEmptyStack_seq(st)) { // 走不通时,一步步回退
element = top_seq(st);
pop_seq(st);
i = element.x; j = element.y;
for (k = 0; k <= 3; k++) { // 依次试探每个方向
g = i + direction[k][0];h = j + direction[k][1];
if (g == x2 && h == y2 && maze[g][h] =='$'){//走到出口点 pushtostack(st, i, j);
pushtostack(st, g, h);
printpath(st); // 打印路径
return;
}
if (maze[g][h] =='$') { // 走到没走过的点
maze[g][h] = '#';
pushtostack(st, i, j); // 进栈
i = g; j = h; k =-1; //下一点转换成当前点
}
}
}
printf("The path has not been found!\n");// 栈退完未找到路径
}
//****************************主函数**************************
int main(){
char maze[N][N];
initmaze(maze);
int direction[][2]={{0,1},{1,0},{0,-1},{-1,0}};
mazePath(maze,direction,1,1,8,8);
getchar();
return 0;
}
(2)二叉树:
#include"stdio.h"
#include"stdlib.h"
#define Max 20 //结点的最大个数
typedef struct node{
char data;
struct node *lchild,*rchild;
}BinTNode; //自定义二叉树的结点类型
typedef BinTNode *BinTree; //定义二叉树的指针
int NodeNum; //NodeNum为结点数
//==========基于先序遍历算法创建二叉树==============
//=====要求输入先序序列,其中加入虚结点"#"以示空指针的位置========== BinTree CreatBinTree(void)
{
BinTree T;
char ch;
if((ch=getchar())=='#')
return(NULL); //读入#,返回空指针
else{
T=(BinTNode *)malloc(sizeof(BinTNode)); //生成结点
T->data=ch;
T->lchild=CreatBinTree(); //构造左子树
T->rchild=CreatBinTree(); //构造右子树return(T);
}
}
//========NLR 先序遍历=============
void Preorder(BinTree T)
{
if(T) {
printf("%c",T->data); //访问结点
Preorder(T->lchild); //先序遍历左子树
Preorder(T->rchild); //先序遍历右子树
}
}
//=====采用后序遍历求二叉树的深度、结点数的递归算法======== int TreeDepth(BinTree T)
{
int hl,hr,max;
if(T){
hl=TreeDepth(T->lchild); //求左深度
hr=TreeDepth(T->rchild); //求右深度
max=hl>hr? hl:hr; //取左右深度的最大值NodeNum=NodeNum+1; //求结点数
return(max+1);
}
else return(0);
}
//====利用"先进先出"(FIFO)队列,按层次遍历二叉树========== void Levelorder(BinTree T)
{
int front=0,rear=1;
BinTNode *cq[Max],*p; //定义结点的指针数组cq
cq[1]=T; //根入队
while(front!=rear)
{
front=(front+1)%NodeNum;
p=cq[front]; //出队
printf("%c",p->data); //出队,输出结点的值
if(p->lchild!=NULL){
rear=(rear+1)%NodeNum;
cq[rear]=p->lchild; //左子树入队
}
if(p->rchild!=NULL){
rear=(rear+1)%NodeNum;
cq[rear]=p->rchild; //右子树入队
}
}
}
//==========主函数=================
void main()
{
BinTree root;
int i;
printf("\n");
printf("Creat Bin_Tree; Input preorder:"); //输入完全二叉树的先序序列,
// 用#代表虚结点,如ABD###CE##F##
root=CreatBinTree(); //创建二叉树,返回根结点
do { //从菜单中选择遍历方式,输入序号。
printf("\t********** select ************\n");
printf("\t1: Preorder Traversal\n");
printf("\t2: Level Depth\n"); //按层次遍历
printf("\t0: Exit\n");
printf("\t*******************************\n");
scanf("%d",&i); //输入菜单序号(0-2)
switch (i){
case 1: printf("Print Bin_tree Preorder: ");
Preorder(root); //先序遍历
break;
case 2: printf("LevePrint Bin_Tree: ");
TreeDepth(root);
Levelorder(root); //按层次遍历
break;
default: exit(1);
}
printf("\n");
} while(i!=0);
}
四.调试分析:
(1)迷宫:
测试数据:
8
8
#$$#$$$#$
#$$#$$$#$
#$$$$##$$
#$###$$$$
#$$$#$$$$
#$#$$$#$$
#$###$##$
##$$$$$$$
##$$$###$
测试输出的结果:
建立的迷宫为:
# # # # # # # # # #
# $ $ # $ $ $ # $ #
# $ $ # $ $ $ # $ #
# $ $ $ $ # # $ $ #
# $ # # # $ $ $ $ #
# $ $ $ # $ $ $ $ #
# $ # $ $ $ # $ $ #
# $ # # # $ # # $ #
# # $ $ $ $ $ $ $ #
# # # # # # # # # #
迷宫的一条符合要求的路径如下所示: the node is: 6 5
the node is: 6 4
the node is: 6 3
the node is: 5 3
the node is: 5 2
the node is: 5 1
the node is: 4 1
the node is: 3 1
the node is: 3 2
the node is: 2 2
the node is: 1 2
the node is: 1 1
Press any key to continue
时间复杂度分析:
本程序的时间复杂度为O(mxn)
(2).二叉树:
测试数据:
abc###de##f##
1
2
测试输出的结果:
Creat Bin_Tree; Input preorder:abc###de##f##
********** select ************
1: Preorder Traversal
2: Level Depth
0: Exit
*******************************
1
Print Bin_tree Preorder: abcdef
********** select ************
1: Preorder Traversal
2: Level Depth
0: Exit
*******************************
2
LevePrint Bin_Tree: abdcef
********** select ************
1: Preorder Traversal
2: Level Depth
0: Exit
*******************************
Press any key to continue
时间复杂度分析:
本程序的时间复杂度为O(MAX)
五.课设总结:
(1)设计时遇到的问题与自己解决的办法的设想及具体实现:
问题:
a.当前通道方块的四个方向如何有效简洁地表示和利用方位预测做下一步操作。
b.迷宫的建立问题。
解决设想:
a.第一个问题只需将满足题意的方块入栈并一直按照那个方向找下去如果没找
到则会由于弹栈的原因而回溯到最开始的那块的其他方向并会按前述过程一直找下去直到找遍所有可能的通道快。
b.简单地直接赋值,或用一个随机生成算法来随机生成迷宫。
在用输入的方式生成一个迷宫时由于主函数调用的原因需要在调用创建迷宫的函数时返回一个迷宫类型的指针来继续对迷宫路径的寻找。
(我实际没有用到这些,只是用了一个函数手动输入迷宫的,但是这是我的另外两条思路,不过简单赋值太简单了而随机算法实现起来又有点困难故采用了此种处理方法。
)
(2)感想及教训总结:
这次课程设计花了我整整一个星期去真正地设计数据结构和实现相应算法,虽然这两个问题在一些人看来实在是不怎么难,但是因为本人c语言功底不怎么扎实,自认为数据结构学的还可以,所以整个过程中设计部分比较容易就实现了而真的去实现自己的想法时却显得有点力不从心了。
所以大部分时间主要花在具体算法的实现,而且在写这个设计说明书由于操作word不慎的原因曾两次导致说明书写了一大半而不得不从头开始重新写,这是一个很痛苦的事,真的很深刻。
但是工作必须得继续下去,所以咬咬牙就继续坚持下来了,而到最后写完时可以说整个人都懵了。
但重点不在这里,我要表达的是,我确实在这次课程设计中学到了很多。
而且也清楚地了解到自己的不足之处在何处,我需要更多的针对性练习。
这一次由于基础的问题更难的想法就没有去实现了,但是基本的要求还算是实现了,这是我感到欣慰的,感觉到这几乎是第一次的自己一个人独自设计思考编写解决问题实现代码,但是我想我需要的是更多的练习来弥补自己的不足!。