数据结构(C语言版)第六章:图

6.1 ADT图

定义:图G由两个集合组成:一个由顶点构成的有穷非空集合和一个由边构成的有穷允空集合.V(G)和E(G)分别表示图G的顶点集和边集,有时也用G=(V,E)表示图.

无向图是表示边的两个顶点之间没有次序关系的图.例如,顶点对(v0,v1)和(v1,v0)表示同一条边.

有向图是表示边的顶点对有方向的图.例如,顶点对<v0,v1>和<v1,v0>为不同的边.

图的限制:

1) 图中不能有从顶点i到其自身的边.

2) 同一条边在图中不能出现两次或两次以上,不满足这个限制的图称为多重图.

一些基本的概念:

1. 路径的长度:路径上边的条数

2. 简单路径:路径上除了起点和终点可能相同外,其余顶点都互不相同,可以用顶点序列来表示一条简单路径.

3. 回路(环路):一条简单路径,且其起点和终点相同.

4. 顶点的度:关联于该顶点的边的条数.


6.2 图的基本操作

  1. 深度优先搜索

下面是我写的第一个程序,但是是错误的,我调试的时候才发现,分配的内存空间是局部变量,所以进行:

dfs( 0, visited, graph);




时候,graph内部的数据均被销毁.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_VERTICES 50
typedef struct NODE{
	int					vertex;
	struct NODE	*link;
}Node;

void initNode( Node *graph[] )
{
	struct NODE node0_0, node0_1, node0_2, node1_1, node1_0, node1_3, node1_4, node2_2, node2_0, node2_5, node2_6;
	struct NODE node3_3, node3_1, node3_7, node4_4, node4_1, node4_7, node5_5, node5_2, node5_7;
	struct NODE node6_6, node6_2, node6_7, node7_7, node7_3, node7_4, node7_5, node7_6;

	node0_0.vertex = node1_0.vertex = node2_0.vertex = 0;
	node0_1.vertex = node1_1.vertex = node3_1.vertex = node4_1.vertex = 1;
	node0_2.vertex = node2_2.vertex = node5_2.vertex = node6_2.vertex = 2;
	node1_3.vertex = node3_3.vertex = node7_3.vertex = 3;
	node1_4.vertex = node4_4.vertex = node7_4.vertex = 4;
	node2_5.vertex = node5_5.vertex = node7_5.vertex = 5;
	node2_6.vertex = node6_6.vertex = node7_6.vertex = 6;
	node3_7.vertex = node4_7.vertex = node5_7.vertex = node6_7.vertex = node7_7.vertex = 7;

	node0_0.link = &node0_1;
	node0_1.link = &node0_2;
	node0_2.link = NULL;
	graph[ 0 ] = &node0_0;

	node1_1.link = &node1_0;
	node1_0.link = &node1_3;
	node1_3.link = &node1_4;
	node1_4.link = NULL;
	graph[ 1 ] = &node1_1;

	node2_2.link = &node2_0;
	node2_0.link = &node2_5;
	node2_5.link = &node2_6;
	node2_6.link = NULL;
	graph[ 2 ] = &node2_2;

	node3_3.link = &node3_1;
	node3_1.link = &node3_7;
	node3_7.link = NULL;
	graph[ 3 ] = &node3_3;

	node4_4.link = &node4_1;
	node4_1.link = &node4_7;
	node4_7.link = NULL;
	graph[ 4 ] = &node4_4;

	node5_5.link = &node5_2;
	node5_2.link = &node5_7;
	node5_7.link = NULL;
	graph[ 5 ] = &node5_5;

	node6_6.link = &node6_2;
	node6_2.link = &node6_7;
	node6_7.link = NULL;
	graph[ 6 ] = &node6_6;

	node7_7.link = &node7_3;
	node7_3.link = &node7_4;
	node7_4.link = &node7_5;
	node7_5.link = &node7_6;
	node7_6.link = NULL;
	graph[ 7 ] = &node7_7;
}

