赞
踩
图(Graph)是由顶点的有穷非空集合和顶点之间边的集合组成的一种非线性表结构,通常表示为:G(V,E),其中,G表示一个图,V是图G中顶点的集合,E是图G中边的集合。
在无向图中,如果任意两个顶点之间都存在边,则称该图为无向完全图。
含有n个顶点的无向完全图有n×(n-1)/2条边
在有向图中,如果任意两个顶点之间都存在方向互为相反的两条弧,则称该图为有向完全图。
含有n个顶点的有向完全图有n×(n-1)条边
如果从顶点v到顶点w之间有路径,则称顶点v和w连通。
连通图一般都是指无向图。
顶点数为n的连通图,至少有n-1条边。
在有向图中,若从顶点v到w有路径,则称这两个顶点强连通。若任意一对顶点都是强连通的,称此图为强连通图。
顶点数为n的强连通图,最少有n条边。
图的邻接矩阵(Adjacency Matrix)存储方式是用两个数组来表示图。一个一维数组存储图中顶点信息,一个二维数组(称为邻接矩阵)存储图中的边信息。
无向图
有向图
使用邻接矩阵的存储方式比较简单、直接,且可以高效的获取两个顶点的关系;但是由于存在n个顶点的图需要n*n个数组元素进行存储,当图为稀疏图时,使用邻接矩阵存储方法将会出现大量0元素,这会造成极大的空间浪费。这时,可以考虑使用邻接表表示法来存储图中的数据。
图的顶点对应一条链表,链表中存储的是与这个顶点相连接的其他顶点。
邻接表存储起来比较节省空间,但是使用起来就比较耗时间。
当链表过长,为了提高查找效率,我们可以将链表换成其他更加高效的数据结构,如平衡二叉树(红黑树)、跳表、散列表等。
图的深度优先遍历,类似于树的先序遍历,主要思想是首先选择一个未被访问过的顶点作为起始顶点,沿当前顶点的边走到未访问过的顶点。当没有未访问过的顶点时,则回到上一个顶点,继续试探别的顶点,直至所有的顶点都被访问过。
以无向图为例,深度优先搜索的算法步骤。
- //递归实现
- void DfsRecursive(int v)
- {
- cout<<v<<" ";
- //将v标记为已读
- visited[v] = true;
-
- for (int i = 0; i < vertexNum; i++)
- {
- //选择一个没有被标记过的节点
- if ((arc[v][i] != 0 && arc[v][i] != inf) && visited[i] == 0)
- {
- DfsRecursive(i);
- }
- }
-
- }
- //非递归
- void DFS(int v) {
- stack<int> st;
- st.push(v); // 将起始顶点压入栈中
-
- visited[v]=true // 标记起始顶点为已访问
-
- while (!st.empty()) {
- v = stack.top();
- stack.pop();
-
- cout << v << " "; // 访问顶点v
-
- // 遍历顶点v的所有邻接点
- for (int i = 0; i < vertexNum; i++)
- {
- //选择一个没有被标记过的节点
- if ((arc[v][i] != 0 && arc[v][i] != inf) && visited[i] == false)
- {
- st.push(i);
- }
- }
-
- }
- }
深度优先搜索的时间复杂度为 O(E),E 表示边的个数;空间复杂度为 O(V),V 表示顶点的个数。
广度优先遍历从某个顶点 v 出发,首先访问这个结点,并将其标记为已访问,然后顺序访问v的所有未被访问的邻接点 {vi,..,vj} ,并将其标记为已访问,然后将 {vi,...,vj} 中的每一个节点重复节点v的访问方法,直到所有结点都被访问完为止。
步骤:
- void BFS(int v)
- {
- queue<int> q;
- q.push(v);
- visited[v] = true;
- while (!q.empty())
- {
- v = q.front();
- q.pop();
- cout<<v<<" ";
- for (int i = 0; i < vertexNum; i++)
- {
- if ((arc[v][i] !=0&&arc[v][i]!=inf) && visited[i] == false)
- {
- q.push(i);
- visited[i] = true;
- }
- }
-
- }
-
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。