从图中提取边的开始begin、结束end和权重weight

package test1;


import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;
public class test {
	
       //邻接矩阵 
    final static int MAX = 65535;  //  两个顶点之间没有路径时的长度
    int verticts;                 //  顶点数
    int sides;                   //  边数
    String[] vex;               //  一维数组        存储顶点信息
    int[][] arc;               //  二维数组        存储边的权重;
    
    test(int verticts){
        this.verticts = verticts;
        this.sides = 0;
        for(int i = verticts-1;i>0;i--){
            this.sides +=i;                  //  计算边数,共n(n-1)/2;
        }
        this.vex = new String[verticts];                    // 创建  顶点数组
        this.arc = new int[verticts][verticts];             // 创建  边数组
      
        //初始化一个无向图,所有边设为最大权值(即不可能达到的值)
        for(int i = 0; i < verticts;i++){
            for(int j = 0; j < verticts;j++){
                if(i!=j){
                   this.arc[i][j] = MAX;
                }else{
                    this.arc[i][j]=0;
                }
                
            }
        }
    }
    
    // 建立无向网图,  给图中的  顶点内容 和  边权重  赋值
    public void addGraph(){
        //顶点数据
        this.vex[0] = "beijing";
        this.vex[1] = "shanghai";
        this.vex[2] = "tianjing";
        this.vex[3] = "chengdu";
        this.vex[4] = "changsha";
        this.vex[5] = "chongqing";

        //边的权值
        for(int i = 1; i < verticts;i++){
            for(int j = 0; j < i;j++){
                int n = (int)(Math.random()*100);    //随机生成权值
                if(n > 0){
                this.arc[i][j]=this.arc[j][i] = n;
                }else if(n == 0){
                    this.arc[i][j]=this.arc[j][i] = MAX;
                }
                
            }
        }
    }

    //利用图的二维数组输出
    public void printGraph(){
        for(int i = 0; i < verticts;i++){
            //输出第一行的名称
            if(i == 0){
                System.out.print("*         ");
                for(int x=0;x<verticts;x++){
                    System.out.print(this.vex[x]+"  ");
                }
                System.out.println();
                System.out.println("         ==============================================================");
            }
            //给每行前面输出地址
                System.out.print(this.vex[i]+"     ");
            for(int j = 0; j < verticts;j++){
                System.out.print(this.arc[i][j]+"        ");
            }
            System.out.println();
            System.out.println();
        }
    }

   
    /*//得到最小生成树之克鲁斯卡尔(Kruskal)算法
    //得到边集数组并按权由大到小排序 这一步是利用Edge类来实现的
    //注意 此函书还有错误,有时候会输出6条边,尚待解决(MinispanTree_kruskal在寻找的过程中不可能形成环路,所以不可能多一条边)
    //上述错误已经解决,有两个地方出来问题,第一:Edge的begin必须小于end,否则在Find函数中判断将出现错误,因为如果end小于begin的话,end有可能
    //出现等于0的情况,第二:循环每一条边时,i应该小于G.sides;而我之前写成了i<G.verticts
    public void MiniSpanTree_Kruskal(test G){
        Edge edge = new Edge(); 
        edge.Edge_1(G);
        //edge.PrintEdge();
        int i, n, m;
        int num = 0;  //记录找到了多少条边
        int parent[] = new int[G.verticts];   //定义一个数组用来判断边与边是否形成回路
        for( i = 0;i < G.verticts;i++){
            parent[i] = 0;      //初始化数组为-1
        }
        for(i = 0;i < G.sides;i++){        // 循环每一条边,15为顶点
            n = Find(parent,edge.edge[i].begin);
            m = Find(parent,edge.edge[i].end);
            if(n != m ){         //n不等于m  说明边与边没有形成环路
                parent[n] = m;//将此边的尾节点放入下标为起点的parent中
                System.out.println("("+edge.edge[i].begin+","+edge.edge[i].end+")"+"  权长:"+edge.edge[i].weight);
                num++;
                //for(int j = 0;j < G.verticts;j++){
                    //System.out.print("  !!!!"+parent[j]);      //初始化数组为0
                 //}
            }
            if(num >= G.verticts)  break;     //如果找到了(顶点数-1)条边,并且没有构成回路,就已经完成任务了,不用再找了,
            
        }
    }
    public int Find(int[] parent,int f){        //查找连线顶点的尾部下表
        while(parent[f] > 0){
            f = parent[f];
        }
        return f;
    }

*/
    //测试函数
    public static void main(String[] args){
        test graph = new test(6);  //创建一个顶点个数为6的图
        graph.addGraph();
        System.out.println("将图以二维矩阵的方式输出");
        graph.printGraph(); 
       
        Edge edge = new Edge(); 
        edge.Edge_1(graph);
        edge.PrintEdge();
        
       /* System.out.println();
        System.out.println("最小生成树之克鲁斯卡尔算法Kruskal   ");
        graph.MiniSpanTree_Kruskal(graph);
*/
    }
}


