随笔 - 251  文章 - 504  trackbacks - 0
<2006年11月>
2930311234
567891011
12131415161718
19202122232425
262728293012
3456789

本博客系个人收集材料及学习记录之用,各类“大侠”勿扰!

留言簿(14)

随笔分类

收藏夹

My Favorite Web Sites

名Bloger

非著名Bloger

搜索

  •  

积分与排名

  • 积分 - 200393
  • 排名 - 285

最新评论

若要在n个城市之间建设通讯网络,只需要架设n-1条线路即可。如何以最低的经济代价建设这个通讯网络,是一个网的最小生成树问题。本单元的实验内容主要是利用克鲁斯卡尔算法求出网的最小生成树,并且以文本形式输出树中的各条边以及他们的权值。

#include<iostream>
#include<stdlib.h>//产生随机数组用
#include<time.h> //同上
 #include<list>

 // 1) 带权边的类MyArc:

class MyArc
{
public:
    int m_beginVex;
    int m_endVex;
    int m_weight;
    MyArc(int beginVex,int endVex,int weight);
    MyArc(){}
    bool operator < (const MyArc& arc)
    {
        return m_weight<arc.m_weight;
    }
    bool operator == (const MyArc& arc)
    {
        return m_weight==arc.m_weight;
    }
    bool operator > (const MyArc& arc)
    {
        return m_weight>arc.m_weight;
    }
}  ;

MyArc::MyArc(int beginVex,int endVex,int weight):m_beginVex(beginVex),m_endVex(endVex),m_weight(weight)
{}
//2) 表示图的邻接矩阵类Graph:
class Graph
{
public:
    int m_vexnum;
    int m_arcnum;
    int *m_pmatrix;
public:
    ~Graph();
    Graph(int vexnum);
    Graph(int vexnum,int *pmatrix);
    void insert(MyArc arc);//按权值大小排序插入
    bool bound(int x);   //判断顶点x是否已与其它顶点连通
};
//构造函数
Graph::Graph(int vexnum)
{
    m_pmatrix=new int[vexnum*vexnum];
    m_vexnum=vexnum;m_arcnum=0;
    for(int i=0;i<vexnum*vexnum;++i)
    m_pmatrix[i]=0;

}

//构造函数
Graph::Graph(int vexnum,int *pmatrix)
{
    m_vexnum=vexnum;
    // m_arcnum=arcnum;
    m_pmatrix=new int[m_vexnum*m_vexnum];
    for(int i=0;i<m_vexnum*m_vexnum;++i)
        m_pmatrix[i]=pmatrix[i];
}

//测试 顶点x是否已与其他点连通
bool Graph::bound(int x)
{
    for(int i=0;i<m_vexnum;++i) if(m_pmatrix[x+i*m_vexnum]!=0) return true;
    return false;
}

//在邻接表中连通 arc表示的边,并且设置权
void Graph::insert(MyArc arc)
{
    m_pmatrix[arc.m_beginVex*m_vexnum+arc.m_endVex]=arc.m_weight;
    m_pmatrix[arc.m_endVex*m_vexnum+arc.m_beginVex]=arc.m_weight;
    ++m_arcnum;
}
//析构
Graph::~Graph()
{
    delete[] m_pmatrix;
}
//3) 按权存储边的有序队列类MyQueues:

//边按权值插入队列中合适位置,
class MyQueues
{
public:
    list<MyArc> m_list;
    MyQueues(){}
    void insert(const MyArc& arc);//边按权值插入队列中合适位置,
    void InsertGraph(const Graph &graph);//将图的连通分量插入队列
    MyArc pop();
};
//边出队
MyArc MyQueues::pop()
{
    MyArc arc=m_list.front();
    m_list.pop_front();
    return arc;
}
//边按权值插入队列中合适位置,
void MyQueues::insert(const MyArc& arc)
{
    list<MyArc>::iterator pos;
    pos=m_list.begin();
    while(pos!=m_list.end())
    {
        if(*pos>arc) break;
        else ++pos;
    }
    m_list.insert(pos,arc);
}
//将图的连通分量插入队列
void MyQueues::InsertGraph(const Graph &graph)
{
    for(int i=0;i<graph.m_vexnum;++i)
    {
        for(int j=i+1;j<graph.m_vexnum;++j)
              if(graph.m_pmatrix[i*graph.m_vexnum+j]) insert(MyArc(i,j,graph.m_pmatrix[i*graph.m_vexnum+j]));
    }
}

 //5)判断是否有回路的IsCycle函数:
