克鲁斯卡尔算法求最小生成树

目录1.需求分析 (2)1.1 设计题目 (2)1.2 设计任务及要求 (2)1.3课程设计思想 (2)1.4 程序运行流程 (2)1.5软硬件运行环境及开发工具 (2)2.概要设计 (2)2.1流程图 (2)2.2抽象数据类型MFSet的定义 (3)2.3主程序 (4)2.4抽象数据类型图的定义 (4)2.5抽象数据类型树的定义 (5)3.详细设计 (7)3.1程序 (7)4.调试与操作说明 (10)4.1测试结果 (10)4.2调试分析 (11)5.课程设计总结与体会 (11)5.1总结 (11)5.2体会 (11)6. 致谢 (12)7. 参考文献 (12)1.需求分析1.1 设计题目:最小生成树1.2 设计任务及要求:任意创建一个图,利用克鲁斯卡尔算法,求出该图的最小生成树。

1.3 课程设计思想:Kruskal算法采用了最短边策略(设G=(V,E)是一个无向连通网,令T=(U,TE)是G的最小生成树。

最短边策略从TE={}开始,每一次贪心选择都是在边集E中选择最短边(u,v),如果边(u,v)加入集合TE中不产生回路,则将边(u,v)加入边集TE中,并将它在集合E中删去。

),它使生成树以一种任意的方式生长,先让森林中的树木随意生长,每生长一次就将两棵树合并,最后合并成一棵树。

1.4程序运行流程:1)提示输入顶点数目;2)接受输入,按照项目要求产生边权值的随机矩阵;然后求解最小生成树;3)输出最小生成树并且退出;1.5 软硬件运行环境及开发工具:VC2.概要设计2.1流程图图1流程图2.2抽象数据类型MFSet的定义:ADT MFSet {数据对象:若设S是MFSet型的集合,则它由n(n>0)个子集Si(i = 1,2...,n)构成,每个子集的成员代表在这个子集中的城市。

数据关系:S1 U S2 U S3 U... U Sn = S, Si包含于S(i = 1,2,...n)Init (n): 初始化集合,构造n个集合,每个集合都是单成员,根是其本身。

rank 数组初始化0Find(x):查找x所在集合的代表元素。

即查找根,确定x所在的集合,并路径压缩。

Merge(x, y):检查x与y是否在同一个集合,如果在同一个集合则返回假,否则按秩合并这两个集合并返回真。

}2.3主程序:int main(){初始化;while (条件){接受命令;处理命令;}return 0;}2.4抽象数据类型图的定义如下:ADT Graph{数据对象V:V是具有相同特性的数据元素的集合,成为顶点集。

数据关系R:R={VR} VR={<v,w>|v,w∈V且P(v,w),<v,w>表示从v 到w的弧,谓词P(v,w)定义了弧<v,w>的意义或信息}基本操作P:CreateGraph(&G,V,VR);初始条件:V是图的顶点集,VR是图中弧的集合。

操作结果:按V和的VR定义构造图G。

DestoryGraph(&G);初始条件:图G存在。

操作结果:销毁图G。

LocateVex(G,u);初始条件:图G存在,u和G中是顶点有相同特征。

操作结果:若G中存在顶点u,则返回该顶点在图中位置;否则返回其他信息。

GetVex(G,v);初始条件:图G存在,v是G中某个顶点。

操作结果:返回v的值。

PutVex(&G,v,value);初始条件:图G存在,v是G中某个顶点。

操作结果:对V赋值value,FirstAdjVex(G,v);初始条件:图G存在,v是G中某个顶点。

操作结果:返回v的第一个邻接顶点。

若顶点在G中没有顶点,则返回“空”。

NextAdjVex(G,v,w);初始条件:图G存在,v是G中某个顶点,w是v的邻接顶点。

操作结果:返回v的(相对于w的)下一个邻接顶点。

若w是v的最后一个邻接顶点,则返回“空”。

InsertVex(&G,v);初始条件:图G存在,v和途中顶点有相同特征。

操作结果:在图G中添加新顶点v。

DeleteVex(&G,v);初始条件:图G存在,v是G中某个顶点。

操作结果:删除G中顶点v及其相关的弧。

InsertArc(&G,v,w);初始条件:图G存在,v和w是G中两个顶点。

操作结果:在G中添加弧<v,w>,若G是无向的,则还增添对称弧<v,w>。

DeleteArc(&G,v,w);初始条件:图G存在,v和w是G中两个顶点。

操作结果:在G中删除弧<v,w>,若G是无向的,则还删除对称弧<v,w>。

DFSTravrese(G,Visit());初始条件:图G存在,Visit是顶点的应用函数。

操作结果:对图进行深度优先遍历。

在遍历过程中对每个顶点调用函数Visit一次且仅一次。

一旦Visit()失败,则操作失败。

BFSTravrese(G,Visit());初始条件:图G存在,Visit是顶点的应用函数。

操作结果:对图进行广度优先遍历。

在遍历过程中对每个顶点调用函数Visit 一次且仅一次。

一旦Visit()失败,则操作失败。

}ADT Graph2.5抽象数据类型树的定义如下:ADT Tree{数据对象D:D是具有相同特性数据元素的集合。

数据关系R:若D为空集,则称为空树;若D仅含一个元素数据,则R为空集,否则R={H},H是如下二元关系:(1)在D中存在唯一的称为根的数据元素root,它在关系H 下无前驱;(2)若D-{root}≠Φ,则存在D-{root}的一个划分D1,D2,…,D m(m>0),对任意j≠k(1≤j,k≤m)有D j∩D k=Φ,且对任意的I(1≤i≤m),惟一存在数据元素x i∈D i有<root,x i>∈H;(3)对应于D-{root}的划分,H-{<root,x1>,…,<roor,x m>}有惟一的一个划分H1,H2,…,H m(m>0),对任意j≠k(1≤j,k≤m)有H j∩H k=Φ,且对任意I(1≤i≤m),H i是D i上的二元关系,(D i,{H i})是一棵符合本定义的树,称为跟root的子树。

基本操作P:InitTree(&T);操作结果:构造空树T。

DestoryTree(&T);初始条件:树T存在。

操作结果:销毁树T。

CreateTree(&T,definition);初始条件:definition给出树T的定义。

操作结果:按definition构造树T。

ClearTree(&T);初始条件:树T存在。

操作结果:将树T清为空树。

TreeEmptey(T);初始条件:树T存在。

操作结果:若T为空树,则返回TRUE,否则FALSE。

TreeDepth(T);初始条件:树T存在。

操作结果:返回T的深度。

Root(T);初始条件:树T存在。

操作结果:返回T的跟。

Value(T,cur_e);初始条件:树T存在,cur_e是T中某个结点。

操作结果:返回cur_e的值。

Assign(T,cur_e,value);初始条件:树T存在,cur_e是T中某个结点。

操作结果:结点cur_e赋值为value。

Parent(T,cur_e);初始条件:树T存在,cur_e是T中某个结点。

操作结果:若cur_e是T的非根结点,则返回它的双亲,否则函数值为“空”。

LeftChild(T,cur_e);初始条件:树T存在,cur_e是T中某个结点。

操作结果:若cur_e是T的非叶子结点,则返回它的最左子,否则返回“空”。

RightSibling(T,cur_e);初始条件:树T存在,,cur_e是T中某个结点。

操作结果:若cur_e有右兄弟,则返回它的右兄弟,否则函数值为“空”。

InsertChild(&T,&p,I,c);初始条件:树T存在,P指向T中某个结点,1≤i≤p所指向的结点度数+1,非空树c与T不相交。

操作结果:插入c为T中p指结点的第i棵子树。

DeleteChild(&T,&p,i);初始条件:树T存在,p指向T中某个结点,1≤i≤p指结点的度。

操作结果:删除T中p所指结点的第i棵子树。

TraverseTree(T,Visit());初始条件:树T存在,Visit是对结点操作的应用函数。

操作结果:按某种次序对T的每个结点调用函数visit()一次且至多一次。

一旦vista()失败,则操作失败。

}ADT Tree3.详细设计3.1程序:如下#include<stdio.h>#include<stdlib.h>#include<string.h>#define MAX_NAME 5#define MAX_VERTEX_NUM 30typedef char Vertex[MAX_NAME];/*顶点名字数组*/typedef int AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];/*邻接矩阵*/typedef struct /*定义图*/{Vertex vexs[MAX_VERTEX_NUM];AdjMatrix arcs;int vexnum,arcnum;}MGraph;int LocateVex(MGraph *G,Vertex u){int i;for(i=0;i<G->vexnum;++i)if(strcmp(G->vexs[i],u)==0)return i;return -1;}void CreateGraph(MGraph *G){int i,j,k,w;Vertex va,vb;printf("请输入无向网G的顶点数和边数(以空格作为间隔): \n");scanf("%d %d",&G->vexnum,&G->arcnum);printf("请输入%d个顶点的名字(小于%d个字符):\n",G->vexnum,MAX_NAME);for(i=0;i<G->vexnum;++i) /*构造顶点集*/scanf("%s",G->vexs[i]);for(i=0;i<G->vexnum;++i) /*初始化邻接矩阵*/for(j=0;j<G->vexnum;++j)G->arcs[i][j]=0x7fffffff;printf("请输入%d条边的顶点1 顶点2 权值(以空格作为间隔):\n",G->arcnum);for(k=0;k<G->arcnum;++k)scanf("%s%s%d%*c",va,vb,&w);i=LocateVex(G,va);j=LocateVex(G,vb);G->arcs[i][j]=G->arcs[j][i]=w; /*对称*/}}void kruskal(MGraph G){FILE *fpt;fpt = fopen("9.txt","w");/*打开文档,写入*/fprintf(fpt,"最小生成树的各条边为:\n");int i,j;int k=0,a=0,b=0,min=G.arcs[a][b],min_out;printf("最小生成树的各条边为:\n");while(k<G.vexnum-1){for(i=0;i<G.vexnum;++i)for(j=i+1;j<G.vexnum;++j)if(G.arcs[i][j]<min){min=G.arcs[i][j];a=i;b=j;}min_out=min;min=G.arcs[a][b]=0x7fffffff;printf("%s-%s-%d\n",G.vexs[a],G.vexs[b],min_out);fprintf(fpt,"%s-%s-%d\n",G.vexs[a],G.vexs[b],min_out);k++;}fclose(fpt);}void main()MGraph g;CreateGraph(&g);kruskal(g);}4. 调试与操作说明4.1测试结果:如下图图2测试结果1图3测试结果24.2调试分析本程序利用克鲁斯卡尔算法求最小生成树数据结构清晰因而调试比较顺利。

合集下载

最小生成树算法

最小生成树算法

最小生成树之克鲁斯卡尔(Kruskal)算法、普里姆(prim)算法分类:算法 2012-01-04 11:091159人阅读评论(0)收藏举报算法问题描述:在一个具有几个顶点的连通图G中,如果存在子图G'包含G中所有顶点和一部分边,且不形成回路,则称G'为图G的生成树,其中代价最小的生成树则称为最小生成树。

例如,设有下图G,找出连接图G所有顶点(v1,v2,v3,v4,v5,v6)的边,且这些边的权重之和最小。

那么如何生成该最小生成树呢?两个经典算法是普里姆 (Prim)算法和克鲁斯卡(Kruskal )算法。

克鲁斯卡尔(Kruskal)算法:克鲁斯卡尔(Kruskal)算法是以图上的边为出发点依据贪心策略逐次选择图中最小边为最小生成树的边,且所选的当前最小边与已有的边不构成回路。

在图G中,首先选择最小的边(V2,V3),(V4,V5),(V2,V4),因为(V4,V6)和(V5,V6)权重相等,所以可以任选其中一条(这也表明最小生成树不是唯一的)。

同样的道理,选择权重为5的边(V3,V5)(V2,V1),因为(V3,V5)和(V2,V3),(V2,V4),(V4,V5)构成了回路,所以舍弃(V3,V5)保留(V2,V1)。

这时该子图G‘已经包含了图G的所有的边,算法结束。

得到的最小生成树如下图:伪代码: Kruskal(G,W)1、按照权重从小到大顺序排序G的边{e1,e2,e3,e4,e5,...,em};2、for i = 1to m do3、如果ei的两个端点不在同一个连通分支,则将ei加到T中;算法特点:时间复杂度为O(eloge)(e为网中边数),适合于求稀疏的网的最小生成树。

普里姆(Prim)算法:普里姆(Prim)算法是以图上的顶点为出发点,逐次选择到最小生成树顶点集距离最短的顶点为最小生成树的顶点,并加入到该顶点集,直到包含所有的顶点。

在图G中,选择顶点V1加入到顶点集S,连接S中顶点的边为(V1,V2)(V1,V3),选择最小的即(V1,V2),并将V2加入到顶点集S。

