图的遍历
有两种方法:深度优先,广度优先
深度优先遍历
- 约定左手原则,在没有遇到重复顶点的情况下,分叉路口是从向左手边走,每走过一个顶点就做一个记号
- 如果分叉路所通向的结点已经全部走过,则返回上一个结点(回溯)
- 由此方法,直到返回这个顶点时结束
邻接矩阵中实现思路:
- 从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("\n"); 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\t",arr[i][j]); 77 } 78 printf("\n"); 79 } 80 printf("\n"); 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 }
广度优先遍历
其实广度优先遍历,类似于树的层序遍历
方法:
- 任意选一顶点,加入队列中;
- 在队列中让第一个位置进行操作,遍历这个顶点的所有连接的顶点,依次加入到这个队列中(加入时做好标记以免重复添加);删除刚刚操作的队头顶点
- 重复 ② 步骤,直到队列中全部结点出队列

实现方法:
1 #include <stdio.h> 2 #include <malloc.h> 3 #define SIZE 9 4 #define ElemType char 5 6 typedef struct Node{ 7 int index;//该结点在顶点数组中的位置 8 ElemType data;//顶点数据 9 struct Node *next;//指针域 10 }Node; 11 12 typedef struct Queue{ 13 Node *head; 14 Node *tail; 15 }Queue; 16 17 //定义图 18 ElemType lin[]={'A','B','C','D','E','F','G','H','I'}; 19 int arr[9][9]={ 20 {0,1,0,0,0,1,0,0,0}, 21 {1,0,1,0,0,0,1,0,1}, 22 {0,1,0,1,0,0,0,0,1}, 23 {0,0,1,0,1,0,1,1,1}, 24 {0,0,0,1,0,1,0,1,0}, 25 {1,0,0,0,1,0,1,0,0}, 26 {0,1,0,1,0,1,0,1,0}, 27 {0,0,0,1,1,0,1,0,0}, 28 {0,1,1,1,0,0,0,0,0} 29 }; 30 31 void user(ElemType data){ 32 printf("%c ",data); 33 } 34 35 //q:遍历时用的队列 36 //n:队头顶点的下标 37 //tab:标记数组 38 void start(Queue *q,int *tab){ 39 int i; 40 Node *node; 41 int n; 42 if(q->head==NULL){ 43 q->tail=NULL; 44 }else{ 45 n=q->head->index; 46 for(i=0;i<SIZE;i++){ 47 if(i==n) 48 continue; 49 if(arr[n][i]==1 && tab[i]==0){ 50 tab[i]=1; 51 node=(Node *)malloc(sizeof(Node)); 52 node->index=i; 53 node->data=lin[i]; 54 node->next=NULL; 55 q->tail->next=node; 56 q->tail=node; 57 } 58 } 59 node=q->head; 60 q->head=node->next; 61 user(node->data); 62 free(node); 63 start(q,tab); 64 } 65 } 66 67 //n:在图中选的第一个顶点的下标 68 void breadthFirst(int n){ 69 //定义静态标记数组 70 static int tab[SIZE]={0,0,0,0,0,0,0,0,0}; 71 Queue *q=(Queue *)malloc(sizeof(Queue)); 72 Node *node=(Node *)malloc(sizeof(Node)); 73 q->head=node; 74 q->tail=node; 75 node->index=n; 76 node->data=lin[n]; 77 node->next=NULL; 78 tab[n]=1; 79 start(q,tab); 80 } 81 82 void main(){ 83 breadthFirst(0); 84 printf("\n"); 85 }
浙公网安备 33010602011771号