void dfs( int v, int *visited, Node *graph[] )
{
	Node *w = ( Node * )malloc( sizeof( Node ) );
	visited[ v ] = 1;
	printf("%5d", v );
	for ( w = graph[ v ]; w; w = w->link ){
		if ( !visited[ w->vertex ] ){
			dfs( w->vertex, visited, graph );
		}
	}
}

int main( void )
{
	Node *graph[ MAX_VERTICES ];
	int		visited[ MAX_VERTICES ];
	memset( visited, 0, sizeof( int ) * MAX_VERTICES );
	memset( graph, 0, sizeof( Node * ) * MAX_VERTICES );

	initNode( graph );

	dfs( 0, visited, graph);

	return 0;
}




那么应该怎么办呢?方法1是动态分配内存,但是什么时候free着实让我着急啊.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_VERTICES 50
typedef struct NODE{
	int					vertex;
	struct NODE	*link;
}Node;

void initNode( Node *graph[])
{
	Node *node0_0 = ( Node * )malloc( sizeof( Node ) );
	Node *node0_1 = ( Node * )malloc( sizeof( Node ) );
	Node *node0_2 = ( Node * )malloc( sizeof( Node ) );
	Node *node1_1 = ( Node * )malloc( sizeof( Node ) );
	Node *node1_0 = ( Node * )malloc( sizeof( Node ) );
	Node *node1_3 = ( Node * )malloc( sizeof( Node ) );
	Node *node1_4 = ( Node * )malloc( sizeof( Node ) );
	Node *node2_2 = ( Node * )malloc( sizeof( Node ) );
	Node *node2_0 = ( Node * )malloc( sizeof( Node ) );
	Node *node2_5 = ( Node * )malloc( sizeof( Node ) );
	Node *node2_6 = ( Node * )malloc( sizeof( Node ) );
	Node *node3_3 = ( Node * )malloc( sizeof( Node ) );
	Node *node3_1 = ( Node * )malloc( sizeof( Node ) );
	Node *node3_7 = ( Node * )malloc( sizeof( Node ) );
	Node *node4_4 = ( Node * )malloc( sizeof( Node ) );
	Node *node4_1 = ( Node * )malloc( sizeof( Node ) );
	Node *node4_7 = ( Node * )malloc( sizeof( Node ) );
	Node *node5_5 = ( Node * )malloc( sizeof( Node ) );
	Node *node5_2 = ( Node * )malloc( sizeof( Node ) );
	Node *node5_7 = ( Node * )malloc( sizeof( Node ) );
	Node *node6_6 = ( Node * )malloc( sizeof( Node ) );
	Node *node6_2 = ( Node * )malloc( sizeof( Node ) );
	Node *node6_7 = ( Node * )malloc( sizeof( Node ) );
	Node *node7_7 = ( Node * )malloc( sizeof( Node ) );
	Node *node7_3 = ( Node * )malloc( sizeof( Node ) );
	Node *node7_4 = ( Node * )malloc( sizeof( Node ) );
	Node *node7_5 = ( Node * )malloc( sizeof( Node ) );
	Node *node7_6 = ( Node * )malloc( sizeof( Node ) );

	node0_0->vertex = node1_0->vertex = node2_0->vertex = 0;
	node0_1->vertex = node1_1->vertex = node3_1->vertex = node4_1->vertex = 1;
	node0_2->vertex = node2_2->vertex = node5_2->vertex = node6_2->vertex = 2;
	node1_3->vertex = node3_3->vertex = node7_3->vertex = 3;
	node1_4->vertex = node4_4->vertex = node7_4->vertex = 4;
	node2_5->vertex = node5_5->vertex = node7_5->vertex = 5;
	node2_6->vertex = node6_6->vertex = node7_6->vertex = 6;
	node3_7->vertex = node4_7->vertex = node5_7->vertex = node6_7->vertex = node7_7->vertex = 7;

	node0_0->link = node0_1;
	node0_1->link = node0_2;
	node0_2->link = NULL;
	graph[ 0 ] = node0_0;

	node1_1->link = node1_0;
	node1_0->link = node1_3;
	node1_3->link = node1_4;
	node1_4->link = NULL;
	graph[ 1 ] = node1_1;

	node2_2->link = node2_0;
	node2_0->link = node2_5;
	node2_5->link = node2_6;
	node2_6->link = NULL;
	graph[ 2 ] = node2_2;

	node3_3->link = node3_1;
	node3_1->link = node3_7;
	node3_7->link = NULL;
	graph[ 3 ] = node3_3;

	node4_4->link = node4_1;
	node4_1->link = node4_7;
	node4_7->link = NULL;
	graph[ 4 ] = node4_4;

	node5_5->link = node5_2;
	node5_2->link = node5_7;
	node5_7->link = NULL;
	graph[ 5 ] = node5_5;

	node6_6->link = node6_2;
	node6_2->link = node6_7;
	node6_7->link = NULL;
	graph[ 6 ] = node6_6;

	node7_7->link = node7_3;
	node7_3->link = node7_4;
	node7_4->link = node7_5;
	node7_5->link = node7_6;
	node7_6->link = NULL;
	graph[ 7 ] = node7_7;
}

