一、代码
#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图的遍历是一样的,在此代码中主要理解的是如何将图转化为邻接表,以及邻接表的广度遍历,与图的广度遍历相似,都运用队列来进行操作。