您的位置:首页 > 其它

深度优先DFS和广度优先BFS,破圈法,拓扑序列,prim,克鲁斯卡尔等生成算法(需要用到并查集)迪杰斯特拉算法和弗洛伊德的总结

2016-12-16 16:07 791 查看
1.有向图:比较好

2.无向图是变态的有向图,需要注意度和节点之类的比如MST,最小生成树利用破圈法生成,关联的度为1的无向图节点肯定不是回路(不知道对不。。),1.找到图中的一个圈。2.删除其中的权最大的边。3.重复上述操作,直到图中已无圈。

针对无向图,可以这样做:

1.用拓扑分类算法,找到图中的圈。具体就是依次找到图中度为1的顶点(可以保存在队列里),删除之(这里的删除是暂时的,下次遍历还要还原这些点),然后与其邻接的顶点的入度-1,这样往复操作,直到图中已不存在入度为1的顶点,即所有的顶点的度都》=2,那么剩下的边就都在环里了。当然,如果没剩下边,说明没有环,算法结束。

2.剩下的边就都是环中的边了,找一个权最大的删去即可。

3.再进行1操作,直到图中无圈,即所有的圈都已破掉,剩下的就是最小生成树了。

还有DFS和BFS:

深度优先DFS和广度优先BFS的区分并不是看遍历结果

而是策略上的区分

简单说,深度优先 就是从某个点出发,依次递归深度优先遍历其每个未被访问的邻接点

广度优先,是从某个点出发,依次遍历其每个未被访问的邻接点(并做记录),再对之前一步记录的每个邻接点,重复上述过程

节点可变

3.还有prim,克鲁斯卡尔等生成算法(需要用到并查集)

4.迪杰斯特拉算法和弗洛伊德注重过程,怎么一步步来的,挺重要的

5.还有关键路径

关键路径分析

如图,每个节点表示一个必须执行的动作以及完成动作所花费的时间。该图叫做动作节点图。图中的边代表优先关系,一条边(v,w)意味着动作v必须在动作w开始前完成。(这意味着这个图必然是无圈的)。

这个图可以模拟两类问题:

1. 整个方案最早什么时间完成?

2. 确定哪些动作时可以延迟的,延迟多长,而不致影响最少完成时间?

我们把动作节点图转化为事件节点图

1. 每个事件对应一个动作和所有相关的动作的完成;

2. 从事件节点图中的节点v可达到的事件可以在事件v完成后开始;

3. 在一个动作依赖于几个其他动作的情况下,可能需要插入哑边和哑节点(保证每个真实点只有一条入边)。

为了找出方案的最早完成时间,我们只要找出从第一个事件到最后一个事件的最长路径长度。

由于这是个无圈图,可以采纳最短路径算法计算图中所有节点的最早完成时间。

如果ECi是节点i的最早完成时间,则有

1. EC1 = 0;

2. ECw = max(ECv + c(v,w))

用以下法则计算每个节点最晚完成时间

1. LCn = ECn;//最后一个点的最晚完成时间和最早完成时间相同

2.LCv = min(LCw - c(v,w))

对于每个顶点,通过保存一个所有邻接且在先的顶点的表,这些值就可以以线性时间算出。借助顶点的拓扑顺序计算它们的最早完成时间,而最晚完成时间则通过倒转它们的拓扑顺序来计算。

拓扑排序-》有向图

#include <iostream>
#include<stack>
#include<queue>
#include "MinHeap.h"
#include "MaxHeap.h"
using namespace std;
class UFsets{
private:
int n;
int *root;
int *next;
int *length;
public:
UFsets(int size)
{
n=size;
root =new int
;
next =new int
;
length=new int
;

for(int i=0;i<n;i++)
{
root[i]=next[i]=i;
length[i]=1;
}

}
int Find(int v)
{
return root[v];

}
void Union(int v,int u)
{
if(root[v]==root[u])
return;
else if(length[root[v]]<length[root[u]])
{

int rt=root[v];
length[root[u]]+=length[rt];
root[rt]=root[u];
for(int j=next[rt];j!=rt;j=next[j])
{
root[j]=root[u];

}
std::swap(next[rt],next[root[u]]);
}
else
{
int rt=root[u];
length[root[v]]+=length[rt];
root[rt]=root[v];
for(int j=next[rt];j!=rt;j=next[j])
{
root[j]=root[v];

}
std::swap(next[rt],next[root[u]]);
}

}
};
template<class T>