void dfs( int v, int *visited, Node *graph[] )
{
	Node *w = ( Node * )malloc( sizeof( Node ) );
	visited[ v ] = 1;
	printf("%d->", v );
	for ( w = graph[ v ]; w; w = w->link ){
		if ( !visited[ w->vertex ] ){
			dfs( w->vertex, visited, graph );
		}
	}
}

int main( void )
{
	Node *graph[ MAX_VERTICES ];
	int		visited[ MAX_VERTICES ];
	memset( graph, 0, sizeof( Node * ) * MAX_VERTICES );
	memset( visited, 0, sizeof( int ) * MAX_VERTICES );

	initNode( graph );

	dfs( 0, visited, graph );
	printf("NULL\n");

	return 0;
}




程序输出:

185841_AXSS_1017135.png

这种方法是我经常用的,但是没有free,是不好的设计.但是我确实不知道怎么去free(良好的free掉).然后我再想,在设计中更重要的是安全性,既然free很难,那我们不用malloc不就行了吗?于是我手动分配了一个确定的内存空间用来存储结点:

PS:这种方法是我个人比较推荐的(我也说不出为什么,总感觉malloc很危险就是了)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_VERTICES 50
typedef struct NODE{
	int					vertex;
	struct NODE	*link;
}Node;

void initNode( Node *graph[], struct NODE stack[] )
{
	stack[ 0 ].vertex = 0, stack[ 0 ].link = &stack[ 1 ];
	stack[ 1 ].vertex = 1, stack[ 1 ].link = &stack[ 2 ];
	stack[ 2 ].vertex = 2, stack[ 2 ].link = NULL;

	stack[ 3 ].vertex = 1, stack[ 3 ].link = &stack[ 4 ];
	stack[ 4 ].vertex = 0, stack[ 4 ].link = &stack[ 5 ];
	stack[ 5 ].vertex = 3, stack[ 5 ].link = &stack[ 6 ];
	stack[ 6 ].vertex = 4, stack[ 6 ].link = NULL;

	stack[ 7 ].vertex = 2, stack[ 7 ].link = &stack[ 8 ];
	stack[ 8 ].vertex = 0, stack[ 8 ].link = &stack[ 9 ];
	stack[ 9 ].vertex = 5, stack[ 9 ].link = &stack[ 10 ];
	stack[ 10 ].vertex = 6, stack[ 10 ].link = NULL;

	stack[ 11 ].vertex = 3, stack[ 11 ].link = &stack[ 12 ];
	stack[ 12 ].vertex = 1, stack[ 12 ].link = &stack[ 13 ];
	stack[ 13 ].vertex = 7, stack[ 13 ].link = NULL;

	stack[ 14 ].vertex = 4, stack[ 14 ].link = &stack[ 15 ];
	stack[ 15 ].vertex = 1, stack[ 15 ].link = &stack[ 16 ];
	stack[ 16 ].vertex = 7, stack[ 16 ].link = NULL;

	stack[ 17 ].vertex = 5, stack[ 17 ].link = &stack[ 18 ];
	stack[ 18 ].vertex = 2, stack[ 18 ].link = &stack[ 19 ];
	stack[ 19 ].vertex = 7, stack[ 19 ].link = NULL;

	stack[ 20 ].vertex = 6, stack[ 20 ].link = &stack[ 21 ];
	stack[ 21 ].vertex = 2, stack[ 21 ].link = &stack[ 22 ];
	stack[ 22 ].vertex = 7, stack[ 22 ].link = NULL;

	stack[ 23 ].vertex = 7, stack[ 23 ].link = &stack[ 24 ];
	stack[ 24 ].vertex = 3, stack[ 24 ].link = &stack[ 25 ];
	stack[ 25 ].vertex = 4, stack[ 25 ].link = &stack[ 26 ];
	stack[ 26 ].vertex = 5, stack[ 26 ].link = &stack[ 27 ];
	stack[ 27 ].vertex = 6, stack[ 27 ].link = NULL;

	graph[ 0 ] = &stack[ 0 ];
	graph[ 1 ] = &stack[ 3 ];
	graph[ 2 ] = &stack[ 7 ];
	graph[ 3 ] = &stack[ 11 ];
	graph[ 4 ] = &stack[ 14 ];
	graph[ 5 ] = &stack[ 17 ];
	graph[ 6 ] = &stack[ 20 ];
	graph[ 7 ] = &stack[ 23 ];
}

