shenwenjie 2020-05-09
图的遍历
有两种方法:深度优先,广度优先
深度优先遍历
邻接矩阵中实现思路:
代码实现
#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("马踏棋盘失败"); } }
广度优先遍历
其实广度优先遍历,类似与树的层序遍历
方法: