好几天没有补算法了。以前对于图的各种算法没有学好,特此机会重新复习一下图的基本算法。
图的定义:
图是一种数据结构,和树一样可以用二元组表示。它可定义为Graph=(V,R)其中,V={x|x∈datatype},R={VR},VR={(x,y)|P(x,y)∧(x,y∈V)}, V是顶点的非空有穷集合,R是边的有穷集合。
也就是说说,图就是记录一些点和点之间的关系的数据结构。
图的存储:
1:邻接矩阵:一个二维数组,不同下标对应着不同的点。分为无向图和有向图。如果是无向图,vi<->vj 即 graph[vi][vj] = graph[vj][vi] = 1; 有向图 vi->vj 则只有graph[vi][vj] = 1。如果边上有权重val,则graph[vi][vj] = val。
而虽然邻接矩阵在记录边关系时很方便,但是面临的问题是浪费大量空间,特别是面对稀疏图(即图中边的数量大大少于节点数量)时,问题尤其明显。因为我们的示例图很简单,所以接下来我用的都是邻接矩阵。
2:邻接表:
邻接表的出现解决了邻接矩阵的问题,即使用了链式结构。 邻接表的处理方法是这样的:
(1):图中顶点用一个一维数组存储。
(2):图中每个顶点vi的所有邻接点构成一个线性表,由于邻接点的个数不定,所以,用链表存储。链表中每个节点有两个信息:当前顶点的下标,指向下一节点的指针。在该图中,数组里面的下标对应不同的顶点,而链表里的节点对应这个顶点的邻接点。
图的遍历:
1:深度优先搜索(DFS):注重的是深度优先。
拿上图举例,我们从v1出发,如果我们先走左边的顶点(这个左边在程序里即第一个顶点),我们走到了v2,发现还能往下(下的意思是有邻接点存在)走,走左边到了v4,发现有岔路口,但是v1我们走过了,只能走v5,v5走到了v3。此时全部点都遍历了一遍,即DFS完成。顺序:v1,v2,v4,v5,v3。
2:广度优先搜索(BFS):注重广度,按层次遍历。
即先把眼前的地方先走一遍,再接着遍历更远的地方。拿上图举例。我们从v1出发,首先把眼前的顶点遍历完(即遍历v1所有的邻接点),我们遍历了v2,v3,v4。然后从最左边的顶点接着重复此过程,遍历了v5。此时全部点都遍历了一遍,即BFS完成。顺序:v1,v2,v3,v4,v5。
了解基本思想,仔细阅读源代码,并动手运算一遍。
//本实例通过建立邻接矩阵来遍历图
#include <iostream>
#include <cstdlib>
#include <cassert>
#include <cstring>
#include <queue>
using namespace std;
#define MAX 100
#define max(x,y)(x > y ? x : y)
//这里假设我们从顶点1开始遍历
#define initNode 1
typedef struct{
int matrix[MAX][MAX];
int num;
}Graph;
Graph example;
void createPoint()
{
int i, j;
//图的初始化
memset(example.matrix, 0 ,sizeof(example.matrix));
example.num = 0;
while(cin>>i>>j && i != 0 && j != 0)
{
example.matrix[i][j] = 1;
example.matrix[j][i] = 1;
//出现的最大数即为最大顶点数
example.num = max(example.num, i);
example.num = max(example.num, j);
}
}
void DFS(int x, int* visited)
{
cout<<" "<<x;
for(int i = 1; i <= example.num; i++)
{
if (visited[i] == 0 && example.matrix[x][i] == 1)
{
visited[i] = 1;
DFS(i, visited);
}
}
}
void BFS()
{
int i, nNode;
queue<int> gQueue;
int* visited = new int[example.num++];
memset(visited, 0, sizeof(int)*(example.num++));//此处的*为乘号
cout<<"BFS"<<"------------------"<<endl;
visited[initNode] = 1;
gQueue.push(initNode);
while(!gQueue.empty())
{
nNode = gQueue.front();
cout<<" "<<nNode;
for (int i = 1; i <= example.num; ++i)
{
if(example.matrix[nNode][i] == 1 && visited[i] == 0)
{
gQueue.push(i);
visited[i] = 1;
}
}
gQueue.pop();
}
cout<<endl<<"--------------"<<endl;
}
void initDFS()
{
int* visited = new int[example.num++];
memset(visited, 0, sizeof(int)*(example.num++));
cout<<"DFS"<<"----------------"<<endl;
visited[initNode] = 1;
DFS(initNode,visited);
cout<<endl<<"DFS"<<"----------------"<<endl;
}
void test()
{
createPoint();
cout<<example.num<<endl;
BFS();
initDFS();
}
int main(int argc, char const *argv[])
{
test();
return 0;
}
参考文章:http://blog.csdn.net/u010006643/article/details/45673571