void dfs( int v, int *visited, Node *graph[] )
{
	Node *w = ( Node * )malloc( sizeof( Node ) );
	visited[ v ] = 1;
	printf("%d->", v );
	for ( w = graph[ v ]; w; w = w->link ){
		if ( !visited[ w->vertex ] ){
			dfs( w->vertex, visited, graph );
		}
	}
}

int main( void )
{
	Node					*graph[ MAX_VERTICES ];
	int						visited[ MAX_VERTICES ];
	struct NODE		stack[ MAX_VERTICES ];
	memset( graph, 0, sizeof( Node * ) * MAX_VERTICES );
	memset( visited, 0, sizeof( int ) * MAX_VERTICES );
	memset( stack, 0, sizeof( struct NODE ) * MAX_VERTICES );

	initNode( graph, stack );

	dfs( 0, visited, graph );
	printf("NULL\n");

	return 0;
}




程序输出:

191301_6Ebz_1017135.png


2. 广度优先搜索

广度优先搜索类似于层次遍历,写写看:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_VERTICES 50
typedef struct NODE{
	int					vertex;
	struct NODE	*link;
}Node;

void initNode( Node *graph[], struct NODE stack[] )
{
	stack[ 0 ].vertex = 0, stack[ 0 ].link = &stack[ 1 ];
	stack[ 1 ].vertex = 1, stack[ 1 ].link = &stack[ 2 ];
	stack[ 2 ].vertex = 2, stack[ 2 ].link = NULL;

	stack[ 3 ].vertex = 1, stack[ 3 ].link = &stack[ 4 ];
	stack[ 4 ].vertex = 0, stack[ 4 ].link = &stack[ 5 ];
	stack[ 5 ].vertex = 3, stack[ 5 ].link = &stack[ 6 ];
	stack[ 6 ].vertex = 4, stack[ 6 ].link = NULL;

	stack[ 7 ].vertex = 2, stack[ 7 ].link = &stack[ 8 ];
	stack[ 8 ].vertex = 0, stack[ 8 ].link = &stack[ 9 ];
	stack[ 9 ].vertex = 5, stack[ 9 ].link = &stack[ 10 ];
	stack[ 10 ].vertex = 6, stack[ 10 ].link = NULL;

	stack[ 11 ].vertex = 3, stack[ 11 ].link = &stack[ 12 ];
	stack[ 12 ].vertex = 1, stack[ 12 ].link = &stack[ 13 ];
	stack[ 13 ].vertex = 7, stack[ 13 ].link = NULL;

	stack[ 14 ].vertex = 4, stack[ 14 ].link = &stack[ 15 ];
	stack[ 15 ].vertex = 1, stack[ 15 ].link = &stack[ 16 ];
	stack[ 16 ].vertex = 7, stack[ 16 ].link = NULL;

	stack[ 17 ].vertex = 5, stack[ 17 ].link = &stack[ 18 ];
	stack[ 18 ].vertex = 2, stack[ 18 ].link = &stack[ 19 ];
	stack[ 19 ].vertex = 7, stack[ 19 ].link = NULL;

	stack[ 20 ].vertex = 6, stack[ 20 ].link = &stack[ 21 ];
	stack[ 21 ].vertex = 2, stack[ 21 ].link = &stack[ 22 ];
	stack[ 22 ].vertex = 7, stack[ 22 ].link = NULL;

	stack[ 23 ].vertex = 7, stack[ 23 ].link = &stack[ 24 ];
	stack[ 24 ].vertex = 3, stack[ 24 ].link = &stack[ 25 ];
	stack[ 25 ].vertex = 4, stack[ 25 ].link = &stack[ 26 ];
	stack[ 26 ].vertex = 5, stack[ 26 ].link = &stack[ 27 ];
	stack[ 27 ].vertex = 6, stack[ 27 ].link = NULL;

	graph[ 0 ] = &stack[ 0 ];
	graph[ 1 ] = &stack[ 3 ];
	graph[ 2 ] = &stack[ 7 ];
	graph[ 3 ] = &stack[ 11 ];
	graph[ 4 ] = &stack[ 14 ];
	graph[ 5 ] = &stack[ 17 ];
	graph[ 6 ] = &stack[ 20 ];
	graph[ 7 ] = &stack[ 23 ];
}

