基于邻接表实现的图的遍历

1:首先是头文件和全局变量的写入和定义:

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

#define MAXSIZE  20

char vex[MAXSIZE] ;            //存储读入的节点信息
int outDegree[MAXSIZE], 
	inDegree[MAXSIZE] ;    //存储结点出入度
int visited[MAXSIZE] ;         //进行DFS搜索遍历时用的访问数组
int LTnum = 0 ;                //记录连通分量个数

2:然后定义数据结构:

//**********************************************数据结构定义
typedef struct ArcNode {
	int adjvex ;                //存储与当前结点连接的结点下标(在vex数组里的下标)
	int weight ;	            //权值
	struct ArcNode *next ;      
}ArcNode ;

typedef struct VertexNode {
	char vexdata ;              //存储结点信息
	ArcNode *head ;             //存储链表的头指针,此链表存的是一个结点所有邻接信息
}VertexNode ;

typedef struct {
	VertexNode vertex[MAXSIZE] ;
	int vexnum ;                //结点总个数
	int arcnum ;                //结点关系的总个数
}AdjList ;
//**********************************************队列结点定义(DFS遍历时需要用到)
typedef struct Node
{
	int data;                   //存储类型
	struct Node *next;
}qNode;
typedef struct 
{
	qNode *front;
	qNode *rear;
}Queue;

3:接下来是邻接表的创建

int index(char ch,int vexnum){
/*求出ch的下标*/
	int num = 1 ;
	for(int i = 0; i < vexnum; i++){
		
		if( ch == vex[i] ){
			return num ;	
		}
		num++ ;
	} 
} 
void Create(AdjList *L){
/*创建有向邻接表*/
	char a, b ;
	int i, j, k;
	
	ArcNode *p;
	scanf("%d%d", &(*L).vexnum, &(*L).arcnum) ;
	scanf("%s ", vex) ;				//输入结点 加空格防止读取
                                                          了回车:这个特别坑!!!
	for(i = 1; i <= (*L).vexnum; i++){
		(*L).vertex[i].head = NULL ;            //初始化指针数组
		(*L).vertex[i].vexdata = vex[i-1] ;     //存储vexdata的内容
	}
	for (i=0; i<(*L).arcnum; i++){	
		scanf(" %c%c", &a,&b);                  //空格作用同上
		j = index(a, (*L).vexnum) ;
		k = index(b, (*L).vexnum) ;
		p = (ArcNode *)malloc(sizeof(ArcNode)) ;
		p->adjvex = k ;                         //存入关系
		p->next = (*L).vertex[j].head ;         //采用头插法(不带头结点)
		(*L).vertex[j].head = p ;
	}
}

4:由于我们创建的邻接表是逆邻接表(尾插法太麻烦),所以函数我们再写一个函数将它逆置过来:

void Reverse(AdjList L, AdjList *B){
/*逆邻接表:新建立一个邻接表,将刚才的邻接表信息照搬过来,链表的信息重新头插一遍*/
	int i,k;

	ArcNode *p1,*p2;
	(*B).vexnum = L.vexnum;
	(*B).arcnum = L.arcnum;
	
	for(i=1; i<=L.vexnum; i++){
		(*B).vertex[i].vexdata = L.vertex[i].vexdata ;  //
		(*B).vertex[i].head = NULL ;                    //头指针赋空
	} 
	
	for(i=1; i<=L.vexnum; i++){
		p1 = L.vertex[i].head;
		while(p1){
			k = p1->adjvex ;
			p2 = (ArcNode *)malloc(sizeof(ArcNode));
			p2->adjvex = k ;
			p2->next = (*B).vertex[i].head;         //再头插一遍邻接表就会复原
			(*B).vertex[i].head = p2;
			p1 = p1->next;
		}
	}
}

5:打印出入度(可有可无,很简单):

