数据结构8——图(2)

本文介绍了图数据结构中的重要概念,包括最小生成树的Prim法和Kruskal法,以及最短路径的Dijkstra方法和Floyd方法。此外,还探讨了AOV网的拓扑排序和AOE网的关键路径计算,是理解图论和算法的良好资源。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、最小生成树(最小代价生成树)

Prim法:(加点法)           

    时间复杂度:O(n*n)——适用于稠密图

   辅助数组:lowcost(=arc[0][i])和adjvex(=0)(0是始点)      

      

void prime(MGraph G){
    for(int i=1;i<G.vertexNu;i++){//若有n个点,需要执行共n-1次操作
        lowcost[i]=G.arc[0][i];  //用于从中选取最短边  
adjvex[i]=0; 
    }
    lowcost[0]=0;
    for(i=1;i<G.vertexNum;i+++){
        k=MinEdge(lowcost,G.vertexNum)
        cout<<K<<adjvex[k]<<lowcost[k];
        lowcost[k]=0;
     for(j=1;j<G.vertexNum;j++)
        if((G.arc[k][j]<lowcost[j]){
        lowcost[j]=G.arc[k][j];
        arcvex[j]=k;	
        }
    }
}

Kruskal法:(加边法)

时间复杂度:O(eloge)

int main(){
    int arcNum, int vertexNum;
    EdgeNode *edge;
    int *parent;
    cout<<"please input the number of vertexNum:"; cin>>vertexNum;
    cout<<"please input the number of edges:";	cin>>arcNum;
    edge=new EdgeNode[arcNum];	parent=new int[vertexNum];
    for(int i=0;i<arcNum;i++)	{
 	cout<<"Please input the edges:";
	cin>>edge[i].from>>edge[i].to>>edge[i].weight;
    }
    sort(edges, G); //对边集数组进行堆排序,时间复杂性为O(eloge)
    for (i=0;i<vertexNum;i++)
	parent[i]=-1;  //每个节点分属于不同的集合
    int k=0,begin,end,count=0;
cout<<"next is the MST :"<<endl;
for (k=0;k<arcNum;k++)	{
         begin=edge[k].from;	end=edge[k].to;	
         int m,n;
        m=Find(parent,begin);	n=Find(parent,end);
        if(m!=n)	{
            cout<<begin<<","<<end<<","<<edge[k].weight<<endl;
            parent[n]=m;	
            count++;
            if(count==vertexNum-1)	break;} }
   return 0;}

2、最短路径

Dijkstra方法(时间复杂度O(n*n))

const int MAX=1000;
void  Dijkstra(MGraph g, int v){
       for ( i =0; i<g.vexnum ; i++){
	 dist[i]=g.arcs[v][i];  
               if ( dist[i]!= MAX) 
                      path [i]=g.vertex[v]+g.vertex[i];
               else
                      path[i]=“”;
       }
       S[0]=g.vertex[v]; 
       num=1;  
While (num<g.vextexNum){
    k=0;
    for(i=0;i<G.vertexNum;i++)
           if((dist[i]<dist[k])   k=i
    cout<<dist[k]<<path[k];
    s[num++]=G.vertex[k];                
    for(i=0;i<G.vertexNum;i++)
             if(dist[k]+g.arc[k][i]<dist[i] {
		 dist[i]=dist[k]+g.arc[k][i];
                       path[i]=path[k]+g.vertex[i];
               }}}

Floyed方法(时间复杂度O(n*n*n))

void Floyd(MGraph G)	
{
    for (i=0; i<G.vertexNum; i++)        
       for (j=0; j<G.vertexNum; j++)
       {
          dist[i][j]=G.arc[i][j];
          if (dist[i][j]!=∞) 
               path[i][j]=G.vertex[i]+G.vertex[j];
          else path[i][j]=""; 
       }
     for (k=0; k<G.vertexNum; k++)         
        for (i=0; i<G.vertexNum; i++)       
           for (j=0; j<G.vertexNum; j++)
               if (dist[i][k]+dist[k][j]<dist[i][j]) {
                    dist[i][j]=dist[i][k]+dist[k][j];
                    path[i][j]=path[i][k]+path[k][j]; }}

3、AOV网

特点:

  1. AOV网中的弧表示活动之间存在的某种制约关系
  2. AOV网中不能出现回路

PS:拓扑序列使得AOV网中所有应存在的前驱和后继关系都能得到满足。

拓扑排序:

  1. 从AOV网中选择一个没有前驱的顶点并且输出;
  2. 从AOV网中删去该顶点,并且删去所有以该顶点为尾的弧;
  3. 重复上述两步,直到全部顶点都被输出,或AOV网中不存在没有前驱的顶点。
void TOpSort(){
int  top=-1, count=0;
for(int i=0;i<vertexnum;i++)
     if(adjlist[i].in==0) s[++top]=i;
while(top!=-1){
    j=s[top--]; cout <<adjlist[j].vertext;   count++;
    p=adjlist[j].firstedge;
    while(p!=NULL){
          k=p->adjvex; adjlist[k].in--;
         if(adjlist[k].in==0) s[top++]=k;
         p=p->next;
      } 
}
If (count<vertexNum) cout<<“有回路”;}

4、AOE网

性质:

  1. 只有在某顶点所代表的事件发生后,从该顶点出发的各活动才能开始;
  2. 只有在进入某顶点的各活动都结束,该顶点所代表的事件才能发生。

关键路径:

  1. 事件的最早发生时间ve[k]
  2. 事件的最迟发生时间vl[k]
  3. 活动的最早开始时间e[i]
  4. 活动的最晚开始时间l[i]

ve[k]的计算

q.push(0);//源点事件入队
	for(j=0;j<vertexnum;j++)	{  //初始化每个事件最早发生时间
		ve[j]=0;	visit[j]=0;	}
	visit[0]=1;	
     while(!q.empty())	{		
		i=q.front();       //利用标准模板库中的队列实现
		q.pop();
		for(j=0;j<vertexnum;j++){//计算i的邻接点的ve
			if(adjlist[i][j]!=9999 && ve[i]+adjlist[i][j]>ve[j] ){
				ve[j]=ve[i]+adjlist[i][j];
				if(!visit[j])   //如果j没有被访问过,顶点j入队
					q.push(j);
				visit[j]=1;
			}
		}
	}

vl[k]的计算

q.push(vertexnum-1);
	for(j=0;j<vertexnum;j++)	{
		vl[j]=ve[vertexnum-1];	visit[j]=0;	}
    while(!q.empty())	{
		i=q.front();
		q.pop();
		for(j=0;j<vertexnum;j++)	{
			if(adjlist[j][i]!=9999 && vl[i]-adjlist[j][i]<vl[j] ){
				vl[j]=vl[i]-adjlist[j][i];
				if(!visit[j])
					q.push(j);
				visit[j]=1;
			}
		}
	}

活动最早开始时间e[i]

for(i=0;i<e;i++)
{
	edge[i].e=ve[edge[i].from];
}

活动最晚开始时间l[i]

for(i=0;i<e;i++)
{
	edge[i].e=ve[edge[i].from];
	edge[i].l=vl[edge[i].to]-adjlist[edge[i].from][edge[i].to];
        if(edge[i].e==edge[i].l)
		cout<<edge[i].from<<"  "<<edge[i].to<<endl;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值