一个别人问我的多叉树的问题....

来源:互联网 发布:java api有手机版的吗 编辑:程序博客网 时间:2024/04/28 11:53
问题描述:

这是她的项目里的一个需求好像要做什么聚类的,但是我不太懂,只是用我的思路解决了问题...

输入:

一个字符串数组,数组中的每个字符串的格式为A B,AB中间有一个空格,A和B是源IP和目的IP.

输出:

输出所有的A B B C C D形式的串,即数组中的字符串的后半部分和另一个字符串的前半部分相同的话就要成一条链,但是扫描到一个字符串的时候不用考虑他前面串是否满足该特性.

我的思路:

这个问题可以用多叉树来做,为每一个根结点创建一个树(用哈希表防止重复建树和关键节点,这个很重要),读入数组后根据条件建立一个多叉树,然后用深度优先搜索遍历并保存每一条路径,就是要的结果,时间复杂度为O(n2),应该还有更好的方案,但是我智商捉急,只能想到O(n2)复杂度的算法,另外二叉树的深度优先非递归写法在保存路径时节点回退我没有想到解决方案,就改写成了递归方法,否则可以用一个栈来做.

借用数据结构:

HashMap:根据字符串的值来当哈希键值,用来存储一个串的节点是否被访问过,以防止多建了树。

