数据结构7.2--邻接表及广度优先遍历

一、代码

#include<stdio.h>
#include<malloc.h>
#define QUEUE_SIZE 10

int* visitedPtr;

/**
 * 图的数据结构
 */
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

/**
 * 队列的数据结构
 */
typedef struct GraphNodeQueue{
	int* nodes;
	int front;
	int rear;
} GraphNodeQueue, *QueuePtr;

/**
 * 初始化队列
 */
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

/**
 * 判断队列是否为空
 */
bool isQueueEmpty(QueuePtr paraQueuePtr){
	if((paraQueuePtr->front + 1) % QUEUE_SIZE == paraQueuePtr->rear){
		return true;
	}
	
	return false;
} // of isQueueEmpty

/** 
 * 在队列中加入结点
 */
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

/**
 * 在对队列中删除元素
 */
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

/**
 * 邻接结点的数据结构
 */
typedef struct AdjacencyNode{
	int column;
	AdjacencyNode* next;
} AdjacencyNode, *AdjacentNodePtr;

/**
 * 邻接表的数据结构
 */
typedef struct AdjacencyList{
	int numNodes;
	AdjacencyNode* headers;
} AdjacencyList, *AdjacencyListPtr;

/**
 * 构造邻接表
 */
AdjacencyListPtr graphToAdjacentList(GraphPtr paraPtr){
	//分配空间
	int i, j, tempNum;
	AdjacentNodePtr p, q;
	tempNum = paraPtr->numNodes;
	AdjacencyListPtr resultPtr = (AdjacencyListPtr)malloc(sizeof(struct AdjacencyList));
	resultPtr->numNodes = tempNum;
	resultPtr->headers = (AdjacencyNode*)malloc(tempNum * sizeof(struct AdjacencyNode));
	
	//填充数据
	for(i = 0; i < tempNum; i ++){
		//初始化头指针
		p = &(resultPtr->headers[i]);
		p->column = -1;
		p->next = NULL;
		
		for(j = 0; j < tempNum; j ++){
			if(paraPtr->connections[i][j] > 0){
				//创建一个新结点
				q = (AdjacentNodePtr)malloc(sizeof(struct AdjacencyNode));
				q->column = j;
				q->next = NULL;
				
				//连接
				p->next = q;
				p = q; 
			}// of if
		}//o for j
	}//of for i
	
	return resultPtr;
} //of graphToAdjacentList

/**
 * 输出邻接表
 */
void printAdjacentList(AdjacencyListPtr paraPtr){
	int i;
	AdjacentNodePtr p;
	int tempNum = paraPtr->numNodes;
	
	printf("This is the graph:\r\n");
	for(i = 0; i < tempNum; i ++){
		p = paraPtr->headers[i].next;
		while(p != NULL){
			printf("%d, ", p->column);
			p = p->next;
		}//of while
		printf("\r\n");
	}// of for i
} // of printAdjacentList


/**
 * 广度优先遍历
 */
void widthFirstTranverse(AdjacencyListPtr paraListPtr, int paraStart){
	printf("width first \r\n");
	//使用队列处理指针
	int i, j, tempNode;
	AdjacentNodePtr p;
	i = 0;
	
	//初始化数据
	visitedPtr = (int*)malloc(paraListPtr->numNodes * sizeof(int));
	
	for(i =0; i < paraListPtr->numNodes; i ++) {
		visitedPtr[i] = 0;
	}// of for i
	
	QueuePtr tempQueuePtr = initQueue();
	printf("%d\t", paraStart);
	visitedPtr[paraStart] = 1;
	enqueue(tempQueuePtr, paraStart);
	
	while(!isQueueEmpty(tempQueuePtr)){
		tempNode = dequeue(tempQueuePtr);
		
		for(p = &(paraListPtr->headers[tempNode]); p != NULL; p = p->next){
			j = p->column;
			
			if(visitedPtr[j])
				continue;
				
			printf("%d\t", j);
			visitedPtr[j] = 1;
			enqueue(tempQueuePtr, j);
		}// of for
	}//of while
	printf("\r\n");
} //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 ++){
			tempPtr[i][j] = myGraph[i][j];
		}//of for j
	}// of for i
	
	printf("Data ready\r\n");
	
	GraphPtr tempGraphPtr = initGraph(5, tempPtr);
	AdjacencyListPtr tempListPtr = graphToAdjacentList(tempGraphPtr);
	
	printAdjacentList(tempListPtr);
	
	widthFirstTranverse(tempListPtr, 4);
	
} // of testGraphTranverse

int main(){
	testGraphTranverse();
	return 0;
}

二、运行结果

三、代码说明

代码中有部分与7.1图的遍历是一样的,在此代码中主要理解的是如何将图转化为邻接表,以及邻接表的广度遍历,与图的广度遍历相似,都运用队列来进行操作。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值