前言——图的遍历
图遍历又称图的遍历,属于数据结构中的内容。指的是从图中的任一顶点出发,对图中的所有顶点访问一次且只访问一次。图的遍历操作和树的遍历操作功能相似。图的遍历是图的一种基本操作,图的许多其它操作都是建立在遍历操作的基础之上。
由于图结构本身的复杂性,所以图的遍历操作也较复杂,主要表现在以下四个方面:
① 在图结构中,没有一个“自然”的首结点,图中任意一个顶点都可作为第一个被访问的结点。
② 在非连通图中,从一个顶点出发,只能够访问它所在的连通分量上的所有顶点,因此,还需考虑如何选取下一个出发点以访问图中其余的连通分量。
③ 在图结构中,如果有回路存在,那么一个顶点被访问之后,有可能沿回路又回到该顶点。
④ 在图结构中,一个顶点可以和其它多个顶点相连,当这样的顶点访问过后,存在如何选取下一个要访问的顶点的问题。
一、实际操作
1.定义结构体
typedef struct GraphNodeQueue
{
int* nodes;
int front;
int rear;
}GraphNodeQueue, *QueuePtr;
2.初始化
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;
}
3.判断是否为空
bool isQueueEmpty(QueuePtr paraQueuePtr)
{
if((paraQueuePtr->front + 1) % QUEUE_SIZE == paraQueuePtr->rear)
{
return true;
}// Of if
return false;
}
4.添加
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;
}/
5.移动
{
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
6.遍历
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
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] =
{
{1, 1, 0, 1, 0},
{0, 1, 1, 0, 1},
{0, 0, 0, 1, 1},
{1, 0, 0, 1, 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
二、完整代码
#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] =
{
{1, 1, 0, 1, 0},
{0, 1, 1, 0, 1},
{0, 0, 0, 1, 1},
{1, 0, 0, 1, 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
三、测试结果
Preparing data
i = 0, j = 0, 155960
i = 0, j = 0, 1
i = 0, j = 1, 131264
i = 0, j = 1, 1
i = 0, j = 2, 1835228210
i = 0, j = 2, 0
i = 0, j = 3, 2019896932
i = 0, j = 3, 1
i = 0, j = 4, 1917059173
i = 0, j = 4, 0
i = 1, j = 0, 155960
i = 1, j = 0, 0
i = 1, j = 1, 131264
i = 1, j = 1, 1
i = 1, j = 2, 1953724755
i = 1, j = 2, 1
i = 1, j = 3, 842231141
i = 1, j = 3, 0
i = 1, j = 4, 1769096284
i = 1, j = 4, 1
i = 2, j = 0, 155960
i = 2, j = 0, 0
i = 2, j = 1, 131264
i = 2, j = 1, 0
i = 2, j = 2, 1464816194
i = 2, j = 2, 0
i = 2, j = 3, 1599227219
i = 2, j = 3, 1
i = 2, j = 4, 1599098945
i = 2, j = 4, 1
i = 3, j = 0, 155960
i = 3, j = 0, 1
i = 3, j = 1, 131264
i = 3, j = 1, 0
i = 3, j = 2, 544499054
i = 3, j = 2, 0
i = 3, j = 3, 1819310149
i = 3, j = 3, 1
i = 3, j = 4, 1919251055
i = 3, j = 4, 0
i = 4, j = 0, 155960
i = 4, j = 0, 0
i = 4, j = 1, 131264
i = 4, j = 1, 1
i = 4, j = 2, 1279870543
i = 4, j = 2, 1
i = 4, j = 3, 1414750021
i = 4, j = 3, 0
i = 4, j = 4, 1196312914
i = 4, j = 4, 0
Data ready
num nodes = 5
Graph initialized
Depth first visit:
4 1 2 3 0
Width first visit:
4 1 2 3 0
--------------------------------
Process exited after 2.536 seconds with return value 1
请按任意键继续. . .