数据结构最小生成树克鲁斯卡尔算法代码

数据结构最小生成树克鲁斯卡尔算法代码

数据结构最小生成树克鲁斯卡尔算法代码以下是克鲁斯卡尔算法的实现代码:```python# 定义边的类class Edge:def __init__(self, src, dest, weight):self.src = srcself.dest = destself.weight = weight# 定义图的类class Graph:def __init__(self, vertices):self.V = verticesself.edges = []def add_edge(self, src, dest, weight):edge = Edge(src, dest, weight)self.edges.append(edge)# 查找顶点的根节点def find(self, parent, i):if parent[i] == i:return ireturn self.find(parent, parent[i])# 合并两个集合def union(self, parent, rank, x, y):xroot = self.find(parent, x)yroot = self.find(parent, y)if rank[xroot] < rank[yroot]:parent[xroot] = yrootelif rank[xroot] > rank[yroot]:parent[yroot] = xrootelse:parent[yroot] = xrootrank[xroot] += 1# 使用克鲁斯卡尔算法计算最小生成树def kruskal(self):result = []i = 0e = 0 # 已选择的边的数量# 按权重对边进行排序self.edges = sorted(self.edges, key=lambda x:x.weight)parent = []rank = []# 初始化每个顶点的父节点和秩for node in range(self.V):parent.append(node)rank.append(0)while e < self.V - 1:# 选择权重最小的边edge = self.edges[i]i += 1x = self.find(parent, edge.src)y = self.find(parent, edge.dest) # 判断是否形成环路if x != y:e += 1result.append(edge)self.union(parent, rank, x, y) return result# 测试代码g = Graph(4)g.add_edge(0, 1, 10)g.add_edge(0, 2, 6)g.add_edge(0, 3, 5)g.add_edge(1, 3, 15)g.add_edge(2, 3, 4)result = g.kruskal()for edge in result:print(f"{edge.src} -- {edge.dest} == {edge.weight}")```这段代码实现了克鲁斯卡尔算法,其中`Graph`类表示图,`Edge`类表示边。

最小生成树克鲁斯卡尔算法详解

最小生成树克鲁斯卡尔算法详解

最小生成树克鲁斯卡尔算法详解转载自:数据结构中图结构的最小生成树克鲁斯卡尔算法详解我一直想把克鲁斯卡尔算法实现,但是由于马上就要考试了,而且自己由于天气寒冷等各种原因没能如愿。

不过在昨天一天的努力中,我终于完成了克鲁斯卡尔算法的实现。

算法是c++的,图的数据结构是以邻接矩阵为基础,并且使用了模板,所以可以对任何类型的顶点进行最小生成树的生成。

克鲁斯卡尔算法中的核心思想就是逐个在边的集合中找到最小的边,如果满足条件就将其构造,最后生成一个最小生成树。

它首先是一系列的顶点集合,并没有边,然后我们从邻接矩阵中寻找最小的边,看看它是否和现有的边连接成一个环,如果连接成环,则舍弃,另外取其它的边。

如果不连接成环,则接受这个边,并把其纳入集合中。

以此类推。

我们知道,一课有n个顶点的树(无论是树还是二叉树),它必定有n-1个边。

我们只需要对上述操作循环至少n-1次(因为可能选出的边会构成环,不是我们需要的边)。

下面就是我寻找最小边的c++代码:Code:min=INFINITY;for(i=0;i vexnum;i++){for(j=i;j vexnum;j++){if(arcs[i][j].adj!=INFINITY&&minarcs[i][j].adj){if(arcs[i][j].adj=vexSet.lowcost&&!vexSet.IsAlreadyIn(i,j)){min=arcs[i][j].adj;track_i=i;track_j=j;}}}}首先让min为最大(INFINITY),然后让其与邻接矩阵的一个个元素进行比较,我在遍历邻接矩阵的时候使用的是上三角(◥)法,因为无向网的邻接矩阵是对称矩阵。

当然我们必须记录满足调件的顶点的下标,所以track_i、track_j就变得必要了。

又因为我们要满足每次选取的最小权值的边呈递增数列,所以arcs[i][j].adj vexSet.lowcost(其中vexSet.lowcost为上次保存的最小边)就变得必要了。

2.kruskal算法求解最小生成树算法

2.kruskal算法求解最小生成树算法

Kruskal算法是一种用于求解最小生成树的算法,它的主要特点是按边的权值大小进行排序,并逐步添加边,直到构成一棵生成树为止。

在实际应用中,Kruskal算法通常被用来解决各种最小生成树的问题,比如公路修建、通信网络的建设、电路板的设计等等。

本文将着重介绍Kruskal算法的原理、步骤和具体应用,以期为读者提供全面的了解和指导。

一、Kruskal算法的原理Kruskal算法是一种基于贪心策略的算法,它通过不断地选择边来构建生成树,直到所有的顶点都被包含在生成树中。

其基本原理可以概括如下:1. 将图中的所有边按权值大小进行排序。

2. 依次从小到大选择边,并检查是否形成环路。

3. 如果没有形成环路,则将该边添加到生成树中。

Kruskal算法的核心思想是“先小后大”,即先选择权值较小的边,直到所有的顶点都被包含在生成树中。

由于Kruskal算法是基于边来构建生成树的,因此它适用于稀疏图和稠密图,而且在实际应用中通常具有较好的效率。

二、Kruskal算法的步骤Kruskal算法的具体步骤可以简单总结为以下几个步骤:1. 初始化:将图中的所有边按权值大小进行排序。

2. 创建一个空的数组T来存储最小生成树的边。

3. 依次从排序后的边集合中选择边e,并检查是否添加e会形成环路。

4. 如果不形成环路,则将边e添加到数组T中。

5. 直到T中包含了n-1条边为止,其中n为顶点的个数。

三、Kruskal算法的具体实现下面我们通过一个简单的示例来说明Kruskal算法的具体实现步骤。

示例:假设有如下的图G和边集合E:顶点集合V:{A, B, C, D, E, F, G, H}边集合E:{(A, B, 4), (A, H, 8), (B, C, 8), (B, H, 11), (C, D, 7), (C, F, 4), (C, I, 2), (D, E, 9), (D, F, 14), (E, F, 10), (F, G, 2), (G, H, 1), (G, I, 6), (H, I, 7)}我们可以按照如下的步骤来求解最小生成树:1. 首先对边集合E进行按权值的排序:(E, F, 2), (G, H, 1), (C, I, 2), (A, B, 4), (C, F, 4), (H, I, 7), (C, D, 7), (D, E, 9), (A, H, 8), (B, C, 8), (G, I, 6), (B, H, 11), (D, F, 14)2. 初始化一个空的数组T来存储最小生成树的边,初始化一个数组parent来记录每个顶点的父节点。

c语言最小生成树kruskal算法

c语言最小生成树kruskal算法

c语言最小生成树kruskal算法Kruskal算法是一种用于解决最小生成树问题的贪心算法。

它的核心思想是通过不断添加边来构建最小生成树,直到所有的顶点都被连接在一起。

本文将介绍Kruskal算法的基本原理、实现步骤以及其在实际应用中的一些注意事项。

一、基本原理最小生成树是一个无向图的生成树中边的权值和最小的生成树。

Kruskal算法是一种基于边的贪心算法,它的主要思想是按照边的权值从小到大的顺序选择边,并且每次选择的边不能构成环,直到所有的顶点都被连接在一起。

二、实现步骤1. 将图的所有边按照权值从小到大排序;2. 依次选择权值最小的边,如果这条边的两个顶点不在同一棵生成树中,则将这条边添加到最小生成树中,并将这两个顶点合并为一棵生成树;3. 重复步骤2,直到所有的顶点都被连接在一起。

三、注意事项1. 在实现Kruskal算法时,需要使用并查集数据结构来判断两个顶点是否在同一棵生成树中。

并查集是一种用于处理不相交集合的数据结构,它支持合并和查询两个集合的操作,可以有效地判断两个顶点是否在同一棵生成树中。

2. 在选择边的过程中,需要注意避免选择会导致环形成的边,否则会破坏生成树的结构。

3. Kruskal算法可以应用于带权无向图,但是对于带权有向图,则需要使用其他算法来解决最小生成树的问题。

4. Kruskal算法的时间复杂度为O(ElogE),其中E为图的边数。

这是因为在算法的过程中需要对边进行排序,并且需要进行并查集的操作。

四、应用场景Kruskal算法在实际应用中有着广泛的应用场景,例如:1. 网络布线规划:在进行网络布线规划时,可以使用Kruskal算法来确定最优布线方案,以减少总线的长度和成本。

2. 铁路规划:在进行铁路线路规划时,可以使用Kruskal算法来确定最优的铁路线路,以减少运输成本和时间。

3. 电力传输:在进行电力传输规划时,可以使用Kruskal算法来确定最优的输电线路,以减少能量损耗和成本。

数据结构最小生成树克鲁斯卡尔算法的实现资料

数据结构最小生成树克鲁斯卡尔算法的实现资料

摘要设计了一个用C/C++编写程序实现克鲁斯卡尔最小生成树算法,该程序操作简单,界面清晰,易于为用户所接受。

关键词:克鲁斯卡尔,邻接矩阵,最小生成树,vc++。

目录1 课题描述 (1)2 问题分析和任务定义 (2)3 逻辑设计 (3)4 详细设计 (4)5 程序编码 (11)6 程序调试与测试 (17)7 结果分析 (19)8 总结 (20)参考文献 (21)1课题描述用C/C++编写程序实现克鲁斯卡尔最小生成树算法。

假设要在n 个城市之间建立通讯联络网,则连通n个城市只需要n-1条线路。

这是我们设计一个最小生成树的程序用来算出最节省经费的前提下建立这个通信站。

2问题分析和任务定义假设连通网N=(V,{E}),则令最小生成树的初始状态为只有n 个顶点而无边的非连通图T=(V,{}),图中每个顶点自成一个连通分量。

在E中选择代价最小的边,若该边依附的顶点落在T中不同的连通分量上,则将此边加入到T中,否则舍去此边而选择下一条代价最小的边。

依次类推,直到T中所有顶点都在同一连通分量上为止。

设计思想:采用邻接矩阵来存储图,然后采用克鲁斯卡尔算法求出最小生成树。

1).定义结构体。

2).采用邻接矩阵做存储结构创建图(函数模块一)。

3).采用克鲁斯卡尔算法求出该图的最小生成树(函数模块二)。

4).在主函数里面分别调用以上各个函数,最终实现设计目的。

4.1.程序结构·函数CreateMGraph用来实现图的创建,以及图的相关信息的存储。

图的存储采用邻接矩阵存储结构。

·函数minitree_KRUSKAL用来求图的最小生成树。

图的最小生成树有普利姆算法和克鲁斯卡尔算法可以实现,本段代码使用的是克鲁斯卡尔算法,这也是本题所要求使用的。

·各个函数间的联系先调用函数CreateMGraph实现图的创建,然后调用函数minitree_KRUSKAL求出该图的最小生成树4.2.设计说明·在开始的时候添加一些限制条件方便函数的功能实现例如:#define MaxVertexNum 100 //最大顶点个数#define QueueSize 30#define M 30·模块一:图的创建·结构体定义为:typedef struct{VertexType vexs[MaxVertexNum]; //顶点表Link edges[MaxVertexNum][MaxVertexNum]; //图中当前的相连接的两个顶点int n,e; //图中当前的顶点数和边数}MGraph;·函数定义为:MGraph CreateMGraph(){MGraph G;int i,j,k,ch3;char ch1,ch2;printf("请输入该图的顶点数和边数:\n");scanf("%d,%d",&(G.n),&(G.e));printf("请输入该图的顶点信息:\n");for(i=1;i<=G.n;i++){getchar();scanf("%c",&(G.vexs[i]));}for(i=1;i<=G.n;i++)for(j=1;j<=G.n;j++)G.edges[i][j].w=0;printf("请输入该图每条边对应的两个顶点的名称:\n");for(k=1;k<=G.e;k++){scanf("%c",&ch1);printf("请输入第%d条边的顶点序号:",k);scanf("%c %c",&ch1,&ch2);printf("请输入第%d条边的权值大小:",k);scanf("%d",&ch3);for(i=1;ch1!=G.vexs[i];i++);for(j=1;ch2!=G.vexs[j];j++);e[p].vexh=i;e[p].vext=j;e[p].weight=G.edges[i][j].w=ch3; //权值e[p].flag=0;p++;}return G;}流程如图4.1所示创建图使用的是函数MGraph CreateMGraph(),该图的存储结构是邻接矩阵,先对图的结构体进行定义,再进行初始化。

kruskal算法求最小生成树