//Edge类  利用深度优先遍历得到树的所有路径以及这些路径的权值,并根据权值的大小进行从小到大排序
class Edge{
    public int begin;           //这两个顶点的开始顶点
    public int end;             //这两个顶点的结束顶点
    public int weight;          //两个顶点之间的权值
    Edge edge[] = new Edge[15]; //edge数组  图的边数没有传入,计算最大值
   
    public void Edge_1(test G){
        DFSTraverse_1(G);       //得到edge数组
        sortEdge();             //对edge进行排序
    }
    
    public void SetEdge(int begin,int end,int weight){
        this.begin = begin;
        this.end = end;
        this.weight = weight;
        
    }
    int k=0;        //用于数组赋值是计数
    //利用深度优先遍历得到edge数组
    public void  DFS_1(test G,int i,boolean[] visited){
        int j;
        
        visited[i] = true;
        //System.out.print(G.arc[i][i+1]+"  ");   //打印顶点的值
        for(j = 0;j < G.verticts;j++)
        {
            if(G.arc[i][j]>0 && !visited[j]){
                //System.out.print(G.arc[i][j]+"  ");
                DFS_1(G,j,visited);       //对访问的邻接顶点递归调用
            }
            if(G.arc[i][j] > 0  && i < j){
                this.edge[this.k] = new Edge();
                edge[this.k].SetEdge(i,j,G.arc[i][j]);   //edge数组中的每个元素都是Edge类型,即每个元素有begin,end和weight三个属性
                this.k++;
            }
            
        }
        
    }
    public void DFSTraverse_1(test  G){
        boolean[] visited = new boolean[G.verticts];
        for(int i = 0;i < G.verticts;i++){
            visited[i] = false;         //初始状态所有顶点都是未访问过的状态
        }
        for(int i = 0;i < G.verticts;i++){
            if(!visited[i])
                DFS_1(G,i,visited);       //对未访问过的顶点调用DFS  如果是连通图,则只会执行一次
        }
    }
    //对得到的数组进行排序
    public void sortEdge(){
        Edge newEdge = new Edge();
        newEdge.edge[0] = new  Edge();
        for(int i = 0;i < this.edge.length;i++){
            for(int j =  i;j < this.edge.length;j++){
                if(this.edge[i].weight > this.edge[j].weight){
                    newEdge.edge[0] = this.edge[i];
                    this.edge[i] = this.edge[j];
                    this.edge[j] = newEdge.edge[0];
                }
            }
        }
    }
    //输出Edge数组,用以测试Edge是否创建、赋值成功
    public void PrintEdge(){
        for(int i = 0; i < this.edge.length;i++){
            System.out.println("数组"+i+":    "+this.edge[i].begin+"  "+this.edge[i].end+"  "+this.edge[i].weight);
        }
    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值