数据结构(图的遍历和马踏棋盘算法)

Posted tianliang-2000

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构(图的遍历和马踏棋盘算法)相关的知识,希望对你有一定的参考价值。

图的遍历

  有两种方法:深度优先,广度优先

 

深度优先遍历

  • 约定左手原则,在没有遇到重复顶点的情况下,分叉路口是从向右手边走,每走过一个顶点就做一个记号
  • 如果分叉路所通向的结点已经全部走过,则返回上一个结点(回溯)
  • 由此方法,直到返回这个顶点是结束

邻接矩阵中实现思路:

  • 从A[0][0]开始,连向第一行中的第一个为1的元素A[ i ][ j ];
  • 然后跳到第 j 行继续找到第一个为1的元素,并确定这个元素是否走过,如果走过,则返回上一次跳转的行;第0行所对应结点全部走过

技术图片

代码实现

 1 #include <stdio.h>
 2 #include <malloc.h>
 3 #define SIZE 9
 4 
 5 void user(char *lin,int n){
 6     printf("%c  ",lin[n]);
 7 }
 8 
 9 void depthTraversal(char *lin,int (*arr)[SIZE],int n){
10     int i=0,j=n;
11     static int tab[]={0,0,0,0,0,0,0,0,0};
12     tab[j]=1;
13     user(lin,j);
14     for(i=0;i<SIZE;i++){
15         if(i==j)
16             continue;
17         if(*(*(arr+j)+i)==1 && tab[i]==0)
18             depthTraversal(lin,arr,i);
19     }
20 }
21 
22 void main(){
23     char lin[]={A,B,C,D,E,F,G,H,I};
24     int arr[9][9]={
25            {0,1,0,0,0,1,0,0,0},
26            {1,0,1,0,0,0,1,0,1},
27            {0,1,0,1,0,0,0,0,1},
28            {0,0,1,0,1,0,1,1,1},
29            {0,0,0,1,0,1,0,1,0},
30            {1,0,0,0,1,0,1,0,0},
31            {0,1,0,1,0,1,0,1,0},
32            {0,0,0,1,1,0,1,0,0},
33            {0,1,1,1,0,0,0,0,0}
34         };
35     depthTraversal(lin,arr,0);
36     printf("
");
37 }

技术图片

马踏棋盘算法

  问题概述:在国际棋盘(8*8)中将‘马’放在任意指定的方框中,按照‘马’走‘日’的规则将马进行移动。要求每个方格只能进入一次,最终使马走遍棋盘64个方格。

  解决方法:利用深度遍历的方法(回溯);使马遇到死路时就回溯,直到走遍棋盘;

注:在(n*n)的棋盘上,当 n ≥ 5且为偶数时,以任一点都有解

  1 #include <stdio.h>
  2 #include <malloc.h>
  3 #define X 8
  4 #define Y 8
  5 
  6 int arr[X][Y];
  7 
  8 int nextxy(int *x,int*y,int count){
  9     switch(count){
 10         case 0:
 11             if(*x+2<=X-1 && *y-1>=0 && arr[*x+2][*y-1]==0){
 12                 *x+=2;
 13                 *y-=1;
 14                 return 1;
 15             }
 16             break;
 17         case 1:
 18             if(*x+2<=X-1 && *y+1<=Y-1 && arr[*x+2][*y+1]==0){
 19                 *x+=2;
 20                 *y+=1;
 21                 return 1;
 22             }
 23             break;
 24         case 2:
 25             if(*x+1<=X-1 && *y-2>=0 && arr[*x+1][*y-2]==0){
 26                 *x+=1;
 27                 *y-=2;
 28                 return 1;
 29             }
 30             break;
 31         case 3:
 32             if(*x+1<=X-1 && *y+2<=Y-1 && arr[*x+1][*y+2]==0){
 33                 *x+=1;
 34                 *y+=2;
 35                 return 1;
 36             }
 37             break;
 38         case 4:
 39             if(*x-2>=0 && *y-1>=0 && arr[*x-2][*y-1]==0){
 40                 *x-=2;
 41                 *y-=1;
 42                 return 1;
 43             }
 44             break;
 45         case 5:
 46             if(*x-2>=0 && *y+1<=Y-1 && arr[*x-2][*y+1]==0){
 47                 *x-=2;
 48                 *y+=1;
 49                 return 1;
 50             }
 51             break;
 52         case 6:
 53             if(*x-1>=0 && *y-2>=0 && arr[*x-1][*y-2]==0){
 54                 *x-=1;
 55                 *y-=2;
 56                 return 1;
 57             }
 58             break;
 59         case 7:
 60             if(*x-1>=0 && *y+2<=Y-1 && arr[*x-1][*y+2]==0){
 61                 *x-=1;
 62                 *y+=2;
 63                 return 1;
 64             }
 65             break;
 66         default:
 67             break;
 68     }
 69     return 0;
 70 }
 71 
 72 void Print(){
 73     int i,j;
 74     for(i=0;i<X;i++){
 75         for(j=0;j<Y;j++){
 76             printf("%d	",arr[i][j]);
 77         }
 78         printf("
");
 79     }
 80     printf("
");
 81 }
 82 
 83 //(x,y)为位置坐标
 84 //tag是标记变量,也用于记录步骤
 85 int TravelBoard(int x,int y,int tag){
 86     int x1=x,y1=y;
 87     int i=0;
 88     int flag=0;//记录当前位置的选者是否会导致失败
 89     arr[x][y]=tag;
 90     if(X*Y==tag){
 91         Print();//打印
 92         return 1;
 93     }
 94     //找到马下一个可走的坐标(x1,y1),如果找到flag=1,否者为0
 95     flag=nextxy(&x1,&y1,i);
 96     while(0==flag &&i<8){
 97         i++;
 98         flag=nextxy(&x1,&y1,i);
 99     }
100 
101     while(flag){//这里的flag记录是否结束(失败)
102         if(TravelBoard(x1,y1,tag+1)){
103             return 1;
104         }
105 
106         //这个位置会导致后面碰壁失败,需要回溯到上个位置
107         x1=x;
108         y1=y;
109         i++;
110         flag=nextxy(&x1,&y1,i);
111         while(0==flag &&i<8){
112             i++;
113             flag=nextxy(&x1,&y1,i);
114         }
115     }
116     if(flag==0){
117         arr[x][y]=0;
118     }
119     return 0;
120 }
121 
122 void main(){
123     int i,j;
124     for(i=0;i<X;i++){
125         for(j=0;j<Y;j++){
126             arr[i][j]=0;
127         }
128     }
129     printf("请输入起始位置的行:");
130     scanf("%d",&i);
131     printf("请输入起始位置的列:");
132     scanf("%d",&j);
133     //建议用两行一列测试
134 
135     if(!TravelBoard(i,j,1)){
136         printf("马踏棋盘失败");
137     }
138 }

广度优先遍历

  其实广度优先遍历,类似与树的层序遍历

  方法:

  • 任意选一顶点,放入队列中;
  • 在队列中让第一个位置进行操作,遍历这个顶点的所有连接的顶点,依次加入到这个队列中(加入时做好标记以免重复添加);删除刚刚操作的队头顶点
  • 重复 ② 步骤,直到队列中全部结点出队列

 

以上是关于数据结构(图的遍历和马踏棋盘算法)的主要内容,如果未能解决你的问题,请参考以下文章

Day600&601.马踏棋盘算法 -数据结构和算法Java

大话数据结构C语言43 图的应用 - 马踏棋盘算法

大话数据结构C语言43 图的应用 - 马踏棋盘算法

程序员常用 10 种算法之马踏棋盘算法

马踏棋盘(骑士周游问题)

马踏棋盘算法详解