void bfs( int v, int *visited, Node *graph[] )
{
	Node *stack[ MAX_VERTICES ];
	int top = 0;
	int rear = 0;
	Node *w = ( Node * )malloc( sizeof( Node ) );
	visited[ v ] = 1;
	printf("%d->", v );
	stack[ top++ ] = graph[ v ];
	while ( top != rear ){
		w = stack[ rear++ ];
		for ( ; w; w = w->link ){
			if ( !visited[ w->vertex ] ){
				printf("%d->", w->vertex );
				stack[ top++ ] = graph[ w->vertex ];
				visited[ w->vertex ] = 1;
			}
		}
	}
}


int main( void )
{
	Node					*graph[ MAX_VERTICES ];
	int						visited[ MAX_VERTICES ];
	struct NODE		stack[ MAX_VERTICES ];
	memset( graph, 0, sizeof( Node * ) * MAX_VERTICES );
	memset( visited, 0, sizeof( int ) * MAX_VERTICES );
	memset( stack, 0, sizeof( struct NODE ) * MAX_VERTICES );

	initNode( graph, stack );

	bfs( 0, visited, graph );
	printf("NULL\n");

	return 0;
}



程序输出:

193816_guVN_1017135.png

3. 测试连通分支

就是测试上例中的visited是否有断开(值为0)的点.假设我们伪造两个不连接的图作为测试:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_VERTICES 50
typedef struct NODE{
	int					vertex;
	struct NODE	*link;
}Node;

void initNode( Node *graph[], struct NODE stack[] )
{
	stack[ 0 ].vertex = 0, stack[ 0 ].link = &stack[ 1 ];
	stack[ 1 ].vertex = 1, stack[ 1 ].link = &stack[ 2 ];
	stack[ 2 ].vertex = 2, stack[ 2 ].link = NULL;

	stack[ 3 ].vertex = 1, stack[ 3 ].link = &stack[ 4 ];
	stack[ 4 ].vertex = 0, stack[ 4 ].link = NULL;

	stack[ 7 ].vertex = 2, stack[ 7 ].link = &stack[ 8 ];
	stack[ 8 ].vertex = 0, stack[ 8 ].link = NULL;

	stack[ 11 ].vertex = 3, stack[ 11 ].link = &stack[ 12 ];
	stack[ 12 ].vertex = 7, stack[ 12 ].link = NULL;

	stack[ 14 ].vertex = 4, stack[ 14 ].link = &stack[ 15 ];
	stack[ 15 ].vertex = 7, stack[ 15 ].link = NULL;

	stack[ 17 ].vertex = 5, stack[ 17 ].link = &stack[ 18 ];
	stack[ 18 ].vertex = 7, stack[ 18 ].link = NULL;

	stack[ 20 ].vertex = 6, stack[ 20 ].link = &stack[ 21 ];
	stack[ 21 ].vertex = 7, stack[ 21 ].link = NULL;

	stack[ 23 ].vertex = 7, stack[ 23 ].link = &stack[ 24 ];
	stack[ 24 ].vertex = 3, stack[ 24 ].link = &stack[ 25 ];
	stack[ 25 ].vertex = 4, stack[ 25 ].link = &stack[ 26 ];
	stack[ 26 ].vertex = 5, stack[ 26 ].link = &stack[ 27 ];
	stack[ 27 ].vertex = 6, stack[ 27 ].link = NULL;

	graph[ 0 ] = &stack[ 0 ];
	graph[ 1 ] = &stack[ 3 ];
	graph[ 2 ] = &stack[ 7 ];
	graph[ 3 ] = &stack[ 11 ];
	graph[ 4 ] = &stack[ 14 ];
	graph[ 5 ] = &stack[ 17 ];
	graph[ 6 ] = &stack[ 20 ];
	graph[ 7 ] = &stack[ 23 ];
}

void bfs( int v, int *visited, Node *graph[] )
{
	Node *stack[ MAX_VERTICES ];
	int top = 0;
	int rear = 0;
	Node *w = ( Node * )malloc( sizeof( Node ) );
	visited[ v ] = 1;
	printf("%d->", v );
	stack[ top++ ] = graph[ v ];
	while ( top != rear ){
		w = stack[ rear++ ];
		for ( ; w; w = w->link ){
			if ( !visited[ w->vertex ] ){
				printf("%d->", w->vertex );
				stack[ top++ ] = graph[ w->vertex ];
				visited[ w->vertex ] = 1;
			}
		}
	}
}

void connected( int *visited, int len, Node *graph[] )
{
	int i = 0;
	for ( i = 0; i < len; i++ ){
		if ( !visited[ i ] ){
			bfs( i, visited, graph );
			printf("NULL\n");
		}
	}
}


int main( void )
{
	Node					*graph[ MAX_VERTICES ];
	int						visited[ MAX_VERTICES ];
	struct NODE		stack[ MAX_VERTICES ];
	memset( graph, 0, sizeof( Node * ) * MAX_VERTICES );
	memset( visited, 0, sizeof( int ) * MAX_VERTICES );
	memset( stack, 0, sizeof( struct NODE ) * MAX_VERTICES );

	initNode( graph, stack );

	bfs( 0, visited, graph );
	printf("NULL\n");

	connected( visited, 8, graph );

	return 0;
}



程序输出:

194834_vczB_1017135.png

PS:之所以不厌其烦的把所有的代码贴出来.是因为我刚开始学习程序的时候,很多的高手总是习惯把关键的代码贴出来,但是没有贴出全部,结果对我来说,怎么写也无法运行代码.这就是为什么我习惯贴出全部代码的原因.


4. 生成树

在深度优先搜索或者广度优先搜索中,打印出来的边构成的树,为图的生成树.

这在城市建设通讯线路的成本中有设计,当然,权值也在那里体现.


5. 双连通分支与关节点

关节点:图G中的一个顶点v,如果删除v以及关联在v上的所有边后,得到的新图至少包含两个连通分支.如下图:

