图是一种较为复杂的数据结构,它是一种非线性的数据结构,表示多对多的关系。树和线性表都是一种特殊的图。这里就简单的介绍图的深度和广度优先遍历。
深度优先遍历即从一个节点找到和它相连接的最小节点后,又继续找最小节点相连接的最小节点,代码中使用了递归,为了防止重复找到,还会采用另一个数组来记录各节点是否被访问过。
原理图:
代码:
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);
}
测试结果: