寻找最小生成树的欧拉路径,即一笔画问题



【程序背景】最近在做子图匹配的实验,对查询图需要进行预处理,得到最小生成树,然后进行后续的子图匹配工作,由于匹配过程是按照顺序依次遍历匹配的,当时程序就卡在寻找一条顺序相连的最小生成树的欧拉路径问题上了,查了很多关于欧拉路径的解决方案,觉得过于复杂,干脆最后自己写了一个小程序,解决了。

【问题说明】输入list:(2,6)(1,3)(1,2)(4,5)(1,4)

得到newlist:(4,5)(1,4)(1,3)(1,2)(2,6)

【实验环境】eclipse+Java

【算法思路】list是最小生成树,newlist是需要得到顺序相连的欧拉路径,注意最小生成树一定是连通图,即一定存在欧拉路径

 * 第一步--->取list中的第一条边,遍历剩余边,寻找与该边相连接的所有边,add到newList中
 * 第二步--->取list中的剩余边edge,与newList中的边进行比较
 * 1-->如果edge与newlist的第一条边相连,直接newList.add(0,edge),在头插入,然后删除list中的edge
 * 2-->如果edge与newlist的最后一条边相连,直接newList.add(edge),在尾插入,然后删除list中的edge
 * 3-->如果edge与newlist中间的一条边相连,先把newlist中的那条边移动到尾部,再进行插入删除操作
 * 4-->如果都不相连,去list的下一条边进行上述操作,直至最后list集合为空为止。

【代码说明】代码中有一个Edge类--->Edge(CITING,CITED),表示一条边,专利的引用关系。

[html] view plain copy
  1. public class Edge {  
  2.     private String CITING;  
  3.     private String CITED;  
  4.       
  5.     public Edge(String CITING,String CITED){  
  6.         this.CITING = CITING;  
  7.         this.CITED = CITED;  
  8.     }  
  9.   
  10.     public String getCITING() {  
  11.         return CITING;  
  12.     }  
  13.   
  14.     public void setCITING(String cITING) {  
  15.         CITING = cITING;  
  16.     }  
  17.   
  18.     public String getCITED() {  
  19.         return CITED;  
  20.     }  
  21.   
  22.     public void setCITED(String cITED) {  
  23.         CITED = cITED;  
  24.     }  
  25.   
  26.     public boolean equals(Edge obj) {  
  27.         // TODO Auto-generated method stub  
  28.         String citing = obj.getCITING();  
  29.         String cited = obj.getCITED();  
  30.         if(CITING.equals(citing)&&CITED.equals(cited))  
  31.             return true;  
  32.         else  
  33.             return false;  
  34.           
  35.     }  
  36.       
  37.     public boolean isExistOf(String str){  
  38.         if(str.equals(CITING)||str.equals(CITED))  
  39.             return true;  
  40.         else  
  41.             return false;  
  42.     }  
  43.       
  44.     public boolean isLinked(Edge e){  
  45.         if(e.getCITING().equals(CITING)||e.getCITING().equals(CITED)||  
  46.                 e.getCITED().equals(CITING)||e.getCITED().equals(CITED))  
  47.             return true;  
  48.         else  
  49.             return false;  
  50.     }  
  51.       
  52.     public String toString(){  
  53.         return CITING +" -> "+CITED;  
  54.     }  
  55. }  

【实验代码】