202337_lBaB_1017135.png

关节点为1,3,5,7,如下图所示:

202821_RHrB_1017135.png双连通图是没有关节点的连通图.连通无向图G的双连通分支是图G中的一个最大双连通子图H.

我们现在通过深度优先搜索树来描述如何找到最大双连通子图(描述不详细,具体参考<数据结构(C语言版)>).我们从结点3开始深度优先搜索,则如下图所示:

204651_DMzL_1017135.png

上图中的曲线(PPT中我不知道虚线怎么画)代表的是回退边.有两个结论:

  1. 当且仅当深度优先生成树的根顶点至少有两个儿子,它就是一个关节点.

  2. 任何非根顶点u是一个关节点,当且仅当u至少有一个儿子w,且从w出发,不能通过w的后代顶点和一条回退边到达u的任意一个祖先顶点.

这样,我们可以给每个顶点u定义low值,low(u)等于从u出发,经过一条由其后代顶点形成的路径和一条回退边,所能到达的具有最小深度优先编号顶点的编号(会死循环吗??)

因此,判断顶点u是否为关节点的方法是:如果顶点u是生成树的根节点,且u至少有两个儿子,则u是关节点;如果u不是根节点,那么当且仅当u有一个儿子w,使得low(w)>=dfn(u),则u是关节点.则下表可以显示上例中的dfn,low的关系:

顶点 0 1 2 3 4 5 6 7 8
dfn 4 3 2 0 1 5 6 7 9
low 4 3 0 0 0 5 5 7 9
为什么 列的长 度不能 超过 10 ? ? ? ?

?

这里的问题是:如何构建良好的数据结构来计算dfn和low的值.

我们来尝试写一下代码(有九天没写C语言了,瞬间感觉有点陌生.加油吧,为了梦想,和无怨无悔的人生).

这个程序难是难在它需要生成树.所以自学很麻烦的,因为你漏掉一点就会使程序完全跑不通.

先把不完整的代码贴出来吧,然后第六章的图和第十章的查找后面再来啃,要一步步来.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_VERTICES 50
#define MIN2(x,y) ((x) < (y) ? (x) : (y))
typedef struct NODE{
	int					vertex;
	struct NODE	*link;
}Node;