class Edge
{
public:
int start,end;
T weight;
Edge(int st,int ed,int w){start=st;end=ed;weight=w;};
Edge(){weight=0;end=-1;};
bool operator >(Edge one)
{

return weight>one.weight;
};
bool operator <(Edge one)
{
return weight<one.weight;
};
};
template<class T>
class AdjGraph
{
public:
int vertexNum;
int edgeNum;
int *Mark;
int **marix;

int getVertexNum(){return vertexNum;};
int getEdgesNum(){return edgeNum;};
bool IsEdge(Edge<T> one)
{
if(one.weight>0&&one.end>=0)
{
return true;
}
else
{
return false;
}
}
int startVertex(Edge<T>one)
{
return one.start;
}
int endVertex(Edge<T>one)
{
return one.end;
}
T Weight(Edge<T> one)
{
return one.weight;
}

AdjGraph(int verticeNum)
{
vertexNum=verticeNum;
edgeNum=0;

vertexNum=verticeNum;
Mark= new int[vertexNum];
for(int i=0;i<vertexNum;i++)
{
Mark[i]=0;
}
int i,j;
marix=new int*[vertexNum];
for(i=0;i<vertexNum;i++)
marix[i]=new int[vertexNum];
for(i=0;i<vertexNum;i++)
for(j=0;j<vertexNum;j++)
marix[i][j]=9999;

}
~AdjGraph()
{

for(int i=0;i<vertexNum;i++)
delete []marix[i];
delete []marix;
}
Edge<T> FirstEdge(int one)
{
Edge<T> tempEdge;
tempEdge.start=one;
for(int i=0;i<vertexNum;i++)
{
if(marix[one][i]!=0)
{
tempEdge.end=i;

tempEdge.weight=marix[one][i];
break;
}
}

return tempEdge;
}
Edge<T> NextEdge(Edge<T> one)
{
Edge<T> tempEdge;
tempEdge.end=-1;
tempEdge.start=one.start;
for(int i=one.end+1;i<vertexNum;i++)
{
if(marix[one.start][i]!=0)
{
tempEdge.end=i;
tempEdge.weight=marix[one.start][i];
break;
}
}
return tempEdge;
}
void setEdge(int start,int end,T weight)
{
if(marix[start][end]==9999)
{
edgeNum++;
}
marix[start][end]=weight;

}
void delEdge(int start,int end)
{
if(marix[start][end]!=0)
{
edgeNum--;
}
marix[start][end]=0;
}
void visit(int v)
{
cout<<v+1<<endl;
}
void DFS(int i)
{
Mark[i]=1;
visit(i);

for(int j=0;j<vertexNum;j++)
{
if(marix[i][j]!=9999&&(Mark[j]==0))
{
DFS(j);
}
}
}

void  DFSTraverse()
{
for(int i=0;i<vertexNum;i++)
{
Mark[i]=0;
}
for(int i=0;i<vertexNum;i++)
{
if(Mark[i]==0)
DFS(i);
}
}
void DFSNoReverse()
{
int i;
using std::stack;
stack<int >s;
for(i=0;i<vertexNum;i++)
{
Mark[i]=0;
}
cout<<1<<endl;
for(int i = 0; i <vertexNum; i++)
{
if(marix[i][0]!=9999&& !Mark[i] )/*先存储到栈不访问*/
{
Mark[i] =  1;
s.push(i);
}
}
while(!s.empty())
{
int s_top =  s.top();
Mark[s_top] = 1;
visit(s_top);
s.pop();
for(int i = 1; i <= vertexNum-1; i++)
{
if(marix[i][s_top]!=9999 && !Mark[i] )/*先存储到栈不访问*/
{
Mark[i] = 1;
s.push(i);
}
}
}
}
void Dijkstra(T mar[6][6],int n,int v,int flag[],int path[])
{
int *dist=new int
;

for(int i=0;i<n;i++)
{
dist[i]=mar[v][i];
path[i]=v;
flag[i]=0;
}
flag[v]=1;

for(int i=0;i<n-1;i++)
{    int min=9999;
int k=0;
for(int i=0;i<n;i++)
{
if(!flag[i])
{
if(dist[i]<min)
{
min=dist[i];
k=i;

}
}
}
cout<<k<<" "<<endl;
flag[k]=1;/*添加到集合*/
for(int j=0;j<n;j++)
{
if(!flag[j])
{
if(dist[j]>(dist[k]+mar[k][j]))
{
path[j]=k;
dist[j]=dist[k]+mar[k][j];
}
}
}
}
cout<<"Path---";
for(int i=0;i<n;i++)
{
cout<<path[i]<<" ";
}
cout<<endl;

}
void BFSTraverse()
{
int v;
for(v=0;v<vertexNum;v++)
Mark[v]=0;
int start=0;
visit(start);
Mark[start]=1;
using std::queue;
queue<T >q;
q.push(start);
while(!q.empty())
{
T temp=q.front();
q.pop();
if(!Mark[temp])
{
visit(temp);
Mark[temp]=1;
}
for(int i=0;i<vertexNum;i++)
{
if(marix[temp][i]!=9999&&(!Mark[i]))
q.push(i);
}
}
}
AdjGraph Prim()
{
int lowcost[vertexNum],vset[vertexNum],v,lowcostr[vertexNum];
int i,j,k,min,r;
int sum=0;
AdjGraph a(vertexNum);

for(i=0;i<vertexNum;i++)
{
lowcost[i]=marix[0][i];/*lowcost[] represents the minimal weight (Tree->node minweight)*/
vset[i]=0;/*wheater exist in the tree*/
lowcostr[i]=0;
}
vset[0]=1;/*insert to the tree*/

for(i=0;i<vertexNum-1;i++)/*insert n-1 times*/
{
min=99999;
for(j=0;j<vertexNum;j++)//寻找未访问的最小边的节点
{
if(vset[j]==0&&lowcost[j]<min)
{
r=lowcostr[j];
min=lowcost[j];
k=j;
}

}
vset[k]=1;
a.setEdge(r,k,min);
a.setEdge(k,r,min);
sum+=min;
v=k;
for(j=0;j<vertexNum;j++)//更新最小边
{
if(vset[j]==0&&marix[v][j]<lowcost[j])
{

lowcostr[j]=v;
lowcost[j]=marix[v][j];
}
}

}
cout<<"the sum of weight is "<<sum<<endl;
return a;
}
AdjGraph Kruskal()
{
int n=vertexNum;
UFsets set(n);
AdjGraph<T> b(n);
int sum=0;
MinHeap<Edge<T> > h(edgeNum/2);
Edge<T> edge;
for(int i=0;i<vertexNum;i++)
{
for(int j=0;j<vertexNum;j++)
{
if((j>i)&&(marix[i][j]!=9999))
{  Edge<T>a(i,j,marix[i][j]);
h.insert(a);

}
}
}
int edgenums=0;

while(edgenums<n-1)
{
if(!h.empty())
{
h.deleteTop(edge);//找最小边
int v=edge.start;
int u=edge.end;
if(set.Find(v)!=set.Find(u))//合并最小
{
set.Union(v,u);//并查集
b.setEdge(edge.start,edge.end,edge.weight);
b.setEdge(edge.end,edge.start,edge.weight);
edgenums++;
}
}
}

return b;
}
void Floyd(int adj[3][3],int path[3][3])
{
int i,j,k,v;
for(i=0;i<vertexNum;i++)
{
for(j=0;j<vertexNum;j++)
{
if(i==j)
{
adj[i][j]=0;
path[i][j]=i+1;
}
else
{
adj[i][j]=9999;
path[i][j]=-1;
}

}

}
for(v=0;v<vertexNum;v++)//初始化
{
for(j=0;j<vertexNum;j++)
{   if(marix[v][j]!=9999)
adj[v][j]=marix[v][j];
else
adj[v][j]=0;

path[v][j]=v+1;
}
}
for(v=0;v<vertexNum;v++)
{for(i=0;i<vertexNum;i++)
{

for(j=0;j<vertexNum;j++)
{if(adj[i][j]>(adj[i][v]+adj[v][j]))
{
adj[i][j]=adj[i][v]+adj[v][j];
path[i][j]=v+1;
}
}
}
}

for(int i=0;i<vertexNum;i++)
{
for(int j=0;j<vertexNum;j++)
cout<<path[i][j]<<" ";
cout<<endl;
}

}
void FindcycleByTopogySort(int ** marix,int *SortArray)
{
int *indegree=new int[vertexNum];
int v;
for(v=0;v<vertexNum;v++)//init
{
indegree[v]=0;
Mark[v]=0;
}
for(v=0;v<vertexNum;v++)//统计入度个数
{
for(int j=0;j<vertexNum;j++)
{
if(marix[v][j]==1)
{
indegree[j]++;
}
}
}
for(int i=0;i<vertexNum;i++)
{
for(v=0;v<vertexNum;v++)
{
if(indegree[v]==0&&Mark[v]==0)
{
break;
}
}
if(v==vertexNum)
{
for(int i=0;i<vertexNum;i++)
{
if(!Mark[i])
{    DFS(i);
break;
}
}

}
else
{
Mark[v]=1;
SortArray[i]=v;
for(int j=0;j<vertexNum;j++)
{
if(marix[v][j]==1)
{
indegree[j]--;
}
}
}
}

}

void MSTByTopogySort()
{
AdjGraph<int> adj(vertexNum);
int *indegree=new int[vertexNum];
int v;
int count=edgeNum/2;
int flag=1;
int flag2=1;
while(count>vertexNum-1)
{
for(v=0;v<vertexNum;v++)//init
{
indegree[v]=0;
Mark[v]=0;
}
for(v=0;v<vertexNum;v++)//统计入度个数
{
for(int j=0;j<vertexNum;j++)
{
adj.marix[v][j]==marix[v][j];
if(marix[v][j]!=9999)
{
indegree[j]++;
}
}
}
for(int i=0;i<vertexNum;i++)
{
cout<<indegree[i]<<endl;
}
flag=1;
for(int i=0;i<vertexNum&&flag;i++)
{

for(v=0;v<vertexNum;v++)
{
if(((indegree[v]==1))&&Mark[v]==0)
{

break;
}
}
if(v==vertexNum)
{

int flag1=1;

for(int i=0;i<vertexNum;i++)
{
if(!Mark[i])
{
Mark[i]=1;
int b=i;
MaxHeap<Edge<T> > e(edgeNum/2);
for(int a=i;a<vertexNum&&flag1;a++)
{

for(int j = i; j <vertexNum&&flag1; j++)
{
if(indegree[j]==1)
{
flag1=0;
}
}
}
if(flag1)
{
for(int a=b;a<vertexNum&&flag1;a++)
{

for(int j = b; j <vertexNum&&flag1; j++)
{
Edge<T>ee(a,j,marix[a][j]);
if(j>a&&(marix[a][j]!=9999))
{
e.insert(ee);
}

}
}
}
Edge<T>ee;
e.deleteTop(ee);
adj.marix[ee.start][ee.end]=9999;
adj.marix[ee.end][ee.start]=9999;
cout<<"bian"<<ee.start+1<<" "<<ee.end+1<<" "<<ee.weight<<endl;
marix[ee.start][ee.end]=9999;
marix[ee.end][ee.start]=9999;
indegree[ee.start]--;
indegree[ee.end]--;
count--;
flag=0;

break;
}
}

}
else
{
Mark[v]=1;

for(int j=0;j<vertexNum;j++)
{
if(marix[v][j]!=9999)
{
indegree[j]--;
indegree[v]--;
}
}

}

}
}
DFSNoReverse();
}
};