数据结构课程设计Kruskal算法求最小生成树学院:班级:学号;姓名;指导老师;完成日期:目录(一)需求分析———————————(二)概要设计———————————(三)详细设计———————————(四)主函数设计—————————(五)经验体会——————————- (六)源代码及调试分析————————1、需求分析运用kruskal算法求最小生成树最短路径:①输入任意源点,求到其余顶点的最短路径。

②输入任意对顶点,求这两点之间的最短路径和所有路径。

2、概要设计首先要确定图的存储形式。

经过的题目要求的初步分析,发现该题的主要操作是路径的输出,因此采用数组(邻接矩阵)的方法构造无向图,比较方便以后的编程。

从而求得最小生成树。

3、函数详细设计(1)构造无向图本题中为了能够求得最小生成树,先要构造无向图,并且用领结矩阵的形式表现出来。

void Create(MGraph &G) //采用数组(邻接矩阵)表示法,构造无向图G。

{int i,j,k,w;char v1[10],v2[10];scanf("%d%d",&G.vexnum,&G.arcnum); //输入定点数和边数for(i=0; i<G.vexnum; i++)scanf("%s", G.vexs[i]);for(i=0; i<G.vexnum; i++) //初始化邻接矩阵{for(j=0; j<G.vexnum; j++)G.arcs[i][j] = INF;}for(k=0; k<G.arcnum; k++) //构造邻接矩阵{scanf("%s%s%d",v1,v2,&w); //输入一条边依附的顶点及权值i = Locate(G,v1); //确定v1在G中的位置j = Locate(G,v2); //确定v2在G中的位置G.arcs[i][j] = w; //弧<v1,v2>的权值G.arcs[j][i] = w; //弧<v2,v1>是权值}for(i=0; i<G.vexnum; i++){for(j=0; j<G.vexnum; j++){printf("%6d ",G.arcs[i][j]);}printf("\n");}}(2) kruskal算法。

最小生成树的方法

最小生成树的方法
最小生成树(Minimum Spanning Tree)是指在一个带权无向连通图中,找到一个包含所有顶点且总权值最小的树。

常用的方法有以下几种:
1. Prim算法(普里姆算法):从一个起始顶点开始,逐步扩展生成树,每次选择一个与当前生成树距离最小的顶点加入,直到所有顶点都被包含在生成树中。

2. Kruskal算法(克鲁斯卡尔算法):首先将图的所有边按照权值从小到大排序,然后依次选择权值最小的边加入生成树中,但要保证加入边后不会形成环,直到生成树中包含所有顶点,或者图中的所有边都被考虑过。

3. Boruvka算法(博鲁卡尔算法):将图的所有顶点分成多个不相交的集合,每个集合中的顶点组成一棵生成树,然后每次选择具有最小权值且连接两个不同集合的边加入生成树中,直到只剩下一个集合。

4. Jarnik算法(加尔尼克算法):也称为更改版的Prim算法,首先选择一个起始顶点加入生成树中,然后通过比较当前生成树中的顶点到其他顶点的距离,选择一个距离最小的顶点加入生成树,重复该过程直到所有顶点都被包含在生成树中。

这些方法都可以得到最小生成树,但在某些情况下,它们的效率和性能可能会不同。

选择合适的方法取决于具体的应用场景和图的特征。

克鲁斯卡尔(Kruskal)算法求无向网的最小生成树数据结构报告

数据结构上机报告(1) 姓名:张可心学号:14030188030 班级:1403018一、题目描述用克鲁斯卡尔(Kruskal)算法求无向网的最小生成树,分析你的算法的时空复杂度,必须有过程说明。

输入:输入数据第一行为两个正整数n和m,分别表示顶点数和边数。

后面紧跟m行数据,每行数据是一条边的信息,包括三个数字,分别表示该边的两个顶点和边上的权值。

输出:按顺序输出Kruskal算法求得的最小生成树的边集,每行一条边,包括三个数字,分别是该边的两个顶点和边上的权值,其中第一个顶点的编号应小于第二个顶点的编号。

示例输入8 111 2 31 4 51 6 182 4 72 5 63 5 103 8 204 6 154 7 115 7 85 8 12示例输出1 2 31 4 52 5 65 7 83 5 105 8 124 6 15二、解题思路(1)假定每对顶点表示图的一条边,每条边对应一个权值;(2)输入每条边的顶点和权值;(3)输入每条边后,计算出最小生成树;(4)打印最小生成树边的顶点及权值。

三、源代码#include<stdio.h>#include<stdlib.h>typedef struct {int a,b,value;}node;int stcmp(const void *p,const void *q){node *a=(node *)p;node *b=(node *)q;if(a->value>b->value){return 1;}else if(a->value==b->value){return 0;}else{return -1;}}int root(int a,int *b){for(;a!=b[a];a=b[a]);return a;}bool isgroup(int a,int b,int *c){if(root(a,c)==root(b,c))return true;return false;}void add(int a,int tob,int *c){c[root(a,c)]=root(tob,c);}int main (){int n,m;scanf("%d %d",&n,&m);node no[m];for(int u=0;u<m;u++){scanf("%d",&(no[u].a));scanf("%d",&(no[u].b));scanf("%d",&(no[u].value));}qsort(no,m,sizeof(no[0]),stcmp);int bcj[n+1];for(int u=1;u<=n;u++){bcj[u]=u;}int i=0;int cc=n;for(;i<m;i++){if(!isgroup(no[i].a,no[i].b,bcj)){add(no[i].a,no[i].b,bcj);cc--;printf("%d %d %d\n",no[i].a,no[i].b,no[i].value);}if(cc==1)break;}return 0;}四、运行结果。

数学建模-最小生成树-kruskal算法及各种代码

kruskal算法及代码之五兆芳芳创作---含伪代码、c代码、matlab、pascal等代码K r u s k a l算法每次选择n- 1条边,所使用的贪婪准则是:从剩下的边中选择一条不会产生环路的具有最小花费的边参加已选择的边的荟萃中.注意到所选取的边若产生环路则不成能形成一棵生成树.K r u s k a l算法分e 步,其中e 是网络中边的数目.按花费递增的顺序来考虑这e 条边,每次考虑一条边.当考虑某条边时,若将其参加到已选边的荟萃中会出现环路,则将其抛弃,不然,将它选入.目录Kruskal算法1.算法定义举例描述Kruskal算法的代码实现1.伪代码C代码实现matlab代码实现pascal代码实现Kruskal算法1.算法定义举例描述Kruskal算法的代码实现1.伪代码C代码实现matlab代码实现pascal代码实现算法定义克鲁斯卡尔算法假定WN=(V,{E}) 是一个含有n 个顶点的连通网,则依照克鲁斯卡尔算法机关最小生成树的进程为:先机关一个只含n 个顶点,而边集为空的子图,若将该子图中各个顶点看成是各棵树上的根结点,则它是一个含有n 棵树的一个森林.之后,从网的边集E 中选取一条权值最小的边,若该条边的两个顶点分属不合的树,则将其参加子图,也就是说,将这两个顶点辨别所在的两棵树分解一棵树;反之,若该条边的两个顶点已落在同一棵树上,则不成取,而应该取下一条权值最小的边再试之.依次类推,直至森林中只有一棵树,也即子图中含有n-1条边为止.举例描述克鲁斯卡尔算法(Kruskal's algorithm)是两个经典的最小生成树算法的较为复杂理解的一个.这里面充分体现了贪心算法的精髓.大致的流程可以用一个图来暗示.这里的图的选择借用了Wikipedia上的那个.很是清晰且直不雅.首先第一步,我们有一张图,有若干点和边如下图所示:第一步我们要做的事情就是将所有的边的长度排序,用排序的结果作为我们选择边的依据.这里再次体现了贪心算法的思想.资源排序,对局部最优的资源进行选择.排序完成后,我们率先选择了边AD.这样我们的图就酿成了第二步,在剩下的变中寻找.我们找到了CE.这里边的权重也是5依次类推我们找到了6,7,7.完成之后,图酿成了这个样子..下一步就是关头了.下面选择那条边呢?BC或EF吗?都不是,尽管现在长度为8的边是最小的未选择的边.但是现在他们已经连通了(对于BC可以通过CE,EB来连接,类似的EF可以通过EB,BA,AD,DF来接连).所以我们不需要选择他们.类似的BD也已经连通了(这里上图的连通线用白色暗示了).最后就剩下EG和FG了.当然我们选择了EG.最后成功的图就是下图:.到这里所有的边点都已经连通了,一个最小生成树构建完成.编辑本段Kruskal算法的代码实现伪代码MST-KRUSKAL(G,w)C代码实现Copyright (c) 2002,2006 by ctu_85All Rights Reserved.*//* I am sorry to say that the situation of unconnected graph is not concerned */#include "stdio.h"#define maxver 10#define maxright 100int G[maxver][maxver],record=0,touched[maxver][maxver]; int circle=0;intFindCircle(int,int,int,int);int main(){int path[maxver][2],used[maxver][maxver];inti,j,k,t,min=maxright,exsit=0;int v1,v2,num,temp,status=0;restart:printf("Please enter the number of vertex(s) in the graph:\n"); scanf("%d",&num);if(num>maxver||num<0){printf("Error!Pleasereinput!\n");goto restart;}for(j=0;j<num;j++)for(k=0;k<num;k++){if(j==k)G[j][k]=maxright;used[j][k]=1;touched[j][k]=0;}elseif(j<k){re:printf("Please input the right between vertex %d and vertex %d,if no edge exists please input -1:\n",j+1,k+1);scanf("%d",&temp);if(temp>=maxright||temp<-1){printf("Invalid input!\n");goto re;}if(temp==-1)temp=maxright;G[j][k]=G[k][j]=temp;used[j][k]=used[k][j]=0;touched[j][k]=touched[k][j]=0;}for(j=0;j<num;j++){path[j][0]=0;path[j][1]=0;}for(j=0;j<num;j++){status=0;for(k=0;k<num;k++)if(G[j][k]<maxright){status=1;break;}if(status==0)break;}for(i=0;i<num-1&&status;i++) {for(j=0;j<num;j++)for(k=0;k<num;k++)if(G[j][k]<min&&!used[j][k]){v1=j;v2=k;min=G[j][k];}if(!used[v1][v2]){used[v1][v2]=1;used[v2][v1]=1;touched[v1][v2]=1;touched[v2][v1]=1;path[0]=v1;path[1]=v2;for(t=0;t<record;t++)FindCircle(path[t][0],path[t][0],num,path[t][0]); if(circle){/*if a circle exsits,roll back*/circle=0;i--;exsit=0;touched[v1][v2]=0;touched[v2][v1]=0;min=maxright;}else{record++;min=maxright;}}}if(!status)printf("We cannot deal with it because the graph is not connected!\n");else{for(i=0;i<num-1;i++)printf("Path %d:vertex %d tovertex %d\n",i+1,path[0]+1,path[1]+1);}return 1;}intFindCircle(intstart,intbegin,inttimes,int pre) { /* to judge whether a circle is produced*/ inti;for(i=0;i<times;i++)if(touched[begin]==1){if(i==start&&pre!=start){circle=1;return 1;break;}elseif(pre!=i)FindCircle(start,i,times,begin);elsecontinue;}return 1;}matlab代码实现functionKruskal(w,MAX)%此程序为最小支撑树的Kruskal算法实现%w为无向图的距离矩阵,故为对称矩阵%MAX为距离矩阵中∞的实际输入值%时间:2011年6月22日0:07:53len=length(w); %图的点数edge=zeros(len*(len-1),3); %用于存储图中的边count=1; %图中的边数for i=1:len-1 %循环距离矩阵,记实存储边for j=i+1:lenif w(i,j)~=MAXedge(count,1)=w(i,j);edge(count,2)=i;edge(count,3)=j;count=count+1;endendendedge=edge(1:count-1,:); %去掉无用边[tmp,index]=sort(edge(:,1)); %所有边按升序排序i=3; %其实测试边数为3条(3条以下无法组成圈,即无需检测)while 1x=findcycle(edge(index(1:i),:),len); %检测这些边是否组成圈if xindex(i)=0; %若组成圈,则将该边对应的index项标识表记标帜为0,以便除去elsei=i+1; %若没有组成圈,则i加1,参加下一边检测endindex=index(index>0); %将组成圈的边从index中除去ifi==lenbreak; %找到合适条件的点数减一条的边,即找到一个最小支撑树endendindex=index(1:len-1); %截短index矩阵,保存前len-1项%%%%%%%%%%%% 结果显示%%%%%%%%%%%%%s=sprintf('\n\t%s\t%s\t %s\t','边端点','距离','是否在最小支撑树');fori=1:count-1edge_tmp=edge(i,:);if ~isempty(find(index==i,1))s_tmp=sprintf('\n \t (%d,%d)\t %d\t %s\t',edge_tmp(2),edge_tmp(3),edge_tmp(1),'√');elses_tmp=sprintf('\n \t (%d,%d)\t %d\t %s\t',edge_tmp(2),edge_tmp(3),edge_tmp(1),'×');ends=strcat(s,s_tmp);enddisp(s);endfunctionisfind=findcycle(w,N)%本程序用于判断所给的边能否组成圈:有圈,前往1;不然前往0%w:输入的边的矩阵%N:原图的点数%原理:不竭除去出现次数小于2的端点所在的边,最后不雅察是否有边留下len=length(w(:,1));index=1:len;while 1num=length(index); %边数p=zeros(1,N); %用于存储各点的出现的次数(一条边对应两个端点)for i=1:num %统计各点的出现次数p(w(index(i),2))=p(w(index(i),2))+1;p(w(index(i),3))=p(w(index(i),3))+1;endindex_tmp=zeros(1,num); %记实除去出现次数小于2的端点所在的边的边的下标荟萃discard=find(p<2); %找到出现次数小于2的端点count=0; %记实剩余的边数fori=1:num%判断各边是否有仅出现一次端点——没有,则记实其序号于index_tmpif ~(~isempty(find(discard==w(index(i),2),1)) ||~isempty(find(discard==w(index(i),3),1)))count=count+1;index_tmp(count)=index(i);endendif num==count %当没有边被被除去时,循环停止index=index_tmp(1:count); %更新indexbreak;elseindex=index_tmp(1:count); %更新indexendendif isempty(index) %若最后剩下的边数为0,则无圈isfind=0;elseisfind=1;endend%% a =[% 0 3 2 3 100 100100% 3 0 2 100 100100 6% 2 2 0 3 100 1 100% 3 100 3 0 5 100 100% 100 100100 5 0 4 6% 100 100 1 100 4 0 5% 100 6 100 6 100 5 0];%% Kruskal(a,100)pascal代码实现{最小生成树的Kruskal算法.Kruskal算法根本思想:每次选不属于同一连通份量(包管不生成圈)且边权值最小的顶点,将边参加MST,并将所在的2个连通份量归并,直到只剩一个连通份量排序使用Quicksort(O(eloge))查抄是否在同一连通份量用Union-Find,每次Find和union运算近似常数Union-Find使用rank启发式归并和路径压缩总庞杂度O(eloge)=O(elogv) (因为e<n(n-1)/2)}constmaxn=100;maxe=maxn*maxn;typeedge=recorda,b :integer; //边的2个顶点len :integer; //边的长度end;varedges :array[0..maxe]of edge; //保管所有边的信息p,r :array[0..maxn]of integer; //p保管i的父亲节点,r用来实现Union-Find的rank启发式n,e :integer; //n为顶点数,e为边数procedure swap(a,b:integer); //互换beginedges[0]:=edges[a];edges[a]:=edges[b];edges[b]:=edges[0];end;procedure quicksort(l,r:integer); //快速排序varx,i,j :integer;beginx:=edges[random(r-l+1)+l].len;i:=l;j:=r;repeatwhile edges[i].len<x do inc(i);while edges[j].len>x do dec(j);ifi<=j thenbeginswap(i,j);inc(i);dec(j);enduntili>j;if l<j then quicksort(l,j);ifi<r then quicksort(i,r);end;procedureinit;vari :integer;beginassign(input,'g.in');reset(input);readln(n,e);for i:=1 to e do readln(edges[i].a,edges[i].b,edges[i].len); //从文件读入图的信息for i:=1 to n do p[i]:=i; //初始化并查集randomize;quicksort(1,e); //使用快速排序将边按权值从小到大排列end;function find(x:integer):integer; //并查集的Find,用来判断2个顶点是否属于一个连通份量beginif x<>p[x] then p[x]:=find(p[x]);find:=p[x]end;procedure union(a,b:integer); //如果不属于且权值最小则将2个顶点归并到一个连通份量vart :integer;begina:=find(a);b:=find(b);if r[a]>r[b] then begin t:=a;a:=b;b:=t end;if r[a]=r[b]then inc(r[a]);p[a]:=b;end;procedure kruskal; //主进程varen :integer; //en为当前边的编号count :integer; //统计进行了几回归并.n-1次归并后就得到最小生成树tot :integer; //统计最小生成树的边权总和begincount:=0;en:=0; tot:=0;while count<n-1 dobegininc(en);with edges[en] dobeginif find(a)<>find(b) thenbeginunion(a,b);writeln(a,'--',b,':',len);inc(tot,len);inc(count);end;end;end;writeln('Total Length=',tot)end;{===========main==========} begininit;kruskal;end.例题详见vijos p1045 Kerry 的电缆网络typerec=recordx,y:longint;cost:real;end;varf:array[1..1000000] of rec;s,ans:real;i,n,m,k,dad:longint;father:array[1..1000000] of longint; procedurekp(l,r:longint);vari,j:longint;xx:real;y:rec;begini:=l;j:=r;xx:=f[(i+j) div 2].cost;repeatwhile xx>f[i].cost do inc(i);while xx<f[j].cost do dec(j);ifi<=j thenbeginy:=f[i];f[i]:=f[j];f[j]:=y;inc(i);dec(j);end;untili>j;ifi<r then kp(i,r);if l<j then kp(l,j);end;function find(x:longint):longint; beginif father[x]=x then exit(x);father[x]:=find(father[x]);exit(father[x]);end;procedure union(x,y:longint;j:real); beginx:=find(x);y:=find(y);if x<>y thenbeginfather[y]:=x;ans:=ans+j;inc(k);end;end;beginreadln(s);readln(n);m:=0;while not eof do begininc(m);with f[m] doreadln(x,y,cost); end;if m<n-1 then beginwriteln('Impossible'); exit;end;fori:=1 to n do father[i]:=i;kp(1,m);k:=0;fori:=1 to m dobeginif k=n-1 then break;union(f[i].x,f[i].y,f[i].cost);end;if k<n-1 thenbeginwriteln('Impossible');exit;end;ifans>s then writeln('Impossible') elsewriteln('Need ',ans:0:2,' miles of cable');end.Kruskal算法适用于边稀疏的情形,而Prim算法适用于边稠密的情形其它最小生成树算法c++代码实现#include <stdio.h>#include <stdlib.h>#include <vector>using namespace std;#define MAXNUM_VERTEX 20 //最多有20个顶点#define MAXNUM_EDGE 21typedefstruct{intv,w;int weight;}Edge;typedefstruct{int vertex[MAXNUM_VERTEX];Edge edge[MAXNUM_EDGE];intnum_vertex,num_edge;}Graph;Graph graph; //声明为全局变量boolsearch_vertex(intver){for(inti=0; i<graph.num_vertex; i++)if(ver == graph.vertex[i] )return 1;printf("the vertex %d you input is not existed! \n",ver); return 0;}voidcreate_graph(){//输入顶点信息printf("input the number of vertex in the graph\n");scanf(" %d",&graph.num_vertex);printf("input the vertex of graph,like 1,2\n");for(inti=0; i<graph.num_vertex; i++)scanf(" %d",&graph.vertex[i]);//输入边信息printf("input the number of edge in the graph\n");scanf(" %d",&graph.num_edge);printf("intput the edge of graph and the weight of line,like 1-2 5\n");for(int j=0; j<graph.num_edge; j++){p1:inta,c,d;char b;scanf(" %d %c %d %d",&a,&b,&c,&d);if(search_vertex(a) && search_vertex(c) ){graph.edge[j].v=a;graph.edge[j].w=c;graph.edge[j].weight=d;}elsegoto p1;}}voidsort_by_weight(){for(inti=1; i<graph.num_edge; i++){Edge temp=graph.edge[i];for(int j=i-1; j>=0 && graph.edge[j].weight>temp.weight; j--) graph.edge[j+1]=graph.edge[j];graph.edge[j+1]=temp;}}/*不相交集处理函数*/inline void makeset(vector<int> & array){for(inti=0; i<array.size(); i++)array[i]=i;}intfindset(vector<int> & parent,inti){if(i != parent[i])i=parent[i];returni;}inline void merge(vector<int> & parent,inti,int j) {parent[i]=j;}/*不相交集处理函数*/voidkruskal(){intnum_ver=graph.num_vertex;int count=0;vector<int> parent_ver;parent_ver.resize(num_ver);/*焦点部分是用不相交集分解树*/ makeset(parent_ver);printf("the edge of min tree as follow: \n");for( inti=0; i<num_ver && count<num_ver-1; i++ ) //count 暗示归并(merge)的次数num_ver-1次{int m=graph.edge[i].v;int n=graph.edge[i].w;int w=graph.edge[i].weight;if(findset(parent_ver,m) != findset(parent_ver,n)) //当属于不合的集应时,则将该边添加进树中{printf("(%d %d) %d\n",m,n,w);merge(parent_ver,m,n);count++;}}}voidprint_edge(){printf("the graph you input as follow: \n");for(inti=0; i<graph.num_edge; i++)printf("%d-%d the weightis: %d\n",graph.edge[i].v,graph.edge[i].w,graph.edge[i].weight);}void main(){create_graph();sort_by_weight();print_edge();kruskal();}java代码实现importjava.util.ArrayList;importjava.util.Collections;class Bian implements Comparable // 两点之间的加权边{private intfirst,second;// 暗示一条边的两个节点private int value;// 权值publicBian(intfirst,intsecond,int value) {this.first = first;this.second = second;this.value = value;}publicintgetFirst() {return first;}publicintgetSecond() {return second;}publicintgetValue() {return value;}@OverridepublicintcompareTo(Object arg0) {return value > ((Bian) arg0).value 1: (value == ((Bian) arg0).value 0 : -1);}@Overridepublic String toString() {return "Bian [first=" + first + ",second=" + second + ",value="+ value + "]";}}classShuZu {static ArrayList<ArrayList> list = newArrayList<ArrayList>();// 存放每一个数组中的节点的数组static ArrayList<ArrayList> bianList = newArrayList<ArrayList>();// 对应存放数组中的边的数组public static void check(Bian b)// 查抄在哪个数组中{if (list.size() == 0) {ArrayList<Integer> sub = new ArrayList<Integer>();sub.add(b.getFirst());sub.add(b.getSecond());list.add(sub);ArrayList<Bian> bian = new ArrayList<Bian>();bian.add(b);bianList.add(bian);return;}int first = b.getFirst();int shuyu1 = -1;int second = b.getSecond();int shuyu2 = -1;for (inti = 0; i < list.size(); i++)// 查抄两个节点辨别属于哪个数组{for (int m = 0; m < list.get(i).size(); m++) {if (first == (Integer) list.get(i).get(m))shuyu1 = i;if (second == (Integer) list.get(i).get(m))shuyu2 = i;}}if (shuyu1 == -1 && shuyu2 == -1)// 暗示这两个节点都没有需要新参加{ArrayList<Integer> sub = new ArrayList<Integer>();sub.add(b.getFirst());sub.add(b.getSecond());list.add(sub);ArrayList<Bian> bian = new ArrayList<Bian>();bian.add(b);bianList.add(bian);}if (shuyu1 == -1 && shuyu2 != -1)// 暗示有一个点已经在数组中只把另一个参加就可以了{list.get(shuyu2).add(first);bianList.get(shuyu2).add(b);}if (shuyu2 == -1 && shuyu1 != -1)// 暗示有一个点已经在数组中只把另一个参加就可以了{list.get(shuyu1).add(second);bianList.get(shuyu1).add(b);}if (shuyu1 == shuyu2 && shuyu1 != -1)// 表述两个在同一个组中会形成环{}if (shuyu1 != shuyu2 && shuyu1 != -1 && shuyu2 != -1)// 暗示两个点在不合的组中需要归并{for (inti = 0; i < list.get(shuyu2).size(); i++) {list.get(shuyu1).add(list.get(shuyu2).get(i));}list.remove(shuyu2);for (inti = 0; i < bianList.get(shuyu2).size(); i++) { bianList.get(shuyu1).add(bianList.get(shuyu2).get(i));}bianList.get(shuyu1).add(b);bianList.remove(shuyu2);}}public static void show() {for (inti = 0; i < bianList.get(0).size(); i++) System.out.println(bianList.get(0).get(i));}}public class Test {public static void main(String[] args) { ArrayList<Bian> l = new ArrayList<Bian>(); l.add(new Bian(1,3,1));l.add(new Bian(1,2,6));l.add(new Bian(1,4,5));l.add(new Bian(2,3,5));l.add(new Bian(2,5,3));l.add(new Bian(3,4,5));l.add(new Bian(3,5,6));l.add(new Bian(3,6,4));l.add(new Bian(4,6,2));l.add(new Bian(5,6,6));Collections.sort(l);// for(inti = 0 ;i<l.size();i++)// System.out.println(l.get(i)); for (inti = 0; i < l.size(); i++) ShuZu.check(l.get(i));ShuZu.show();}}。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
相关文档
最新文档