1. 程式人生 > >樹和二叉樹的轉換,森林和二叉樹的轉化

樹和二叉樹的轉換,森林和二叉樹的轉化

樹具有二叉連結串列的形式,可以將其他形式的樹轉化為二叉連結串列的形式。並且森林合併樹也是基於二叉連結串列形式的樹進行合併的。下面給出程式碼:

/**  
* @Title: CTree.java
* @Package tree
* @Description: TODO
* @author Xie Huafeng
* @date 2017年11月14日
* @version V1.0  
*/

package tree;

import java.util.ArrayList;
import java.util.List;

/**
* @ClassName: CTree
* @author Xie Huafeng
* @date
2017年11月14日 * @Description: TODO */
public class TreeConvertion { /** * @Title: PTreeToCSTree * @param @param csTree * @param @param pTree * @return void * @throws * @Description: 孩子表示法轉為孩子兄弟表示法 */ public <T> void CTreeToCSTree(CTree<T> cTree, CSTree<T> csTree) { if
(cTree.getRootNode() == null) { return; } csTree.setRootNode(toCSTreeNode(cTree.getRootNode(), null)); System.out.println(csTree); } /** * @Title: toCSTreeNode * @param @param cTreeNode * @param @param list * @param @return * @return
CSTree<T>.Node * @throws * @Description: 轉換方法 * * 函式使用遞迴方式寫的。 * 對於每一各節點: * 它的孩子連結串列的第一個資料是它的左子節點, * 與它同屬一個孩子連結串列的下一個節點為右子節點。 * 根據這一邏輯進行每一個節點進行處理。 */
public <T> CSTree<T>.Node toCSTreeNode(CTree<T>.Node cTreeNode, List<CTree<T>.Node> list) { CSTree<T>.Node node = new CSTree<T>().new Node(cTreeNode.getData()); if (cTreeNode.getChildren() != null && cTreeNode.getChildren().size() > 0) { node.setFirstNode(toCSTreeNode(cTreeNode.getChildren().get(0), cTreeNode.getChildren())); } if (list != null) { int index = list.indexOf(cTreeNode); if (index < list.size() - 1) { node.setNextSibling(toCSTreeNode(list.get(index + 1), list)); } } return node; } /** * @Title: convertForeastToCSTree * @param @param foreast * @param @param csTree * @return void * @throws * @Description: 森林轉化為樹,森林使用二叉連結串列形式的樹的集合表示 * * 兩顆二叉連結串列形式的樹合為一顆,即將後面一個作為前面一個樹的右子樹。 * 按照這一邏輯,從尾至前遍歷,最終合為一顆 * * 而樹轉為森林則將根節點的右節點分開則行,不提供程式碼 * * 森林的先序遍歷和中序遍歷等同於對應的二叉樹的先序和中序遍歷 * 樹的遍歷先序遍歷等於對應二叉樹的先序遍歷,後續遍歷則不相同 */ public <T> CSTree<T> convertForeastToCSTree(List<CSTree<T>> foreast) { for (int i = foreast.size() - 1; i >= 0; i--) { CSTree<T> csTreeBack = foreast.get(i); if ( i - 1 >= 0) { CSTree<T> csTreeHead = foreast.get(i-1); csTreeHead.getRootNode().setNextSibling(csTreeBack.getRootNode()); } } if (foreast.size() > 0) { return foreast.get(0); } return null; } /** * 測試程式碼 */ public static void main(String[] args) { CTree<Integer> cTree = new CTree<Integer>(); CTree<Integer>.Node node = new CTree<Integer>().new Node(0); cTree.setRootNode(node); List<CTree<Integer>.Node> list = new ArrayList<>(); for(int i = 1; i < 6; i++) { CTree<Integer>.Node tempNode = new CTree<Integer>().new Node(i); list.add(tempNode); } List<CTree<Integer>.Node> list2 = new ArrayList<>(); for(int i = 10; i < 16; i++) { CTree<Integer>.Node tempNode = new CTree<Integer>().new Node(i); list2.add(tempNode); } list.get(2).setChildren(list2); node.setChildren(list); CSTree<Integer> csTree = new CSTree<Integer>(); CSTree<Integer> csTree2 = new CSTree<Integer>(); TreeConvertion convert = new TreeConvertion(); convert.CTreeToCSTree(cTree, csTree); convert.CTreeToCSTree(cTree, csTree2); List<CSTree<Integer>> treeList = new ArrayList<>(); treeList.add(csTree2); //treeList.add(csTree); CSTree<Integer> csTree3 = convert.convertForeastToCSTree(treeList); System.out.println(csTree3); } }
/**
* @ClassName: Tree2
* @author xhf
* @date 2017年11月5日
* @param <T>
* @Description: 孩子表示法
* 
* 每個節點有多棵子樹,則用多重連結串列,即每個節點有多個指標域,每個指標域指向一棵子樹的根節點。
* 
* 對於子節點個數,指標域的大小一種方式是根據樹的度來確定,度是子節點個數的最大值,所以部分子節點為空。
*   n個度為k的節點有 n(k-1)+1個空鏈域
* 另一種方式是根據每一個節點的子節點個數來確定指標域的大小,這樣不會多出空值得指標域
* 
*/
class CTree<T> {

    CTree() {

    }

    /**
     * 樹的根節點
     */
    private Node rootNode;

    public Node getRootNode() {
        return rootNode;
    }

    public void setRootNode(Node rootNode) {
        this.rootNode = rootNode;
    }

    class Node {
        Node(T data) {
            this.data = data;
        }
        /**
         * 節點的資料
         */
        private T data;

        /**
         * 子節點的引用集合
         */
        private List<Node> children = new ArrayList<>();  

        public T getData() {
            return data;
        }

        public void setData(T data) {
            this.data = data;
        }

        public List<Node> getChildren() {
            return children;
        }

        public void setChildren(List<Node> children) {
            this.children = children;
        }       
    }
}
/**
 * 孩子兄弟表示法,也叫二叉樹表示法,二叉連結串列表示法
 * 
 * 將樹轉變為二叉連結串列
 * 左連結域指向第一個子節點,右連結域指向下一個兄弟節點 
 */
class CSTree<T> {
    /**
     * 根節點
     */
    private Node rootNode;

    public Node getRootNode() {
        return rootNode;
    }

    public void setRootNode(Node rootNode) {
        this.rootNode = rootNode;
    }

    class Node {
        Node(T data) {
            this.data = data;
        }

        /**
        * 資料
        */
        private T data;

        /**
         * 第一個子節點
         */
        private Node firstNode;

        /**
         * 下一個兄弟節點
         */
        private Node nextSibling;

        public T getData() {
            return data;
        }

        public void setData(T data) {
            this.data = data;
        }

        public Node getFirstNode() {
            return firstNode;
        }

        public void setFirstNode(Node firstNode) {
            this.firstNode = firstNode;
        }

        public Node getNextSibling() {
            return nextSibling;
        }

        public void setNextSibling(Node nextSibling) {
            this.nextSibling = nextSibling;
        }   
    }
}