bool IsCycle(Graph& graph, MyArc& arc)
{
    list<int> my_list;
    my_list.push_back(arc.m_beginVex);
    int *ps=new int[graph.m_vexnum];
    for(int i=0;i<graph.m_vexnum;++i)
        ps[i]=0;
    while(!my_list.empty())
    {
        int x=my_list.front();
        ps[x]=1;
        my_list.pop_front();
        for(int i=0;i<graph.m_vexnum;++i)
        {
              if(graph.m_pmatrix[i+x*graph.m_vexnum]!=0)
              {
                  if(i==arc.m_endVex) return true;
                  if(ps[i]!=1) my_list.push_back(i);
              }
        }
    }
    delete[] ps;
    return false;
}
//4) kruskal算法:
void kruskal(const Graph& graph,Graph& smtree)
{
    MyQueues arcqueues;//保存从小到大排列的边
    arcqueues.InsertGraph(graph);
    MyArc myarc;//Arc表示边的类型
    int arcnum=0; //边的个数
    while(arcnum<graph.m_vexnum-1)
    {
        myarc=arcqueues.pop();
        if(!IsCycle(smtree,myarc))
        {
              smtree.insert(myarc);
              ++arcnum;
        }
    }
}


void SetMatrix(int vexnum,int *pmatrix)
{
    srand((unsigned)time(NULL));
    for(int i=0;i<vexnum;++i)//产生随机权值矩阵
    {
        for(int j=i;j<vexnum;++j)
        {
              if(j==i)
              {
                  pmatrix[i*vexnum+j]=0;
                  continue;
              }
              int rnum=rand();rnum%=99;rnum++;//产生1~99的随机整数作为边的权值
              pmatrix[i*vexnum+j]=rnum;
              pmatrix[j*vexnum+i]=rnum;
        }
    }
    cout<<"***随机产生的各边权值矩阵 [顶点数为 "<<vexnum<<"] ****\n";
  for(int i=0;i<vexnum;++i)//输出随机权值矩阵
    {
        for(int j=0;j<vexnum;++j)
        {
              cout<<pmatrix[i*vexnum+j]<<"\t";
        }
        cout<<endl;
    }

}

void SmallestTreeOutput(const Graph& smtree)
{
    cout<<"最小生成树:"<<endl;
    for(int i=0;i<smtree.m_vexnum;++i)//输出最小树
        for(int j=i+1;j<smtree.m_vexnum;++j)
              if(smtree.m_pmatrix[i*smtree.m_vexnum+j])
                  cout<<'('<<i<<','<<j<<','<<smtree.m_pmatrix[i*smtree.m_vexnum+j]<<')'<<endl;
}

 

void main()
{
    char i;
    cout<<"请输入顶点数目:";
    cin>>i;
  int vex=i-'0';
    int *matrix=new int[vex*vex];
    cout<<endl;
    SetMatrix(vex,matrix);
    Graph graph(vex,matrix),smtree(vex);
    kruskal(graph,smtree);
    SmallestTreeOutput(smtree);
    delete []matrix;
}


结果输出:
请输入顶点数目:6

***随机产生的各边权值矩阵 [顶点数为 6] ****
0       64      7       15      22      43
64      0       72      86      53      40
7       72      0       53      37      22
15      86      53      0       87      82
22      53      37      87      0       9
43      40      22      82      9       0
最小生成树:
(0,2,7)
(0,3,15)
(0,4,22)
(1,5,40)
(4,5,9)

posted on 2006-11-20 14:59 matthew 阅读(3847) 评论(6)  编辑  收藏 所属分类: 数据结构与算法设计

FeedBack:
# re: 数据结构之图及其应用—网的最小生成树  2006-12-30 14:38 jdf
好像有点问题,我用vc++6.0编译不过  回复  更多评论
  
# re: 数据结构之图及其应用—网的最小生成树  2006-12-30 18:41 matthew[匿名]
我试过了,能够编译运行。编译环境:C-Free3.5  回复  更多评论
  
# re: 数据结构之图及其应用—网的最小生成树  2007-04-13 08:53 45655
请教用java 怎么编写————最小生成树的应用。
【例】网络G表示n个城市之间的通信线路网(其中顶点表示城市,边表示两个城市之间的通信线路,边上的权值表示线路的长度或造价。可通过求该网络的最小生成树达到求解通信线路或总代价最小的最佳方案。

问题的实现:
要求用java语言动态实现此过程,步骤:
(1)首先在文本框内输入城市的个数,即顶点数;
(2)根据输入的顶点个数点击鼠标分别显示出①②③④⑤;
(3)在文本框内分别输入两个城市的名字以及权值,与此同时,在图中自动画出两点之间的连线,并在线的中央显示其权值。

  回复  更多评论
  
# re: 数据结构之图及其应用—网的最小生成树  2007-04-13 08:53 45655
谢谢拉
  回复  更多评论
  
# re: 数据结构之图及其应用—网的最小生成树  2007-06-01 13:21 wyx860216@sina.com
请教下面这题的C语言源程序:

网络G表示n个城市之间的通信线路网(其中顶点表示城市,边表示两个城市之间的通信线路,边上的权值表示线路的长度或造价。可通过求该网络的最小生成树达到求解通信线路或总代价最小的最佳方案。

要求用visual C++编写..

谢谢!
  回复  更多评论
  
# re: 数据结构之图及其应用—网的最小生成树 [未登录] 2008-12-22 20:37 ZY
万分感谢,写的很精彩,无私的博主!  回复  更多评论
  

只有注册用户登录后才能发表评论。


网站导航: