图的概念
图是用线或边连接在一起的顶点或节点的集合。
图是顶点集 V V V 和边集 E E E 的有序对 G = ( V , E ) G=(V,E) G=(V,E)
图的分类
根据图的定义一个图不能有重复的边。
- 无向图(加权无向图)
- 有向图(加权有向图)
图的存储
图的存储分为:邻接矩阵,邻接链表,邻接数组
邻接矩阵:
部分原代码截取(全代码到GitHub获取)
template<typename T>
class Graph{
public:
Graph();
~Graph();
void inital();
void dfs1(){int x;cin>>x;dfs(x,1);output(1);}
void bfs1(){int x;cin>>x;bfs(x,1);output(1);}
void output(int);
private:
T** element;
T* reach;
void bfs(int,int);
void dfs(int,int);
int size;
const int MAX=1000000;
};
template<typename T>
Graph<T>::Graph(){
element=NULL;
reach=NULL;
size=0;
}
template<typename T>
Graph<T>::~Graph(){
for(int i=0;i<=size;i++){
delete [] element[i];
}
delete [] element;
delete [] reach;
reach=NULL;
element=NULL;
size=0;
}
template<typename T>
void Graph<T>::inital(){
int side_size;
cin>>size>>side_size;
element=new T * [size+1];
for(int i=0;i<=size;i++){
element[i]=new T [size+1];
}
for(int i=1;i<=size;i++)
for(int j=1;j<=size;j++){
if(i==j) element[i][j]=0;
else element[i][j]=MAX;
}
reach=new T [size+1];
for(int i=0;i<=size;i++){
reach[i]=MAX;
}
while(side_size--){
int x,y;
T w;
cin>>x>>y>>w;
//all the side is different
element[x][y]=w;
element[y][x]=w;
}
}
邻接链表:
其中的每个链表完全是自己维护的,也可以通过list(STL)维护链表(具体代码详见GitHub)
class Node{
public:
int index;
int weight;
Node * next;
Node(){index=0;weight=0;next=NULL;}
Node(int x,int y,Node * ne){
index=x;
weight=y;
next=ne;
}
};
template<typename T>
class Graph{
public:
Graph();
~Graph();
void inital();
// void dfs1(){int x;cin>>x;dfs(x,1);output(1);}
// void bfs1(){int x;cin>>x;bfs(x,1);output(1);}
// void output(int);
private:
Node** element;
T* reach;
// void bfs(int,int);
// void dfs(int,int);
int size;
const int MAX=1000000;
};
template<typename T>
Graph<T>::Graph(){
element=NULL;
reach=NULL;
size=0;
}
template<typename T>
Graph<T>::~Graph(){
for(int i=0;i<=size;i++){
Node* cur=element[i];
while(cur!=NULL){
Node* record=cur->next;
delete cur;
cur=record;
}
}
delete [] element;
delete [] reach;
reach=NULL;
element=NULL;
}
template<typename T>
void Graph<T>::inital(){
int side_size;
cin>>size>>side_size;
element=new Node* [size+1];
//inital all the element point to NULL
for(int i=0;i<=size;i++){
element[i]=NULL;
}
reach=new T [size+1];
for(int i=0;i<=size;i++){
reach[i]=MAX;
}
while(side_size--){
int x,y;
T w;
cin>>x>>y>>w;
//add to list
Node* cur_new=new Node (y,w,element[x]);
element[x]=cur_new;
cur_new=new Node (x,w,element[y]);
element[y]=cur_new;
}
}
图的遍历
(此处的代码都是通过邻接矩阵存储的图,其他方法详见GitHub)
- 深度优先搜索
具体算法- 首先从一个点开始,寻找连接与它的所有边,找到一条后,通过该条边找到另一个点,此时从找到的另一个点开始,继续搜索它邻接的边。
- 直到找不到邻接的边,就回溯到它的父亲节点(即从哪个点找到该点),继续搜索父亲节点邻接与的边。直到找完。
template<typename T>
void Graph<T>::dfs(int x,int label){
for(int i=1;i<=size;i++){
if(reach[i]!=label&&element[x][i]!=MAX){
reach[i]=label;
dfs(i,label); //find the next ,and mark the node with label
}
}
}
- 广度优先搜索
1. 从一个点开始,将于该点联通的所有点加入队列中。
2. 当第一个点的所有邻接点都找完之后,在开始下一层点的搜索。
3. 直到队列中不存在元素终止。
template<typename T>
void Graph<T>::bfs(int x,int label){
queue<int> que;
//add the start to queue.
que.push(x);
reach[x]=label;
while(!que.empty()){
int cur=que.front();
que.pop();
for(int i=1;i<=size;i++){
if(element[cur][i]!=MAX&&reach[i]!=label){ //add to queue
que.push(i);
reach[i]=label;
}
}
}
}
源代码GitHub GitHub
下一篇:图的应用