克鲁斯卡尔算法+快速排序算法(最小生成树 2)

【克鲁斯卡尔算法描述】设无向网络N=(v(n),E(n)),待求得最小生成树为T=(V(T),E(T))。

1.初始化:后继数组parent(N)全都置为零(目的是用于算法中判断节点间是否形成回路)

2.从E(N)中选取一条权值最小的边(v,u),快速排序后此时应为E(1),假若当其加入E(T)后使得T不构成回路,即先找到v,u各自的后继,如果不相等,则将(v,u)并入E(T),同时更新网络中顶点的后继,否则舍掉该边,将决策过的(v,u)从E(N)中删掉。

3.重复步骤2(即循环遍历E(N)),直到网络中任意两节点是相通的,此时E(T)中正好有N-1条边。

#include<stdio.h>
#define MAXVER 50
#define MAXEDGE 200
typedef struct edgeNode
{
    int begin;        // 起点
    int weight;     // 权值
    int end;        // 末点
} edgeNode;
//快速排序
int Partition(edgeNode E[],int low,int high)
{
	edgeNode u=E[low];//指定参考值u大小
	while(low<high)
	{
                //从后往前搜比u小的元素,找到后跳出循环
                 while(low<high&&E[high].weight>=u.weight)
		{
			high--;
		}
		if(low<high)//并填充E[low],同时low向后移动
		{
			E[low]=E[high];
			low++;
		}
                

                 //从前往后搜比u大的元素,找到后跳出循环
                while(low<high&&E[low].weight<u.weight)
		{
			low++;
		}
		if(low<high)//并填充到E[high],同时high向前移动
		{
			E[high]=E[low];
			high--;
		}
	}
	E[low]=u;//保存分界点,当low和high相等时,此时u为分界点,u左边是比其小的元素,右边是比起大的元素
	//返回分界点u的位置low
        return low;
}
void QuickSort(edgeNode E[],int low,int high)
{
	int i;
	if(low<high)//停止排序的条件依旧是找到了分界点位置,即low和high相等
	{
		i=Partition(E,low,high);
		QuickSort(E,low,i-1);//分治的思想进行各自的排序
		QuickSort(E,i+1,high);
	}
}
void CreatGraph(edgeNode E[],int &vexs,int &edges)//创建无向网络
{

	printf("please input vertexs and edges:\n");
	scanf("%d %d",&vexs,&edges);
	setbuf(stdin,NULL);
	for(int i=1;i<=edges;i++)
	{
		printf("please input NO.%d begin,end and weight:\n",i);
		scanf("%d %d %d",&E[i].begin,&E[i].end,&E[i].weight);
		setbuf(stdin,NULL);
	}
	printf("\n");
}
int Find(int *parent, int f)//用于找到顶点的后继
{
	while (parent[f] > 0)
        f = parent[f];
        return f;
}
void MiniSpanTree_Kruskal(edgeNode E[],int vernum,int edgenum)
{
    int i = 1, n = 0, m = 0;
    int parent[MAXVER];//作用仅仅是判断两节点是否回路
    for ( ; i < vernum; ++i)//初始化后继
		parent[i] = 0;
    for (i = 1; i <=edgenum; ++i)//遍历所有的边,找到权重和最小的边
    {
	n = Find(parent, E[i].begin);//通过节点的后继判断是否形成回路,同时剔除已形成回路的边
        m = Find(parent, E[i].end);
        if (n != m)//如果各自后继不相等,表明该两节点不联通,
        {
	    parent[n] = m;//更新网络中节点的后继
            printf("%d,%d,%d\n",E[i].begin,E[i].end,E[i].weight);
	}

     }
}

   
int main()
{
    edgeNode E[MAXEDGE];
    int vernum,edgenum;
    CreatGraph(E,vernum,edgenum);//创建无向网络
    QuickSort(E,1,edgenum);//快速排序所有的边
    MiniSpanTree_Kruskal(E,vernum,edgenum);
    return 0;
}

 


【小结】

1.克鲁斯卡尔算法的运算量取决于无向网络的边数,时间复杂度为O(edgenum),因此它适用于稀疏网求最小生成树

2.快速排序算法的时间复杂度为O(nlog2n),空间复杂度取决于递归深度



 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值