樹和二叉樹的轉換,森林和二叉樹的轉化
阿新 • • 發佈:2019-01-27
樹具有二叉連結串列的形式,可以將其他形式的樹轉化為二叉連結串列的形式。並且森林合併樹也是基於二叉連結串列形式的樹進行合併的。下面給出程式碼:
/**
* @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;
}
}
}