数据结构 图的遍历

1.代码如下

#include <stdio.h>
#include <stdbool.h>
#include<malloc.h>

#define QUEUE_SIZE 10

int *visitedPtr;

/**N
*A queue with a number of inddices.
*/

typedef struct GraphNodeQueue{
	int *nodes;
	int front;
	int rear;
}GraphNodeQueue,*QueuePtr;

/**
*Initalize the queue.
*/

QueuePtr initQueue(){
	QueuePtr resultQueuePtr = (QueuePtr) malloc(sizeof(struct GraphNodeQueue));
	resultQueuePtr->nodes = (int*)malloc(QUEUE_SIZE *sizeof(int)) ;
	resultQueuePtr->front = 0;
	resultQueuePtr->rear = 1;
	return resultQueuePtr; 
}//of initQueue

/**
*Is the queue empty?
*/

bool isQueueEmpty(QueuePtr paraQueuePtr){
	if((paraQueuePtr->front +1)%QUEUE_SIZE == paraQueuePtr->rear) {
		return true;
	}//of if
	
	return false;
}//of isQueueEmpty

/**
*Add a node to the node.
*/

void enqueue(QueuePtr paraQueuePtr,int paraNode){

   if((paraQueuePtr->rear +1)%QUEUE_SIZE == paraQueuePtr->front%QUEUE_SIZE){
   	printf("Error,trying to enqueue %d.queue full.\r\n",paraNode);
   	return ;
   }//of if

   paraQueuePtr->nodes[paraQueuePtr->rear] =paraNode;
   paraQueuePtr->rear=(paraQueuePtr->rear+1)%QUEUE_SIZE;
}//of enqueue

/**
*Remove an element from the queue and return.
*/

int dequeue(QueuePtr paraQueuePtr){

	if(isQueueEmpty(paraQueuePtr)){
		printf("Error,empty queue.\r\n");
		return -1;
	}//of if
	
	paraQueuePtr->front=(paraQueuePtr->front+1)%QUEUE_SIZE;
	return paraQueuePtr->nodes[paraQueuePtr->front];
}//of dequeue

/**
*The structure of a graph
*/

typedef struct Graph{
	int **connections;
    int numNodes;
}*GraphPtr;
     

GraphPtr initGraph(int paraSize,int **paraData){
	int i,j;
	GraphPtr resultPtr =(GraphPtr)malloc(sizeof(struct Graph));
	resultPtr->numNodes  =paraSize;
	resultPtr->connections=(int **)malloc(paraSize * sizeof(int));

	for(i=0;i<paraSize;i++){
		resultPtr->connections[i]=(int*)malloc(paraSize*sizeof(int));
		  for(j=0;j<paraSize;j++){
		  	 resultPtr->connections[i][j]=paraData[i][j];
		  }//of for j
	}//of for i
	
	return resultPtr;
}//of initGraph

/**
*Initalize the tranverse.
*/

void initTranverse(GraphPtr paraGraphPtr) {
	int i;
	//initalize data.
	visitedPtr =(int *)malloc(paraGraphPtr->numNodes*sizeof(int));

	for(i=0;i<paraGraphPtr->numNodes;i++){
		visitedPtr[i] =0;
	}//of for i
}//of initTranverse

/**
*Depth first tranverse
*/ 

void depthFirstTranverse(GraphPtr paraGraphPtr,int paraNode){
	int i;
	visitedPtr[paraNode] =1;
	printf("%d\t",paraNode);

	for(i=0;i<paraGraphPtr->numNodes;i++){
		if(!visitedPtr[i]){
		   if(paraGraphPtr->connections[paraNode][i]){
		  	 depthFirstTranverse(paraGraphPtr,i);
		}//of if
	 }//of if
  }//of for i
}//of depthFirstTranverse

/**
*Width first tranverse
*/

void widthFirstTranverse(GraphPtr paraGraphPtr,int paraStart){
	int i,j,tempNode;
	i=0;
	QueuePtr tempQueuePtr =initQueue();
	printf("%d\t",paraStart);
	visitedPtr[paraStart]=1;
	enqueue(tempQueuePtr,paraStart);
	
	while(!isQueueEmpty(tempQueuePtr)){
		tempNode =dequeue(tempQueuePtr);
		visitedPtr[tempNode] = 1;
		
		//For output
		i++;
		
	 	  for(j=0;j<paraGraphPtr->numNodes;j++){
	 	  	if(visitedPtr[j]) 
	 	  	continue;
	 	  	
	 	  	if(paraGraphPtr->connections[tempNode][j]==0)
	 	  	continue;
	 	  	
	 	  	printf("%d\t",j);
	 	  	visitedPtr[j]=1;
	 	  	enqueue(tempQueuePtr,j);
		  }//of for i
	}//of while
}//of widethFiratTranverse

