数据结构邻接表

本文详细介绍了图的深度优先遍历(DFS)和宽度优先遍历(BFS)算法的C语言实现。通过创建队列结构进行BFS,使用递归实现DFS,展示了如何遍历图中的所有节点。这两个算法在图论和数据结构中至关重要,常用于搜索和遍历问题。
摘要由CSDN通过智能技术生成
#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] = { 
		{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(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

深度遍历

//深度遍历(用递归) 
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);
			}
		}
	}
}

图的深度遍历是一个递归的过程,类似于树的先序遍历。
遍历过程:从某个顶点v出发,首先访问该顶点,然后依次从它的各个未被访问的点,直至图中所有和v有路径相通的顶点都被访问到。 若此时尚有其他顶点未被访问到,则另选一个未被访问的顶点作起始点,重复上述过程,直至图中所有顶点都被访问到为止。

广度遍历

//广度遍历(队列实现) 
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;
		
		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);
		}
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值