有向图邻接矩阵深度优先搜索

上一个文章是写的无向图和邻接链表的广度搜索,深度搜索就用矩阵和有向图了。
矩阵处理起来还是会比链表简单一些。

先分析数据结构:
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;
}


在这里插入图片描述

在这里插入图片描述

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值