[html] view plain copy
  1. import java.util.ArrayList;  
  2.   
  3. /**  
  4.  * @author Coraline  
  5.  * 算法---寻找最小生成树的欧拉路径,即一笔画问题  
  6.  * 遍历所有的边仅一次,边前后相连  
  7.  * 算法思路:  
  8.  * 第一步--->取list中的第一条边,遍历剩余边,寻找与该边相连接的所有边,add到newList中  
  9.  * 第二步--->取list中的剩余边edge,与newList中的边进行比较  
  10.  *          1-->如果edge与newlist的第一条边相连,直接newList.add(0,edge),在头插入,然后删除list中的edge  
  11.  *          2-->如果edge与newlist的最后一条边相连,直接newList.add(edge),在尾插入,然后删除list中的edge  
  12.  *          3-->如果edge与newlist中间的一条边相连,先把newlist中的那条边移动到尾部,再进行插入删除操作  
  13.  *          4-->如果都不相连,去list的下一条边进行上述操作,直至最后list集合为空为止。  
  14.  */  
  15.   
  16. public class Main {  
  17.   
  18.     public static void main(String[] args) throws Exception {  
  19.           
  20.         //算法测试数据  
  21.         ArrayList<Edge> list = new ArrayList<>();  
  22.         list.add(new Edge("2", "6"));  
  23.         list.add(new Edge("1", "3"));  
  24.         list.add(new Edge("1", "2"));  
  25.         list.add(new Edge("4", "5"));  
  26.         list.add(new Edge("1", "4"));  
  27.         //用于存放重新排序之后的结果集合  
  28.         ArrayList<Edge> newlist = new ArrayList<>();  
  29.           
  30.         Edge e1 = list.get(0);  
  31.         list.remove(0);  
  32.         newlist.add(e1);  
  33.         String citing = e1.getCITING();  
  34.         String cited = e1.getCITED();  
  35.           
  36.         //第一步,选取第一条边,取得所有与该边相连的所有连边,add到newlist  
  37.         for(int i =0;i<list.size();i++){  
  38.             if(list.get(i).isExistOf(citing)){  
  39.                 newlist.add(0,list.get(i));  
  40.                 list.remove(i);  
  41.                 i--;  
  42.             }  
  43.             else if(list.get(i).isExistOf(cited)){  
  44.                 newlist.add(list.get(i));  
  45.                 list.remove(i);  
  46.                 i--;  
  47.             }  
  48.         }  
  49.           
  50.         System.out.println("newlist");  
  51.         for (Edge edge : newlist) {  
  52.             System.out.println(edge.toString());  
  53.         }  
  54.           
  55.         System.out.println("list");  
  56.         for (Edge edge : list) {  
  57.             System.out.println(edge.toString());  
  58.         }  
  59.           
  60.         //第二步,从剩余边中依次进行判断,有序加入到newlist中  
  61.         int point = 0;//设置一个指针,指明当前进行判断的记录  
  62.         while(!list.isEmpty()){  
  63.             e1 = list.get(point);  
  64.             citing = e1.getCITING();  
  65.             cited = e1.getCITED();  
  66.             for(int i =0 ;i<newlist.size();i++){  
  67.                 //如果list(point)与newlist中的记录是相连的  
  68.                 if(newlist.get(i).isExistOf(citing)||newlist.get(i).isExistOf(cited)){  
  69.                     //相连的记录在newlist的头部,直接在头部插入  
  70.                     if(i == 0){  
  71.                         newlist.add(0,e1);  
  72.                         list.remove(point);  
  73.                         point=-1;//注意指针要回归到-1  
  74.                         break;  
  75.                     }  
  76.                     //相连的记录在newlist的尾部,直接在尾部插入  
  77.                     else if(i == newlist.size()-1){  
  78.                         newlist.add(e1);  
  79.                         list.remove(point);  
  80.                         point=-1;//注意指针要回归到-1  
  81.                         break;  
  82.                     }  
  83.                     //相连的记录不在头尾的,先调整顺序至于尾部,再插入  
  84.                     else{  
  85.                         newlist.add(newlist.get(i));  
  86.                         newlist.remove(i);  
  87.                           
  88.                         newlist.add(e1);  
  89.                         list.remove(point);  
  90.                         point=-1;//注意指针要回归到-1  
  91.                         break;  
  92.                     }  
  93.                 }  
  94.             }  
  95.             point++;//指针下移,判断下一个结点  
  96.         }  
  97.           
  98.         System.out.println("newlist");  
  99.         for (Edge edge : newlist) {  
  100.             System.out.println(edge.toString());  
  101.         }  
  102.           
  103.         System.out.println("list");  
  104.         for (Edge edge : list) {  
  105.             System.out.println(edge.toString());  
  106.         }  
  107.           
  108.     }  
  109.   
  110. }  

【实验结果】分了两个步骤的输出,一个是第一步处理后的输出,一个是第二步处理后的输出。

[java] view plain copy
  1. public class BinaryTree {  
  2.   
  3.     private Node root;  
  4.       
  5.     /** 
  6.      *  
  7.      * 内部节点类 
  8.      * @author yhh 
  9.      */  
  10.     private class Node{  
  11.         private Node left;  
  12.         private Node right;  
  13.         private int data;  
  14.         public Node(int data){  
  15.             this.left = null;  
  16.             this.right = null;  
  17.             this.data = data;  
  18.         }  
  19.     }  
  20.       
  21.     public BinaryTree(){  
  22.         root = null;  
  23.     }  
  24.       
  25.     /** 
  26.      * 递归创建二叉树 
  27.      * @param node 
  28.      * @param data 
  29.      */  
  30.     public void buildTree(Node node,int data){  
  31.         if(root == null){  
  32.             root = new Node(data);  
  33.         }else{  
  34.             if(data < node.data){  
  35.                 if(node.left == null){  
  36.                     node.left = new Node(data);  
  37.                 }else{  
  38.                     buildTree(node.left,data);  
  39.                 }  
  40.             }else{  
  41.                 if(node.right == null){  
  42.                     node.right = new Node(data);  
  43.                 }else{  
  44.                     buildTree(node.right,data);  
  45.                 }  
  46.             }  
  47.         }  
  48.     }  
  49.       
  50.     /** 
  51.      * 前序遍历 
  52.      * @param node 
  53.      */  
  54.     public void preOrder(Node node){  
  55.         if(node != null){  
  56.             System.out.println(node.data);  
  57.             preOrder(node.left);  
  58.             preOrder(node.right);  
  59.         }  
  60.     }  
  61.       
  62.     /** 
  63.      * 中序遍历 
  64.      * @param node 
  65.      */  
  66.     public void inOrder(Node node){  
  67.         if(node != null){  
  68.             inOrder(node.left);  
  69.             System.out.println(node.data);  
  70.             inOrder(node.right);  
  71.         }  
  72.     }  
  73.       
  74.     /** 
  75.      * 后序遍历 
  76.      * @param node 
  77.      */  
  78.     public void postOrder(Node node){  
  79.         if(node != null){  
  80.             postOrder(node.left);  
  81.             postOrder(node.right);  
  82.             System.out.println(node.data);  
  83.         }  
  84.     }  
  85.       
  86.     public static void main(String[] args) {  
  87.         int[] a = {2,4,12,45,21,6,111};  
  88.         BinaryTree bTree = new BinaryTree();  
  89.         for (int i = 0; i < a.length; i++) {  
  90.             bTree.buildTree(bTree.root, a[i]);  
  91.         }  
  92.         bTree.preOrder(bTree.root);  
  93.         bTree.inOrder(bTree.root);  
  94.         bTree.postOrder(bTree.root);  
  95.     }  
  96.   
  97. }  

发布了164 篇原创文章 · 获赞 26 · 访问量 18万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章