数据结构(图的遍历和马踏棋盘算法)
图的遍历
有两种方法:深度优先,广度优先
深度优先遍历
- 约定左手原则,在没有遇到重复顶点的情况下,分叉路口是从向右手边走,每走过一个顶点就做一个记号
- 如果分叉路所通向的结点已经全部走过,则返回上一个结点(回溯)
- 由此方法,直到返回这个顶点是结束
邻接矩阵中实现思路:
- 从A[0][0]开始,连向第一行中的第一个为1的元素A[ i ][ j ];
- 然后跳到第 j 行继续找到第一个为1的元素,并确定这个元素是否走过,如果走过,则返回上一次跳转的行;第0行所对应结点全部走过
代码实现
#include <stdio.h> #include <malloc.h> #define SIZE 9 void user(char *lin,int n){ printf("%c ",lin[n]); } void depthTraversal(char *lin,int (*arr)[SIZE],int n){ int i=0,j=n; static int tab[]={0,0,0,0,0,0,0,0,0}; tab[j]=1; user(lin,j); for(i=0;i<SIZE;i++){ if(i==j) continue; if(*(*(arr+j)+i)==1 && tab[i]==0) depthTraversal(lin,arr,i); } } void main(){ char lin[]={‘A‘,‘B‘,‘C‘,‘D‘,‘E‘,‘F‘,‘G‘,‘H‘,‘I‘}; int arr[9][9]={ {0,1,0,0,0,1,0,0,0}, {1,0,1,0,0,0,1,0,1}, {0,1,0,1,0,0,0,0,1}, {0,0,1,0,1,0,1,1,1}, {0,0,0,1,0,1,0,1,0}, {1,0,0,0,1,0,1,0,0}, {0,1,0,1,0,1,0,1,0}, {0,0,0,1,1,0,1,0,0}, {0,1,1,1,0,0,0,0,0} }; depthTraversal(lin,arr,0); printf("\n"); }
马踏棋盘算法
问题概述:在国际棋盘(8*8)中将‘马’放在任意指定的方框中,按照‘马’走‘日’的规则将马进行移动。要求每个方格只能进入一次,最终使马走遍棋盘64个方格。
解决方法:利用深度遍历的方法(回溯);使马遇到死路时就回溯,直到走遍棋盘;
注:在(n*n)的棋盘上,当 n ≥ 5且为偶数时,以任一点都有解
#include <stdio.h> #include <malloc.h> #define X 8 #define Y 8 int arr[X][Y]; int nextxy(int *x,int*y,int count){ switch(count){ case 0: if(*x+2<=X-1 && *y-1>=0 && arr[*x+2][*y-1]==0){ *x+=2; *y-=1; return 1; } break; case 1: if(*x+2<=X-1 && *y+1<=Y-1 && arr[*x+2][*y+1]==0){ *x+=2; *y+=1; return 1; } break; case 2: if(*x+1<=X-1 && *y-2>=0 && arr[*x+1][*y-2]==0){ *x+=1; *y-=2; return 1; } break; case 3: if(*x+1<=X-1 && *y+2<=Y-1 && arr[*x+1][*y+2]==0){ *x+=1; *y+=2; return 1; } break; case 4: if(*x-2>=0 && *y-1>=0 && arr[*x-2][*y-1]==0){ *x-=2; *y-=1; return 1; } break; case 5: if(*x-2>=0 && *y+1<=Y-1 && arr[*x-2][*y+1]==0){ *x-=2; *y+=1; return 1; } break; case 6: if(*x-1>=0 && *y-2>=0 && arr[*x-1][*y-2]==0){ *x-=1; *y-=2; return 1; } break; case 7: if(*x-1>=0 && *y+2<=Y-1 && arr[*x-1][*y+2]==0){ *x-=1; *y+=2; return 1; } break; default: break; } return 0; } void Print(){ int i,j; for(i=0;i<X;i++){ for(j=0;j<Y;j++){ printf("%d\t",arr[i][j]); } printf("\n"); } printf("\n"); } //(x,y)为位置坐标 //tag是标记变量,也用于记录步骤 int TravelBoard(int x,int y,int tag){ int x1=x,y1=y; int i=0; int flag=0;//记录当前位置的选者是否会导致失败 arr[x][y]=tag; if(X*Y==tag){ Print();//打印 return 1; } //找到马下一个可走的坐标(x1,y1),如果找到flag=1,否者为0 flag=nextxy(&x1,&y1,i); while(0==flag &&i<8){ i++; flag=nextxy(&x1,&y1,i); } while(flag){//这里的flag记录是否结束(失败) if(TravelBoard(x1,y1,tag+1)){ return 1; } //这个位置会导致后面碰壁失败,需要回溯到上个位置 x1=x; y1=y; i++; flag=nextxy(&x1,&y1,i); while(0==flag &&i<8){ i++; flag=nextxy(&x1,&y1,i); } } if(flag==0){ arr[x][y]=0; } return 0; } void main(){ int i,j; for(i=0;i<X;i++){ for(j=0;j<Y;j++){ arr[i][j]=0; } } printf("请输入起始位置的行:"); scanf("%d",&i); printf("请输入起始位置的列:"); scanf("%d",&j); //建议用两行一列测试 if(!TravelBoard(i,j,1)){ printf("马踏棋盘失败"); } }
广度优先遍历
其实广度优先遍历,类似与树的层序遍历
方法:
- 任意选一顶点,放入队列中;
- 在队列中让第一个位置进行操作,遍历这个顶点的所有连接的顶点,依次加入到这个队列中(加入时做好标记以免重复添加);删除刚刚操作的队头顶点
- 重复 ② 步骤,直到队列中全部结点出队列
相关推荐
waitwolf 2020-07-30
roseying 2020-07-04
hugebawu 2020-10-12
koushr 2020-11-12
zhangxiafll 2020-11-13
kikaylee 2020-10-31
范范 2020-10-28
MILemon 2020-10-22
LauraRan 2020-09-28
shenwenjie 2020-09-24
omyrobin 2020-09-23
guangcheng 2020-09-22
qiangde 2020-09-13
hanyujianke 2020-08-18
晨曦之星 2020-08-14
xiesheng 2020-08-06
KAIrving 2020-08-02
xiesheng 2020-08-02