最小生成树(1)

最小生成树是在图论中的一个重要的问题,我们找一个图的最小生成树,也就是找链接所有的顶点,并且使得各边的代价之和最小。当然最小生成树的程序的编写也是相当的复杂,数据结构书上也有通过prim算法来创建最小生成树,当然在这个地方我们是通过克鲁斯卡尔算法:(假设一个连通网N=(V,{E}),则令最小生成树的初始状态为只有n个顶点而无边的非连同图T=(V,{}),图中的每一个顶点自成一个连同分量。在E中选择代价最小的边,如果该边依附的顶点落在T中不同的连接分量上,则将此边加入到T中,否则舍去此边而选择下一条代价最小的边,依次类推,一直到T的所有 的顶点都在一个连通分量上为止。)来创建一个图的最下生成树。

首先我们应该先创建一个图:

typedef struct ArcNode
{
int  adjvex;//该弧所指向顶点的位置
struct ArcNode *nextarc;//指向下一条弧的指针
InfoType info;//该弧相关的信息指针
}ArcNode;
//定义头节点信息
typedef struct VNode
{
   VertexType data;
   ArcNode *firstarc;
}VNode,AdjList[MAX_VERTEX_NUM];
typedef struct{
AdjList vertice;//用来记录顶点的名称
int vexnum,arcnum;//图中的当前的节点和弧度数目
int kind;//图的类型
}ALGraph;

这个地方我们是使用的邻接表来存储一个图,这个在数据结构(严蔚敏)P163可以找到。

第二步:创建一个无向图

Status CreateUDN(ALGraph *G,SqList *L)
{
int a,b,value;
int i=0,j=0;
cout<<"请输入图的顶点数目,边的数目,图的类型(0为无向图): "<<endl;
     cin>>G->vexnum>>G->arcnum>>G->kind;
cout<<"请输入顶点:"<<endl;
//顶点是链表的头结点,然后这个链表的其他的结点都是一些边
for(i;i<G->vexnum;i++)
{
cin>>G->vertice[i].data;//读入顶点的信息
G->vertice[i].firstarc=NULL;//此时顶点作为是链表的头结点,谁也不指向
}
//接着要做的事情也即是填充边
cout<<"请输入边的信息:(a,b,value)"<<endl;
for(i=0;i<G->arcnum;i++)
{
cin>>a>>b>>value;
L->elem[i].data1=a;
L->elem[i].data2=b;
L->elem[i].value=value;
L->length++;
ArcNode *S=(ArcNode *)malloc(sizeof(ArcNode));
S->adjvex=b;
S->info=value;
S->nextarc=G->vertice[a].firstarc;
G->vertice[a].firstarc=S;
ArcNode *S1=(ArcNode *)malloc(sizeof(ArcNode));
S1->adjvex=a;
S1->info=value;
S1->nextarc=G->vertice[b].firstarc;
G->vertice[b].firstarc=S1;
}
return OK;
}
void showUDN(ALGraph *G)
{
ArcNode *V=(ArcNode *)malloc(sizeof(ArcNode));
for(int i=0;i<G->vexnum;i++)
{
cout<<G->vertice[i].data<<"----";
V=G->vertice[i].firstarc;
   while(V)
{
  cout<<V->adjvex<<"-----"<<V->info<<"------";
  V=V->nextarc;
}
cout<<endl;


}
}

需要注意的是,我们在创建无向图的时候,不仅仅是创建了一个图,同时也将每个弧的信息存放到一个连接表中了,这个地方是方便一以后通过各边的权值进行一个大小的排序。

 L->elem[i].data1=a;  L->elem[i].data2=b; L->elem[i].value=value; L->length++;

第三步:根据各边的权值对边进行从小到大的一个排序,这个地方排序采用的是直接插入排序法

void InsertSort(SqList *L)
{
    int j;
for(int i=2;i<=L->length;++i)
{
if(LT(L->elem[i].value,L->elem[i-1].value))
sideEqual(&L->elem[0],&L->elem[i]);
sideEqual(&L->elem[0],&L->elem[i-1]);
for(j=i-2;LT(L->elem[0].value,L->elem[j].value);--j)
sideEqual(&L->elem[j+1],&L->elem[j]);
sideEqual(&L->elem[j+1],&L->elem[0]);
}
}

插入排序之后我们将弧按照权值的大小存放在一个线性表中,然后我们需要做的事情是从线性表中将边依次拿出来连接连通分量,如果每次都是是连接两个连通分量说明没有构成环,当其中的弧连接是一个连通图中的两个点的时候这个时候这个弧我们就要舍弃不用,继续下一个较大的弧依次这样,知道图中的弧的个数比顶点的个数小1的时候,说明最小生成树构造成功。具体程序请见下一节:最小生成树(2)。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值