void printDegree(AdjList L){
/*打印出入度:遍历一遍邻接表*/
	int i ;
	ArcNode *p = NULL ;
	for( i = 1; i <= L.vexnum; i++ ){
		p = L.vertex[i].head ;
		while (p){
			inDegree[p->adjvex]++ ;
			outDegree[i]++ ;
			p = p->next ;
		}
	}
	for(i=1; i<=L.vexnum; i++){
		printf("%c %d %d %d\n", L.vertex[i].vexdata, outDegree[i], inDegree[i], outDegree[i]+inDegree[i]);
	}
}

6:DFS(深度优先遍历):

void DepthFirstSearch(AdjList L, int v){		
/*采用递归深度遍历图的连通子图*/
	int i ;
	ArcNode *p ;

	printf("%c", L.vertex[v].vexdata) ;
	visited[v] = 1 ;                                //访问后访问数组置1
	p = L.vertex[v].head ;
	
	while (p){
		if(visited[p->adjvex]==0)
			DepthFirstSearch(L, p->adjvex) ;
		p = p->next ;
	}
}
void DFS(AdjList L){			
/*遍历整个图*/
	int i ;
	
	for(i=1; i<=L.vexnum; i++){                     //访问数组置0
		visited[i] = 0 ;
	}
	
	for(i=1; i<=L.vexnum; i++){
		if(!visited[i]){                        
			LTnum++ ;                       //可以计算连通子图个数
			DepthFirstSearch(L, i);
		}
	}
}

7:BFS(广度优先遍历)(采用队列):

        (1):队列的操作:

Queue *Init_Queue()
/*初始化队列*/
{
	Queue *q;
	qNode *p;
	q = (Queue *)malloc(sizeof(Queue));
	p = (qNode *)malloc(sizeof(qNode));
	p->next = NULL;
	q->front = q->rear = p;
	return q;
} 
void In_Queue(Queue *q,int x)
/*入队*/
{
	qNode *p;
	p = (qNode *)malloc(sizeof(qNode));
	p->data = x;
	p->next = NULL;
	q->rear->next = p;
	q->rear = p;
} 
int isEmpty(Queue *q)
/*判空*/
{
	if(q->front==q->rear)
		return 1;
	else 
		return 0;
} 
void Out_Queue(Queue *q,int *x)
/*出队*/
{
	qNode *p;
	if(isEmpty(q)){
		printf("ERROR\n");
		return;
	}
	else {
		p = q->front->next;
		q->front->next = p->next;
		*x = p->data;
		free(p);
		if(q->front->next==NULL){
			q->rear = q->front;
		}
	}
} 

        (2):BFS函数:

void BreadthFirstSearch(AdjList L, int v){	
/*广度优先搜索连通子图:入队第一个结点并访问,将访问数组置1,当队列不为空时,出队结点,依次入队并访问未访问的结点*/

	printf("%c", L.vertex[v].vexdata) ;
	visited[v] = 1 ;
	Queue *P = Init_Queue() ;
	In_Queue(P, v) ;
	
	ArcNode *p ;

	while (!isEmpty(P)){
		Out_Queue(P, &v) ;

		p = L.vertex[v].head ;
		
		while (p){
			
			if(visited[p->adjvex]==0){
				printf("%c", L.vertex[p->adjvex].vexdata) ;
				visited[p->adjvex] = 1 ;
				In_Queue(P, p->adjvex) ;
			}
			p = p->next ;
		}
	}
}
void BFS(AdjList L){					//广度优先遍历
	int i ;

	for(i=1; i<=L.vexnum; i++){
		visited[i] = 0 ;
	}

	for(i=1; i<=L.vexnum; i++){
		if(!visited[i]){
			BreadthFirstSearch(L, i) ;
		}
	}
}

9:打印邻接表(用作调试):

void Print(AdjList L){
	int i ;
	ArcNode *p = NULL ;
	for( i = 1; i <= L.vexnum; i++ ){
		p = L.vertex[i].head ;
		while (p){
			printf("%d ", p->adjvex) ;
			p = p->next ;
		}
		printf("\n") ;
	}
}

猜你喜欢

转载自blog.csdn.net/dms2017/article/details/85222034