void initNode( Node *graph[], struct NODE stack[] )
{
	stack[ 0 ].vertex = 0, stack[ 0 ].link = &stack[ 1 ];
	stack[ 1 ].vertex = 1, stack[ 1 ].link = NULL;

	stack[ 2 ].vertex = 1, stack[ 2 ].link = &stack[ 3 ];
	stack[ 3 ].vertex = 0, stack[ 3 ].link = &stack[ 4 ];
	stack[ 4 ].vertex = 2, stack[ 4 ].link = &stack[ 5 ];
	stack[ 5 ].vertex = 3, stack[ 5 ].link = NULL;

	stack[ 6 ].vertex = 2, stack[ 6 ].link = &stack[ 7 ];
	stack[ 7 ].vertex = 1, stack[ 7 ].link = &stack[ 8 ];
	stack[ 8 ].vertex = 4, stack[ 8 ].link = NULL;

	stack[ 9 ].vertex = 3, stack[ 9 ].link = &stack[ 10 ];
	stack[ 10 ].vertex = 1, stack[ 10 ].link = &stack[ 11 ];
	stack[ 11 ].vertex = 4, stack[ 11 ].link = &stack[ 12 ];
	stack[ 12 ].vertex = 5, stack[ 12 ].link = NULL;

	stack[ 13 ].vertex = 4, stack[ 13 ].link = &stack[ 14 ];
	stack[ 14 ].vertex = 2, stack[ 14 ].link = &stack[ 15 ];
	stack[ 15 ].vertex = 3, stack[ 15 ].link = NULL;

	stack[ 16 ].vertex = 5, stack[ 16 ].link = &stack[ 17 ];
	stack[ 17 ].vertex = 3, stack[ 17 ].link = &stack[ 18 ];
	stack[ 18 ].vertex = 7, stack[ 18 ].link = &stack[ 19 ];
	stack[ 19 ].vertex = 8, stack[ 19 ].link = NULL;

	stack[ 20 ].vertex = 6, stack[ 20 ].link = &stack[ 21 ];
	stack[ 21 ].vertex = 5, stack[ 21 ].link = &stack[ 22 ];
	stack[ 22 ].vertex = 7, stack[ 22 ].link = NULL;

	stack[ 23 ].vertex = 7, stack[ 23 ].link = &stack[ 24 ];
	stack[ 24 ].vertex = 5, stack[ 24 ].link = &stack[ 25 ];
	stack[ 25 ].vertex = 6, stack[ 25 ].link = &stack[ 26 ];
	stack[ 26 ].vertex = 8, stack[ 26 ].link = &stack[ 27 ];
	stack[ 27 ].vertex = 9, stack[ 27 ].link = NULL;

	stack[ 28 ].vertex = 8, stack[ 28 ].link = &stack[ 29 ];
	stack[ 29 ].vertex = 7, stack[ 29 ].link = &stack[ 30 ];
	stack[ 30 ].vertex = 9, stack[ 30 ].link = NULL;

	stack[ 31 ].vertex = 9, stack[ 31 ].link = &stack[ 32 ];
	stack[ 32 ].vertex = 7, stack[ 32 ].link = &stack[ 33 ];
	stack[ 33 ].vertex = 8, stack[ 33 ].link = NULL;

	graph[ 0 ] = &stack[ 0 ];
	graph[ 1 ] = &stack[ 2 ];
	graph[ 2 ] = &stack[ 6 ];
	graph[ 3 ] = &stack[ 9 ];
	graph[ 4 ] = &stack[ 13 ];
	graph[ 5 ] = &stack[ 16 ];
	graph[ 6 ] = &stack[ 20 ];
	graph[ 7 ] = &stack[ 23 ];
	graph[ 8 ] = &stack[ 28 ];
	graph[ 9 ] = &stack[ 31 ];
}

void dfnlow( int u, int v, Node *graph[], int *dfn, int *low, int *num )
{
	Node		*ptr = ( Node * )malloc( sizeof( Node ) );
	int			w;
	dfn[ u ] = low[ u ] = ( *num )++;			//注意,++的优先级比*高,所以要加括号
	for ( ptr = graph[ u ]; ptr; ptr = ptr->link ){
		w = ptr->vertex;
		if ( dfn[ w ] < 0 ){
			dfnlow( w, u, graph, dfn, low, num );
			low[ u ] = MIN2( low[ u ], low[ w ] );
		}
		else if ( w != v ){
			low[ u ] = MIN2( low[ u ], dfn[ w ] );
		}
	}
}

int main( void )
{
	Node					*graph[ MAX_VERTICES ];
	int						visited[ MAX_VERTICES ];
	struct NODE		stack[ MAX_VERTICES ];
	int		dfn[ MAX_VERTICES ];
	int		low[ MAX_VERTICES ];
	int		num = 0;
	int		i = 0;
	memset( graph, 0, sizeof( Node * ) * MAX_VERTICES );
	memset( visited, 0, sizeof( int ) * MAX_VERTICES );
	memset( stack, 0, sizeof( struct NODE ) * MAX_VERTICES );
	memset( dfn, -1, sizeof( int ) * MAX_VERTICES );
	memset( low, -1, sizeof( int ) * MAX_VERTICES );

	initNode( graph, stack );

	dfnlow( 3, -1, graph, dfn, low, &num );

	for ( i = 0; dfn[ i ] != -1; i++ ){
		printf("%d ", dfn[ i ] );
	}
	printf("\n");
	for ( i = 0; low[ i ] != -1; i++ ){
		printf("%d ", low[ i ] );
	}
	printf("\n");

	return 0;
}





转载于:https://my.oschina.net/voler/blog/187018

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值