1.图的深度优先搜索DFS
DFS类似于树的先序遍历,是树的先序遍历的推广。在邻接矩阵中,DFS算法的空间复杂度为O(N),时间复杂度为O(N^2)。
DFS算法主要思路
1.从图中某个顶点v出发,访问v。
2.找出刚才访问过的顶点的第一个未被访问的邻接点,访问该顶点。以该顶点为起点,重复此步骤,直至刚访问过的顶点没有未被访问的邻接点为止。
3.返回前一个访问过的且未被访问的邻接点的顶点,找出该顶点的下一个未被访问的邻接点,访问该顶点。
4.重复步骤2,3,直至图中所有顶点都被访问过,搜索结束。
2.广度优先搜索BFS
BFS遍历类似于树的层次遍历。在邻接矩阵中,BFS算法的空间复杂度为O(N),时间复杂度为O(N^2)。
BFS算法主要思路
1。从图中某个顶点v出发,访问v。
2.依次访问v的各个未曾访问过的邻接点。
3.分别从这些邻接点出发依次访问它们的邻接点,并使“先被访问的顶点的邻接点”先于“后被访问的顶点的邻接点”被访问。重复步骤3,直至所有图中已被访问的顶点的邻接点都被访问。
3.代码实现
代码中DFS运用了递归的思想,BFS则使用队列实现类似层次遍历的效果。
#include<stdio.h>
#include<stdlib.h>
#define QUEUE_MAX 20
int* visitedPtr;
typedef struct Graph {
int** connections;
int numNode;
}*GraphPtr;
typedef struct Queue {
int* nodes;
int front, rear;
}Queue,*QueuePtr;
QueuePtr InitQueue()
{
QueuePtr resultPtr = (QueuePtr)malloc(sizeof(Queue));
resultPtr->nodes = (int*)malloc(QUEUE_MAX * sizeof(int));
resultPtr->front = 0;
resultPtr->rear = 1;
return resultPtr;
}//off InitQueue
bool isEmptyQueue(QueuePtr paraQueue)
{
if ((paraQueue->front + 1) % QUEUE_MAX == paraQueue->rear)
{
return true;
}//off if
return false;
}//off isEmptyQueue
void enqueue(QueuePtr paraQueue, int paraNode)
{
if ((paraQueue->rear + 1) & QUEUE_MAX == paraQueue->front)
{
printf("Queue full\r\n");
return;
}//off if
paraQueue->nodes[paraQueue->rear] = paraNode;
paraQueue->rear = (paraQueue->rear + 1) % QUEUE_MAX;
}//off enqueue
int dequeue(QueuePtr paraQueue)
{
if (isEmptyQueue(paraQueue))
{
printf("Error,queue empty\n");
return NULL;
}//off if
paraQueue->front = (paraQueue->front + 1) % QUEUE_MAX;
return paraQueue->nodes[paraQueue->front];
}//off dequeue
GraphPtr InitGraph(int paraSize, int** paraData)
{
GraphPtr resultPtr = (GraphPtr)malloc(sizeof(Graph));
resultPtr->numNode = paraSize;
resultPtr->connections = (int**)malloc(paraSize * sizeof(int*));
for (int i = 0; i < paraSize; i++)
{
resultPtr->connections[i] = (int*)malloc(paraSize * sizeof(int));
for (int j = 0; j < paraSize; j++)
{
resultPtr->connections[i][j] = paraData[i][j];
}//off for j
}//off for i
return resultPtr;
}//off InitQueue
void InitTranverse(GraphPtr paraGraphPtr)
{
visitedPtr = (int*)malloc(paraGraphPtr->numNode * sizeof(int));
for (int i = 0; i < paraGraphPtr->numNode; i++)
{
visitedPtr[i] = 0;
}//off for
}//off InitTranverse
void depthFirstTranverse(GraphPtr paraGarphPtr, int paraNode)
{
visitedPtr[paraNode] = 1;
printf("%d\t", paraNode);
for (int i = 0; i < paraGarphPtr->numNode; i++)
{
if (!visitedPtr[i])
{
if (paraGarphPtr->connections[paraNode][i])
{
depthFirstTranverse(paraGarphPtr, i);
}//off if
}//off if
}//off for
}//off depthFirstTranverse
void widthFirstTranverse(GraphPtr paraGraphPtr, int paraStart)
{
QueuePtr tempQueuePtr = InitQueue();
printf("%d\t", paraStart);
visitedPtr[paraStart] = 1;
enqueue(tempQueuePtr, paraStart);
while (!isEmptyQueue(tempQueuePtr))
{
int tempNode = dequeue(tempQueuePtr);
visitedPtr[tempNode] = 1;
for (int i = 0; i < paraGraphPtr->numNode; i++)
{
if (visitedPtr[i])
{
continue;
}//off if
if (paraGraphPtr->connections[tempNode][i] == 0)
{
continue;
}//off if
printf("%d\t", i);
visitedPtr[i] = 1;
enqueue(tempQueuePtr, i);
}//off for
}//off while
}//off widthTranverse
int main()
{
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;
tempPtr = (int**)malloc(5 * sizeof(int*));
for (int i = 0; i < 5; i++)
{
tempPtr[i] = (int*)malloc(5 * sizeof(int));
for (int j = 0; j < 5; j++)
{
tempPtr[i][j] = myGraph[i][j];
}//off for j
}//off for i
GraphPtr tempGraphPtr = InitGraph(5, tempPtr);
printf("Detph first visit: ");
InitTranverse(tempGraphPtr);
depthFirstTranverse(tempGraphPtr, 4);
printf("\nWidth first visit: ");
InitTranverse(tempGraphPtr);
widthFirstTranverse(tempGraphPtr, 4);
return 0;
}