Stack:非递归深搜二叉树的时候要用到.

  1 package help.myz;  2  3 import java.util.ArrayList;  4 import java.util.HashMap;  5 import java.util.Stack;  6   7   8   9  10 class MultiTreeNode 11 {//多叉树 12     //MultiTreeNode parent = null; //父节点,为了扫描树深搜回退节点的去除字符串的时候用 13     String str = null;//当前字符串的值 14     //boolean isIntree = false; //标志该节点是否已经被填入到一颗树中,如果添加到过就不用添加了 15      16     ArrayList<MultiTreeNode> childList = new ArrayList<>();//所有的孩子节点 17     public MultiTreeNode(String str) { 18         // TODO Auto-generated constructor stub 19         this.str = str; 20     } 21 } 22  23 public class MultiTree { 24      25     ArrayList<MultiTreeNode> treeList = new ArrayList<>(); //存储所有的树 26     HashMap<String, MultiTreeNode> treeMap = new HashMap<>(); //记录字符串是否被扫描过 27      28     ArrayList<String> tmpStrList = new ArrayList<>(); //存储扫描树的某条路径时过程中的中间串 29      30     public void treeBuild(ArrayList<String> strlist) 31     { 32         int index = 0,i; 33         for(i = 0; i < strlist.size(); i++) 34         { 35             String currentString = strlist.get(i); 36             MultiTreeNode currentNode = treeMap.get(currentString); 37              38             if(currentNode == null) 39             { 40                 //System.out.print("build a tree"); 41                 currentNode = new MultiTreeNode(currentString);//创建新的节点 42                 treeMap.put(currentString, currentNode); //把当前节点加入到哈希表 43                 treeList.add(currentNode); //让该节点重新创建一颗树 44             } 45              46             /*更新树,查找当前节点后面的节点是否有其后续链*/ 47             index  = i + 1; 48             for(; index < strlist.size(); index++) 49             { 50                 String strBack = currentString.split(" +")[1];//获取字符串的后半部分 51                 String strForward = strlist.get(index).split(" +")[0];//获取字符串的前半部分 52                  53                 if(strBack.equals(strForward)) 54                 {//该节点满足条件AB BC 55                     MultiTreeNode childNode = new MultiTreeNode(strlist.get(index));//创建新字符串的孩子节点 56                     treeMap.put(strlist.get(index), childNode);//将扫描到的当前孩子节点也加入哈希表,防止二次建树 57                      58                     currentNode.childList.add(childNode);//给当前树的当前节点添加孩子节点 59                 } 60             } 61         } 62      63     } 64      65     /* 66      *递归深度优先遍历树,并生成路径  67      */ 68     public void treeScan_ReCursion(MultiTreeNode root) 69     { 70         this.tmpStrList.add(root.str);//将当前字符串加入临时存储表 71          72         if(root.childList.size() == 0) 73         {//当前节点为叶子节点,扫描完一条路径,保存该路径 74             ArrayList<String> pathStrList = new ArrayList<>(this.tmpStrList); 75              76             PrintPathList(pathStrList); 77             //PrintPathList(tmpStrList); 78         } 79          80         for(int i = 0; i < root.childList.size(); i++) 81         {//递归扫描所有孩子节点 82             treeScan_ReCursion(root.childList.get(i)); 83         } 84          85         this.tmpStrList.remove(this.tmpStrList.size() - 1);//节点回退上一层的时,回退一个字符串 86     } 87      88     /* 89      * 非递归深度优先遍历当前树,并生成路径 90      */ 91     /* 92     public void treeScan(MultiTreeNode root) 93     { 94         ArrayList<String> tmpList = new ArrayList<>();//存储深搜的过程值 95          96         Stack<MultiTreeNode> treeStack = new Stack<>(); 97          98         treeStack.add(root); 99         100         while(!treeStack.isEmpty())101         {//当前树未扫描完102             MultiTreeNode currentNode = treeStack.pop(); //获取栈顶值103             int nodeChildNum = currentNode.childList.size();104             tmpList.add(currentNode.str);//将当前的字符串加入中间结果105             106             if(nodeChildNum == 0)107             {//当前节点为叶子节点108                 ArrayList<String> currentStrList = new ArrayList<>(tmpList);//存储当前扫描完的一条路径的串109                 //System.out.println(currentStrList);//打印当前链 110                 PrintPathList(currentStrList);111                 tmpList.remove(tmpList.size() - 1); //回退一个字符串,为了继续搜索其他路径112             }113             114             115             if(currentNode.parent != null)116             {//父节点不为空117                 ArrayList<MultiTreeNode> brotherList = currentNode.parent.childList;//所有的兄弟节点链表118                 MultiTreeNode finalBrotherNode = brotherList.get(brotherList.size() - 1);//获取当前节点的最后一个兄弟节点119                 if(currentNode == finalBrotherNode)120                 {//访问完当前层的最后一个节点,还需要回退一个节点121                     tmpList.remove(tmpList.size() - 1);122                 }123             }124             125             126             for(int i = nodeChildNum - 1; i >= 0; i--)127             {128                 treeStack.push(currentNode.childList.get(i)); //将其他孩子按照从后到前的顺序入栈129             }130             131         }132     }133     */134     135     /*136      *扫描所有树 137      */138     public void treeListScan()139     {//将所有树扫描出来140         for(int i = 0; i < treeList.size(); i++)141         {142             MultiTreeNode treeRoot = treeList.get(i); //获取当前树的根143             //treeScan(treeRoot);144             treeScan_ReCursion(treeRoot);145         }146     }147     148     public void PrintPathList(ArrayList<String> pathStrList)149     {150         for(int i = 0; i < pathStrList.size(); i++)151         {152             System.out.print(pathStrList.get(i) + "-->");153         }154         155         System.out.println();156         System.out.println("--------------------------");157     }158     159     public static void main(String[] args) {160         // TODO Auto-generated method stub161         MultiTree multiTree = new MultiTree();162         String strArray[] = {163                 "2886758962 2886758450",164                 "2886758450 2886759119",165                 "2886758962 2886758607",166                 "2886758962 2886758740",167                 "2886758450 2886759080",168                 "2886758962 2886758500",169                 "2886758607 2886758500",170                 "2886758962 2886758594",171                 "2886758450 2886758594",172                 "2886758450 2886759081",173                 "2886758962 2886759081",174                 "2886758450 2886758860",175                 "2886758450 3290778526",176                 "2886758607 3290778526",177                 "2886759060 3290778526",178                 "2886759119 3290778526",179                 "2886758450 2886758549",180                 "2886758500 2886758420",181                 "2886758962 2886758706",182                 "2886758420 2886758706",183                 "2886758594 2886758706",184                 "2886758500 2886758706",185                 "2886758740 2886758706"186                 };187         188         String strArray2[] = {189                 "A B",190                 "B C",191                 "C D",192                 "A E",193                 "B F",194                 "D K"195         };196         197         ArrayList<String> strlist = new ArrayList<>();198         199         for(int i = 0; i < strArray.length; i++)200         {201             strlist.add(strArray[i]);202         }203         204         multiTree.treeBuild(strlist);205         //System.out.println("treeNum is " + multiTree.treeList.size());206         multiTree.treeListScan();207     }208 209 }

 

0 0