深度搜索和广度搜索领接表实现_简单无向图(邻接表实现及深度优先和广度优先算法)...

数据结构图

图这种数据结构体接触的很少, 在这里记录一下最简单的无向图, 以及其相关的Breadth First Search,Depth First Search算法

这里使用邻接表实现

邻接表

邻接表.gif

在代码中的表现就比如这样, 每一行存储一个顶点连接的其他顶点(特别适用于稀疏图)

0 -> 1 5 2 3

1 -> 0 8 4 5

2 -> 0 4 5 6

3 -> 0 7 8 5

4 -> 2 1 7 9

5 -> 0 2 1 3 6 8

6 -> 5 2

7 -> 3 4 8 9

8 -> 1 3 5 7

9 -> 4 7

这里是我在C++中随机生成的一个图, 在C++中就表现为 vector>这样的二维"数组", 每一行表示一个vector中的数据

代码

这里就不做太详细的介绍了, 后面简单介绍一下算法思想

#include

#include

#include

#include

static void path_print(std::vector &prev, int start, int target)

{

if(start != target && prev[target] != -1)

{

path_print(prev, start, prev[target]);

}

printf("%d ", target);

}

class Graph

//无向图,使用邻接表表示

{

public:

Graph(int v):adj(v)

{

vertex = v;

}

void addEdge(int s, int t)

{

adj[s].push_back(t);

adj[t].push_back(s);

}

void print()

{

for(int i = 0; i < adj.size(); i++)

{

printf("%d ->\t", i);

for(auto b : adj[i])

{

printf("%d\t", b);

}

printf("\n");

}

}

/*Breadth First Search, search the shortest path

* 假设点数为V 边数为E, 那么时间复杂度O(V+E), 最多每个边和每个顶点被访问一次

* 需要使用的数组队列, 其长度不会超过V, 空间复杂的为O(V)

* */

bool bsf(int s, int t)

{

if(s == t) return false;

std::queue queue;

std::vector visited(vertex, false);

std::vector prev;

queue.push(s);

prev.push_back(s);

visited[s] = true;

while (queue.size())

{

int index = queue.front();

queue.pop();

for(auto c : adj[index])

{

if(t == c)

{

printf("print bfs result path:\n");

path_print(prev, s, t);

printf("\n");

return true;

}

else if(!visited[c])

{

prev[c] = index;

visited[c] = true;

queue.push(c);

}

}

printf("\n");

}

printf("can't find the path form %d -> %d\n", s, t);

return false;

}

/* Depth First Search

* 空间复杂度为O(V), 时间复杂度为O(E)

* */

bool dfs(int s, int t)

{

if(s == t)

{

return true;

}

std::vector prev(vertex, -1);

std::vector visited(vertex, false);

visited[s] = true;

if(recurDfs(s, t, visited, prev))

{

printf("print dfs result path:\n");

path_print(prev, s, t);

printf("\n");

return true;

}

else

{

return false;

}

}

bool recurDfs(int start, int target, std::vector &visited, std::vector &prev)

{

if(start == target)

{

return true;

}

else

{

for(auto c : adj[start])

{

if(!visited[c])

{

prev[c] = start;

visited[c] = true;

if(recurDfs(c, target, visited, prev))

{

return true;

}

}

}

return false;

}

}

private:

int vertex;

std::vector<:vector>> adj;

};

/*

* create a Random Graph with n vertex and e edge

* max e = (v-1)v/2 min e = v - 1

* */

static void Random_Graph(Graph &graph, int v, int e)

{

srand(time(NULL));

e = e > (v-1)*v/2 ? (v-1)*v/2 : e;

e = e < (v-1) ? (v - 1) : e;

std::vector<:vector>> tmp(v, std::vector(v, 0));

for(int i = 0; i < v; i++)

{

while(true)

{

int k = rand() % v;

if(k != i)

{

tmp[i][k] = 1;

e--;

break;

}

}

}

//确保每一个点都有一条边

while(e > 0)

{

int i = rand() % v;

int j = rand() % v;

if(i != j && !tmp[i][j] && !tmp[j][i])

{

tmp[i][j] = 1;

e--;

}

}

for(int i = 0; i < v; i++)

{

for(int j = 0; j < v; j++)

{

if(i != j && tmp[i][j])

{

tmp[j][i] = 0;

graph.addEdge(i, j);

}

}

}

graph.print();

}

int main() {

Graph gra(10);

Random_Graph(gra, 10, 20);

gra.bsf(4, 5);

gra.dfs(4, 5);

system("pause");

return 0;

}

实现思想

BFS(广度优先)

std::queue queue;

/*记录将要遍历其下一级的顶点,使用队列先进先出,*/

std::vector visited(vertex, false);

/*避免重复进行, 用以判断是否曾经遍历过*/

std::vector prev;

/*用于打印, val表示index对应顶点的上一级*/

DFS(深度优先)

采用递归的方式实现

时间空间复杂度

假设顶点数为V, 边数为E

对于BFS, 每个顶点每个边最多可能经过一次, 时间复杂的为o(V+E), 所需要的一些临时空间其大小不超过顶点数, 空间复杂度为O(V)

对于DFS, 每个边最多被访问两次(递归/回退), 时间复杂度为O(E), 空间复杂度还是O(V)

你可能感兴趣的:(深度搜索和广度搜索领接表实现)