int main()
{
/* AdjGraph<int >d(8);
d.setEdge(0,1,1);
d.setEdge(0,2,1);
d.setEdge(1,3,1);
d.setEdge(1,4,1);
d.setEdge(3,7,1);
d.setEdge(4,7,1);
d.setEdge(2,5,1);
d.setEdge(2,6,1);
d.setEdge(5,6,1);
d.setEdge(6,5,1);
d.setEdge(6,2,1);
d.setEdge(5,2,1);
d.setEdge(7,4,1);
d.setEdge(7,3,1);
d.setEdge(4,1,1);
d.setEdge(3,1,1);
d.setEdge(2,0,1);
d.setEdge(1,0,1);
/* for(int i=0;i<a.getVertexNum();i++)
{
for(int j=0;j<a.getVertexNum();j++)
cout<<a.marix[i][j];
cout<<endl;
}

cout<<"DFS-"<<endl;
d.DFSNoReverse();
cout<<"BFS-"<<endl;
d.BFSTraverse();
cout<<"DFS-(digui)"<<endl;
d.DFSTraverse();*/
AdjGraph<int> a(6);
a.setEdge(0,1,6);
a.setEdge(0,3,5);
a.setEdge(0,2,1);
a.setEdge(1,2,5);
a.setEdge(1,4,3);
a.setEdge(2,4,6);
a.setEdge(2,5,4);
a.setEdge(2,3,5);
a.setEdge(3,5,2);
a.setEdge(4,5,6);
a.setEdge(1,0,6);
a.setEdge(3,0,5);
a.setEdge(2,0,1);
a.setEdge(2,1,5);
a.setEdge(4,1,3);
a.setEdge(4,2,6);
a.setEdge(5,2,4);
a.setEdge(3,2,5);
a.setEdge(5,3,2);
a.setEdge(5,4,6);
AdjGraph<int> b(6);
b=a.Kruskal();
cout<<"------------------------------Kruskal--------------"<<endl;
for(int i=0;i<b.getVertexNum();i++)
{ cout<<i+1<<" ";
for(int j=0;j<b.getVertexNum();j++)
cout<<b.marix[i][j]<<" ";
cout<<endl;
}
cout<<"------------------------------Prim--------------"<<endl;
AdjGraph<int> c(6);
c=a.Prim();
for(int i=0;i<c.getVertexNum();i++)
{ cout<<i+1<<" ";
for(int j=0;j<c.getVertexNum();j++)
cout<<c.marix[i][j]<<" ";
cout<<endl;
}
/*AdjGraph<int> c(6);
c.setEdge(0,2,10);
c.setEdge(1,2,5);
c.setEdge(0,4,30);
c.setEdge(0,5,100);
c.setEdge(2,3,50);
c.setEdge(3,5,10);
c.setEdge(4,3,20);
c.setEdge(4,5,60);
int flag[6];
int path[6];
c.Dijkstra(c.marix,c.vertexNum,0,flag,path);
return 0;*/
/*  AdjGraph<int> e(3);
e.setEdge(0,2,5);
e.setEdge(2,0,2);
e.setEdge(2,1,13);
e.setEdge(1,2,6);
e.setEdge(0,1,10);
e.setEdge(1,0,9);
int path[3][3];
int adj[3][3];
e.Floyd(adj,path);*/
AdjGraph<int> f(4);
f.setEdge(0,1,1);
f.setEdge(0,2,1);
f.setEdge(2,1,1);
f.setEdge(3,2,1);
f.setEdge(1,3,1);
int dd[5];
f.FindcycleByTopogySort(f.marix,dd);
/*AdjGraph<int> a(6);
a.setEdge(0,1,6);
a.setEdge(0,3,5);
a.setEdge(0,2,1);
a.setEdge(1,2,5);
a.setEdge(1,4,3);
a.setEdge(2,4,6);
a.setEdge(2,5,4);
a.setEdge(2,3,5);
a.setEdge(3,5,2);
a.setEdge(4,5,6);
a.setEdge(1,0,6);
a.setEdge(3,0,5);
a.setEdge(2,0,1);
a.setEdge(2,1,5);
a.setEdge(4,1,3);
a.setEdge(4,2,6);
a.setEdge(5,2,4);
a.setEdge(3,2,5);
a.setEdge(5,3,2);
a.setEdge(5,4,6);
a.MSTByTopogySort();*/
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