算法分析作业一

1.问题

在一给定的无向图G = (V,E) 中,(u,v) 代表连接顶点u与顶点v的边,w(u, v) 代表此边的权,若存在 T 为 E 的子集且为无循环图,使得的 w(T) 最小,则此 T 为 G 的最小生成树。

2.解析

1).输入:一个加权连通图,其中顶点集合为V,边集合为E;
2).初始化:Vnew = {x},其中x为集合V中的任一节点(起始点),Enew = {},为空;
3).重复下列操作,直到Vnew = V:
在集合E中选取权值最小的边 <u, v>,其中u为集合Vnew中的元素,而v不在Vnew集合当中,并且v∈V(如果存在有多条满足前述条件即具有相同权值的边,则可任意选取其中之一);
将v加入集合Vnew中,将 <u, v> 边加入集合Enew中;
4).输出:使用集合Vnew和Enew来描述所得到的最小生成树。

3.设计

#define NUM 20  //数组容量
#define INFINITY 65535  //象征无穷大
#define VRType int      //权值类型
#define VertexType int  //顶点类型
//存储数组
typedef struct {
    VRType arcs[NUM][NUM];  //邻接矩阵map存储连通图,map[u][v]表示顶点u到v的权值
    VertexType vexnum,arcnum;  //记录图的顶点数和边数
}MGraph;
typedef struct {
    VertexType adjvex;//记录权值最小的边的起始点
    VRType lowcost;//记录该边的权值
}closedge[NUM];
//在辅助数组中找出权值最小的边的数组下标,就可以间接找到此边的终点顶点。
closedge dist;//创建一个全局数组,因为每个函数中都会使用到
mindist(MGraph G,closedge dist);
//start结点为初始结点
void Prim(MGraph G,VertexType start)
{
    
    for(循环n次){
    //遍历除start以外的结点,来记录与start相关的权值,没有和start连线的权值为无穷大
    }
    //由于起始点已经归为最小生成树,所以dist数组对应位置的权值为0,这样,遍历时就不会被选中
    dist[start].lowcost=0;
	for(循环n-1)
	{
		//在dist数组找出权值最小的边,并记录下标pos
        int pos=mindist(G,dist);
        //归入最小生成树的顶点的dist数组中的权值设为0
        dist[pos].locost=0;
		//由于此时树中新加入了一个顶点,需要判断,由此顶点出发,到达其它各顶点的权值是否比之前记录的权值还要小,如果还小,则更新
        for(int i=1;i<=n;i++){
        	//由于之前归入最小生成树的顶点的dist数组中的权值设为0
        	//设初始点为1,且1、2已为生成树内的点,3为新加入的点的话,1-2权值为0,1-3的权值为0
        	//i=1时,dist[1]为0<G.arcs[3][1]
        	//i=2时,dist[2]为1-2权值为0,G.arcs[3][2]为3-2权值>0,因此不会出现闭环情况
            if(dist[i].lowcost>G.arcs[pos][i]){
            	dist[i].lowcost=G.arcs[pos][i];
            }
        }
    }
}

4.源码

https://github.com/8455580/homework/blob/main/1/Prim.c

1.问题

在一给定的无向图G = (V,E) 中,(u,v) 代表连接顶点u与顶点v的边,w(u, v) 代表此边的权,若存在 T 为 E 的子集且为无循环图,使得的 w(T) 最小,则此 T 为 G 的最小生成树

2.解析

记Graph中有v个顶点、e个边

新建图Graphnew,Graphnew中拥有原图中同样的e个顶点,但没有边

将原图Graph中全部e个边按权值从小到大排序

循环:从权值最小的边開始遍历每条边 直至图Graph中全部的节点都在同一个连通分量中

如果这条边连接的两个节点于图Graphnew中不在同一个连通分量中
增加这条边到图Graphnew中

3.设计

#include <stdio.h>
#include <stdlib.h>
#define NUM 20 //最大容量 
#define VertexType int
typedef struct edge{
    VertexType adjvex; //起始点 
    VertexType end;		//终点 
    VertexType arcs;  //权值 
} edge[NUM];
//定义辅助数组
typedef struct {
    VertexType value;//顶点数据
    int sign;//每个顶点所属的集合
}Dist[NUM];
Dist dist;
int main(){
    int arcnum,vexnum,i,j;
    edge edges;
    //创建连通图
    CreateUDN(&edges,&vexnum,&arcnum);
    //对连通网中的所有边进行升序排序,结果仍保存在edges数组中
    //创建一个空的结构体数组,用于存放最小生成树
    edge minTree;
    //设置一个用于记录最小生成树中边的数量的常量
    int num=0;
    //遍历所有的边
    for (i=0; i<arcnum; i++) {
        int initial= edges[i].adjvex;
        int end= edges[i].end;
        //如果顶点位置存在且顶点的标记不同,说明不在一个集合中,不会产生回路
        if (initial!=-1&& end!=-1&&dist[initial].sign!=dist[end].sign) {
            //记录该边,作为最小生成树的组成部分
            minTree[num]=edges[i];
            //计数+1
            num++;
            //将新加入生成树的顶点标记全部更改为一样的
            //如果选择的边的数量和顶点数相差1,证明最小生成树已经形成,退出循环
        }
    }
    //输出语句
    return 0;
}

4.源码

https://github.com/8455580/homework/blob/main/1/Kruskal.c

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值