数据结构学习——图的遍历


前言——图的遍历

图遍历又称图的遍历,属于数据结构中的内容。指的是从图中的任一顶点出发,对图中的所有顶点访问一次且只访问一次。图的遍历操作和树的遍历操作功能相似。图的遍历是图的一种基本操作,图的许多其它操作都是建立在遍历操作的基础之上。
由于图结构本身的复杂性,所以图的遍历操作也较复杂,主要表现在以下四个方面:
① 在图结构中,没有一个“自然”的首结点,图中任意一个顶点都可作为第一个被访问的结点。
② 在非连通图中,从一个顶点出发,只能够访问它所在的连通分量上的所有顶点,因此,还需考虑如何选取下一个出发点以访问图中其余的连通分量。
③ 在图结构中,如果有回路存在,那么一个顶点被访问之后,有可能沿回路又回到该顶点。
④ 在图结构中,一个顶点可以和其它多个顶点相连,当这样的顶点访问过后,存在如何选取下一个要访问的顶点的问题。

在这里插入图片描述

一、实际操作

1.定义结构体

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

2.初始化

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;
}

3.判断是否为空

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

4.添加

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;
			
}/

5.移动

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

6.遍历

typedef struct Graph
{
	int** connections;
	int numNodes;
} *GraphPtr;
	  
	  
	  
GraphPtr initGraph(int paraSize, int** paraData) 
{
	int i,j;
	GraphPtr resultPtr = (GraphPtr)malloc(sizeof(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

void initTranverse(GraphPtr paraGraphPtr) 
{
	int i;
	//Initialize 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)
{
	//Use a queue to manage the pointers
	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 j
	}//Of while
}//Of widthFirstTranverse
 
void testGraphTranverse() 
{
	int i, j;
	int myGraph[5][5] = 
	{ 
		{1, 1, 0, 1, 0},
		{0, 1, 1, 0, 1}, 
		{0, 0, 0, 1, 1}, 
		{1, 0, 0, 1, 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(5 * sizeof(int));
	}//Of for i
	 
	for (i = 0; i < 5; i ++) 
	{
		for (j = 0; j < 5; j ++) 
		{
			printf("i = %d, j = %d, ", i, j);
			printf("%d\r\n", tempPtr[i][j]);
			tempPtr[i][j] = myGraph[i][j];
			printf("i = %d, j = %d, %d\r\n", i, j, tempPtr[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

二、完整代码

#include <stdio.h>
#include <malloc.h>
 
#define QUEUE_SIZE 10
 
int* visitedPtr;
 
/**
 * A queue with a number of indices.
 */
typedef struct GraphNodeQueue
{
 	int* nodes;
 	int front;
 	int rear;
}GraphNodeQueue, *QueuePtr;
 
 /**
  * Initialize 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 iniQueue
  	
  	/**
  	 * 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 queue.
	    */
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 NULL;
	}// 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(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
 
/**
 * Initialize the tranverse.
 */
void initTranverse(GraphPtr paraGraphPtr) 
{
	int i;
	//Initialize 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)
{
	//Use a queue to manage the pointers
	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 j
	}//Of while
}//Of widthFirstTranverse
 
void testGraphTranverse() 
{
	int i, j;
	int myGraph[5][5] = 
	{ 
		{1, 1, 0, 1, 0},
		{0, 1, 1, 0, 1}, 
		{0, 0, 0, 1, 1}, 
		{1, 0, 0, 1, 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(5 * sizeof(int));
	}//Of for i
	 
	for (i = 0; i < 5; i ++) 
	{
		for (j = 0; j < 5; j ++) 
		{
			printf("i = %d, j = %d, ", i, j);
			printf("%d\r\n", tempPtr[i][j]);
			tempPtr[i][j] = myGraph[i][j];
			printf("i = %d, j = %d, %d\r\n", i, j, tempPtr[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

三、测试结果

Preparing data
i = 0, j = 0, 155960
i = 0, j = 0, 1
i = 0, j = 1, 131264
i = 0, j = 1, 1
i = 0, j = 2, 1835228210
i = 0, j = 2, 0
i = 0, j = 3, 2019896932
i = 0, j = 3, 1
i = 0, j = 4, 1917059173
i = 0, j = 4, 0
i = 1, j = 0, 155960
i = 1, j = 0, 0
i = 1, j = 1, 131264
i = 1, j = 1, 1
i = 1, j = 2, 1953724755
i = 1, j = 2, 1
i = 1, j = 3, 842231141
i = 1, j = 3, 0
i = 1, j = 4, 1769096284
i = 1, j = 4, 1
i = 2, j = 0, 155960
i = 2, j = 0, 0
i = 2, j = 1, 131264
i = 2, j = 1, 0
i = 2, j = 2, 1464816194
i = 2, j = 2, 0
i = 2, j = 3, 1599227219
i = 2, j = 3, 1
i = 2, j = 4, 1599098945
i = 2, j = 4, 1
i = 3, j = 0, 155960
i = 3, j = 0, 1
i = 3, j = 1, 131264
i = 3, j = 1, 0
i = 3, j = 2, 544499054
i = 3, j = 2, 0
i = 3, j = 3, 1819310149
i = 3, j = 3, 1
i = 3, j = 4, 1919251055
i = 3, j = 4, 0
i = 4, j = 0, 155960
i = 4, j = 0, 0
i = 4, j = 1, 131264
i = 4, j = 1, 1
i = 4, j = 2, 1279870543
i = 4, j = 2, 1
i = 4, j = 3, 1414750021
i = 4, j = 3, 0
i = 4, j = 4, 1196312914
i = 4, j = 4, 0
Data ready
num nodes = 5
Graph initialized
Depth first visit:
4       1       2       3       0
Width first visit:
4       1       2       3       0
--------------------------------
Process exited after 2.536 seconds with return value 1
请按任意键继续. . .
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值