尋找最小生成樹的歐拉路徑,即一筆畫問題



【程序背景】最近在做子圖匹配的實驗,對查詢圖需要進行預處理,得到最小生成樹,然後進行後續的子圖匹配工作,由於匹配過程是按照順序依次遍歷匹配的,當時程序就卡在尋找一條順序相連的最小生成樹的歐拉路徑問題上了,查了很多關於歐拉路徑的解決方案,覺得過於複雜,乾脆最後自己寫了一個小程序,解決了。

【問題說明】輸入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萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章