上一个文章是写的无向图和邻接链表的广度搜索,深度搜索就用矩阵和有向图了。
矩阵处理起来还是会比链表简单一些。
先分析数据结构:
1.储存所有结点的集合用到了一个单向循环链表,为什么要用循环链表呢,因为在存储结点数据的时候是按照输入数据的顺序来储存的,如果是用一个数组或者单向链表,我们可以得到数组或链表第一个元素作为源节点的遍历,但是我要是指定数组中的第三个元素作为源节点呢。这样就不太好操作了,所以用了一个循环的链表,先把指针移到指定的任意一个源节点作为表头再继续操作。
其他的就是普通的二维数组结构体等没什么特别的了。
注意:
结点的输入顺序还是得记一个位置,因为二维数组是按那个顺序建立的,有一个position可以把二维数组和链表一一对应起来。
其实很难一次性不出问题,我一般第一次运行都是得不到结果或者只得到部分结果。但是只要会调试,其他的都不是什么问题了,特别是main函数是一个一个处理的,每个函数都是一次一次调用的,在调试的时候哪里出问题了会很明显。
还有就是最近发现的一个小skill,在定义结构体的时候可以把key啊这类的明显的不同的变量先定义,在调试的时候就能先显示看到它。
下面代码看函数名基本就知道是在干嘛,注释写的有点少将就看一下。
#include "stdafx.h"
#include<stdio.h>
#include<stdlib.h>
#define N 6 //plane to create a 6*6 matrix
int time; //the whole proccess's time
int n = 0;
typedef enum Color{ W, G, B }Color;
typedef struct vertex_ *vertex;
typedef struct vertex_
{
int key;
int d; //start time
int f; //final time
int position; //store the position of this vertex, position .position is determined by input sentence
Color c;
vertex parent;
}v;
typedef struct list_ *list;
typedef struct list_ //创建一个单向循环链表
{
vertex v;
list next;
// int position; //to correspond this position with metrix
}l;
void DFS_VISIT(int a[][N], list head, vertex x);
void DFS(int a[][N], vertex b[]);
vertex INI_VERTEX(int key)
{
vertex x = (vertex)malloc(sizeof(v));
x->key = key;
x->d = 0;
x->f = 0;
x->position = n;
x->parent = NULL;
x->c = W;
n++;
return x;
}
void INI_METRIX(int a[][N])
{
for (int i = 0; i < N; i++)
for (int j = 0; j < N; j++)
a[i][j] = 0;
}
list INI_LIST(list x)
{
x = (list)malloc(sizeof(l));
x = NULL;
return x;
// x->next = NULL;
// x->v = NULL;
}
void CONNECTION(int a[][N],vertex out, vertex in)
{
a[out->position][in->position] = 1;
}
list MOVE_HEAD(list head, vertex x)
{
list p = (list)malloc(sizeof(l));
p = head;
if (head->v->position == x->position)
{
return head;
}
else
{
p = p->next;
while (p != head)
{
if (p->v->position == x->position)
return p;
p = p->next;
}
}
}
void DFS(int a[][N],list head)
{
list p = head;
while(p->next!=head) //循环一圈
{
if (p->v->c == W)
DFS_VISIT(a, head, p->v);
p=p->next;
}
if (p->v->c == W)
DFS_VISIT(a, head, p->v);
}
void DFS_VISIT(int a[][N], list head, vertex x)
{
time = time++;
x->d = time;
x->c = G;
for (int i = 0; i<N; i++)
if (a[x->position][i] == 1 )
{
list p = head;
while (p->next != head) //循环一圈
{
if (p->v->position == i && p->v->c == W)
{
p->v->parent = x;
DFS_VISIT(a,head, p->v);
}
p=p->next;
}
//97行p->next了,在检查while的时候还要next,就会导致链表的最后一个元素无法进行处理,所以最后追加一个对最后一个元素的处理,下面还有两个类似的处理
//个人感觉比起先判断p==head的代码量要少那么一点点。
if (p->v->position == i && p->v->c == W)
{
p->v->parent = x;
DFS_VISIT(a, head, p->v);
}
}
x->c = B;
time = time + 1;
x->f = time;
}
list INSERT_VERTEX(list head, vertex x)
{
list new_p = (list)malloc(sizeof(l));
new_p->next = NULL;
new_p->v = x;
// new_p->position = n;
// n++;
if (head == NULL)
{
head = new_p;
head->next = head;
}
else
{
list p = head; //遍历传进来这个链表,看他是什么情况
while (p->next != head)
{
p = p->next;
} //遍历一遍,找到新节点插入的位置,
p->next = new_p;
new_p->next = head;
}
return head;
}
int main()
{
int a[N][N];
list b = (list)malloc(sizeof(l));
vertex p1, p2, p3, p4, p5, p6;
INI_METRIX(a);
b=INI_LIST(b);
p1=INI_VERTEX(8);
p2=INI_VERTEX(3);
p3=INI_VERTEX(6);
p4=INI_VERTEX(7);
p5=INI_VERTEX(5);
p6=INI_VERTEX(10);
b=INSERT_VERTEX(b, p1);
b=INSERT_VERTEX(b, p2);
b=INSERT_VERTEX(b, p3);
b=INSERT_VERTEX(b, p4);
b=INSERT_VERTEX(b, p5);
b=INSERT_VERTEX(b, p6);
CONNECTION(a, p1, p2);
CONNECTION(a, p1, p3);
CONNECTION(a, p2, p3);
CONNECTION(a, p3, p4);
CONNECTION(a, p4, p2);
CONNECTION(a, p5, p4);
CONNECTION(a, p5, p6);
CONNECTION(a, p6, p6);
printf("当头指针是p3,(key=6)时\n");
b=MOVE_HEAD(b, p3);
DFS(a, b);
list p=b;
while (p->next != b)
{
printf("(%d, d=%d,f=%d)\n", p->v->key, p->v->d, p->v->f);
p = p->next;
}
printf("(%d, d=%d,f=%d)\n", p->v->key, p->v->d, p->v->f);
return 0;
}