图的深度和广度遍历

图是一种较为复杂的数据结构,它是一种非线性的数据结构,表示多对多的关系。树和线性表都是一种特殊的图。这里就简单的介绍图的深度和广度优先遍历。

深度优先遍历即从一个节点找到和它相连接的最小节点后,又继续找最小节点相连接的最小节点,代码中使用了递归,为了防止重复找到,还会采用另一个数组来记录各节点是否被访问过。

原理图:

 

代码:

void depthFirstTranverse(GraphPtr paraGraphPtr,int paraNode){
	int i;
	visitedPtr[paraNode] = 1;
	printf("%d ",paraNode);
	
	for(i = 0;i < paraGraphPtr->numNodes;i++){
		if(paraGraphPtr->connections[paraNode][i]==1&&visitedPtr[i]==0){
			depthFirstTranverse(paraGraphPtr,i);
		}
	}
}

广度优先遍历:从一个结点找到和它连接的所有节点并保存,接着从和它相邻的节点中编号从小到大开始遍历。同样要借助数组标记是否被访问,重复访问则不在保存。这里要采用循环队列的帮助。为重复访问且被访问的结点存入队中,然后依次出队寻找各个节点相邻的结点,和树的广度遍历相似。

图示

代码:

void widthFirstTranverse(GraphPtr paraGraphPtr,int paraNode){
	int i,tempNode;
	QueuePtr temQueuePtr = initQueue();
	enqueue(temQueuePtr ,paraNode);
	visitedPtr[paraNode] = 1;
	while(!isQueueEmpty(temQueuePtr)){
		tempNode = dequeue(temQueuePtr);
		printf("%d ",tempNode);
		visitedPtr[tempNode] = 1;
		
		for(i = 0;i < paraGraphPtr->numNodes;i++){
			if(paraGraphPtr->connections[tempNode][i]==1&&visitedPtr[i]==0){
				enqueue(temQueuePtr,i);
				visitedPtr[i]=1;
			}
		}
	}
}

全部代码:

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

#define QUEUE_SIZE 10

int *visitedPtr; 

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

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

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

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

	return false;
}

void enqueue(QueuePtr paraQueuePtr,int paraNode){
	if((paraQueuePtr->rear+1)%QUEUE_SIZE == paraQueuePtr->front%QUEUE_SIZE){
		printf("错误,%d尝试入队,队已满\n");
		return;
	}
	paraQueuePtr->nodes[paraQueuePtr->rear] = paraNode;
	paraQueuePtr->rear = (paraQueuePtr->rear+1)%QUEUE_SIZE;
	return;
}

int dequeue(QueuePtr paraQueuePtr){
	if((paraQueuePtr->front+1)%QUEUE_SIZE == paraQueuePtr->rear){
		printf("队列已空\n");
		return NULL; 
	}
	paraQueuePtr->front = (paraQueuePtr->front+1)%QUEUE_SIZE;
	return paraQueuePtr->nodes[paraQueuePtr->front];
}

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

void initTranverse(GraphPtr paraGraphPtr){
	int i;
	visitedPtr = (int*)malloc(sizeof(int)*paraGraphPtr->numNodes);
	
	for(i = 0;i < paraGraphPtr->numNodes;i++){
		visitedPtr[i] = 0;
	}
}

void depthFirstTranverse(GraphPtr paraGraphPtr,int paraNode){
	int i;
	visitedPtr[paraNode] = 1;
	printf("%d ",paraNode);
	
	for(i = 0;i < paraGraphPtr->numNodes;i++){
		if(paraGraphPtr->connections[paraNode][i]==1&&visitedPtr[i]==0){
			depthFirstTranverse(paraGraphPtr,i);
		}
	}
}

void widthFirstTranverse(GraphPtr paraGraphPtr,int paraNode){
	int i,tempNode;
	QueuePtr temQueuePtr = initQueue();
	enqueue(temQueuePtr ,paraNode);
	visitedPtr[paraNode] = 1;
	while(!isQueueEmpty(temQueuePtr)){
		tempNode = dequeue(temQueuePtr);
		printf("%d ",tempNode);
		visitedPtr[tempNode] = 1;
		
		for(i = 0;i < paraGraphPtr->numNodes;i++){
			if(paraGraphPtr->connections[tempNode][i]==1&&visitedPtr[i]==0){
				enqueue(temQueuePtr,i);
				visitedPtr[i]=1;
			}
		}
	}
}

int main(){
	int i,j;
	
	int data[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 **temPtr = (int**)malloc(sizeof(int*)*5);
	for(i = 0;i < 5;i++){
		temPtr[i]=(int*)malloc(sizeof(int)*5);
		for(j = 0;j < 5;j++){
			temPtr[i][j] = data[i][j];
		}
	}
	printf("Data ready\r\n");
	
	GraphPtr tempGraphPtr = initGraph(5, temPtr);
	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);
}

测试结果:

 

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值