void testGraphTranverse(){
	int i,j;

	int myGraph[5][5]={
	{0,1,0,1,0},
	{1,0,1,0,1},
	{0,1,0,1,1},
	{1,0,1,0,0},
	{0,1,1,0,0}};

	int **tempPtr;
	printf("Preparing data\r\n");
	tempPtr =(int**)malloc(5 * sizeof(int *));
	
	for(i=0;i<5;i++){
		tempPtr[i] =(int*)malloc(sizeof(int));
	}//of for i
	
	for(i=0;i<5;i++){
		for(j=0;j<5;j++){
		tempPtr[i][j] = myGraph[i][j];
		}//of for j
	}//of for i
	
	printf("Data ready\r\n");
	GraphPtr tempGraphPtr=initGraph(5,tempPtr);
	printf("num nodes =%d\r\n",tempGraphPtr->numNodes);
	printf("Graph initialized\r\n");
	
	printf("Depth first visit\r\n");
	initTranverse(tempGraphPtr);
	depthFirstTranverse(tempGraphPtr,4);
	
	printf("\r\nWidth first visit:\r\n");
	initTranverse(tempGraphPtr);
	widthFirstTranverse(tempGraphPtr,4);
}//of testGraphTranverse

int main(){
    testGraphTranverse();
    return 1;
}//of main

2.运行结果

444884c3524b465ab2a742b154bddd45.jpg

 3.小结

    数据结构中的图是一种非常重要的非线性数据结构,它用于表示对象之间的关系。以下是关于数据结构图的小结:

1)基本概念:图由顶点和边组成,其中顶点表示对象,边表示对象之间的关系。分为无向图和有向图,无向图中的边没有方向,而有向图中的边有方向。图的表示方法主要有邻接矩阵和邻接表两种。

2)图的遍历:图的遍历主要有深度优先遍历(DFS)和广度优先遍历(BFS)两种。

    深度优先遍历(DFS):这种遍历方式类似于树的先序遍历。它从图的某个顶点开始,访问这个顶点,并尽可能深地搜索图的分支。当节点v的所在边都已被探寻过,搜索将回溯到发现节点v的那条边的起始节点。这一过程一直进行到已发现从源节点可达的所有节点为止。如果还存在未被发现的节点,则选择其中一个作为源节点并重复以上过程,整个进程反复进行直到所有节点都被访问为止。

    广度优先遍历(BFS):这种遍历方式是从图的某一顶点出发,首先访问这个顶点,然后找出这个顶点的所有未被访问过的相邻顶点,访问完后再从这些相邻顶点出发,继续寻找它们的未被访问过的相邻顶点,如此类推,直至图中所有已被访问过的顶点的邻接点都被访问到。广度优先遍历通常使用队列来实现。

这两种遍历方式各有特点,深度优先遍历在寻找路径时更偏向于深入搜索,而广度优先遍历则更偏向于先搜索近的节点再搜索远的节点。在解决不同的问题时,我们可以根据需要选择适合的遍历方式。

3)图的连通性:

    无向图中,如果从任意顶点都存在路径到达另一顶点,则称该图是连通的。

    有向图中,如果从任意顶点都存在路径到达另一顶点,则称该图是强连通的。

    无向图中的极大连通子图称为连通分量,而有向图中的极大连通子图称为强连通分量。

4)图的生成树和生成森林:

    连通图的生成树是包含图中全部顶点的一个极小连通子图,且不含环。

    对于非连通图,由各个连通分量的生成树组成的集合称为生成森林。

5)图的度:

    在无向图中,顶点的度是与该顶点相连的边的数目。

    在有向图中,顶点的度分为入度和出度,入度是以该顶点为终点的边的数目,出度是以该顶点为起点的边的数目。

6)图的特殊类型:

    完全图:在无向图中,如果任意两个顶点之间都存在边,则称该图为完全图。

    简单图:不存在重复边、不存在顶点到自身的边的图称为简单图。

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值