1. 程式人生 > >資料結構3—java 樹 雙親表示法

資料結構3—java 樹 雙親表示法

假設以一組連續空間儲存樹的節點,同時在每個節點中,附設一個指示器指示其雙親結點到連結串列中的 的位置,也就是說,每個結點 知道自己是誰外,還知道雙親在哪裡。
雙親表示法根據結點的parent指標很容易找到它的雙親結點,所以時間複雜度為O[1],知道parent為-1,時,表示找到了根節點。可如果要找結點的孩子是什麼,需要遍歷整個結構才行。

一、定義介面(為什麼要用介面~)

public interface IBinaryTree<E> {

    /**
     * 新增子節點
     * @param data  資料域
     * @param parent  雙親節點E
     */
public void addNode(E data,MNode<E>parent); /** * 獲取根節點 * @return */ public MNode<E> getRoot(); /** * 獲取雙親結點 * @param mNode * @return */ public MNode<E>getParent(MNode<E>mNode); public List<MNode<E>>getChild(MNode<E>mNode); /** * 獲取全部節點 * @param
mNode * @return */
public List<MNode<E>>getTreeNode(); /** * 獲取指定結點的位置SDS * @param mNode * @return */ public int getPos(MNode<E>mNode); public int getDeepth(); }

二、自定義Node類

/**
 * 結點結構
 * @author isc
 *
 * @param <T>
 */
public
class MNode<E> { private E data;//資料域 private int parent;//雙親 public E getData() { return data; } public void setData(E data) { this.data = data; } public int getParent() { return parent; } public void setParent(int parent) { this.parent = parent; } public MNode(E data,int parent){ this.data=data; this.parent=parent; } public MNode(E data) { this.data=data; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((data == null) ? 0 : data.hashCode()); result = prime * result + parent; return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; MNode other = (MNode) obj; if (data == null) { if (other.data != null) return false; } else if (!data.equals(other.data)) return false; if (parent != other.parent) return false; return true; } @Override public String toString() { return "MNode [data=" + data + ", parent=" + parent + "]"; } }

三、定義樹結構

public class MyTree<E> implements IBinaryTree<E>{

    int MAX_TREE_SIZE =100;
    MNode<E>[] nodes; //定義結點陣列

    int treeSize;
    int nodeNums=0;

    /**
     * 指定根節點建立樹
     * @param data
     */
    public MyTree(E data){

        treeSize = MAX_TREE_SIZE;
        nodes = new MNode[treeSize];  //
        nodes[0] = new MNode<E>(data,-1);//定義根節點
        nodeNums++;
    }

    /**
     * 指定根節點\指定結點數    建立樹
     * @param data
     */
    public MyTree(E data,int treeSize){

        this.treeSize = treeSize;
        nodes = new MNode[treeSize];
        nodes[0] = new MNode<E>(data,-1);//定義根節點
        nodeNums++;
    }

    /**
     * 為指定結點新增子節點
     */
    @Override
    public void addNode(E data, MNode<E> parent) {

        for(int i=0;i<treeSize;i++){
            if(nodes[i]==null){
                nodes[i]=new MNode<E>(data, getPos(parent));//指定值和雙親節點
                nodeNums++;
                return;
            }
        }

    }

    @Override
    public MNode<E> getRoot() {
        if(nodeNums>0){
            return nodes[0];
        }
        return null;
    }

    @Override
    public MNode<E> getParent(MNode<E> mNode) {
        return nodes[mNode.getParent()];
    }

    //返回指定節點(非葉節點)的所有子節點
    @Override
    public List<MNode<E>> getChild(MNode<E> parent) {
        List<MNode<E>> list = new ArrayList<MNode<E>>() ;
//      for(int i=0;i<treeSize;i++){
//          if(nodes[i]!=null&&nodes[nodes[i].getParent()].equals(mNode)){
//              list.add(nodes[i]);
//          }
//      }
        for (int i = 0; i < treeSize; i++) {
            if (nodes[i] != null && nodes[i].getParent() == getPos(parent)) {
                list.add(nodes[i]);
            }
        }
        return list;
    }


    @Override
    public int getPos(MNode<E> mNode) {

        for(int i=0;i<treeSize;i++){
            if(nodes[i].equals(mNode)){
                return i;
            }
        }

        return -1;
    }
    @Override
    public int getDeepth() {
        // 用於記錄結點的最大深度
        int max = 0;
        for (int i = 0; i < treeSize && nodes[i] != null; i++) {
            // 初始化本結點的深度
            int def = 1;
            // m記錄當前結點的父結點的位置
            int m = nodes[i].getParent();
            // 如果其父結點存在
            while (m != -1 && nodes[m] != null) {
                // 向上繼續搜尋父結點
                m = nodes[m].getParent();
                def++;
            }
            if (max < def) {
                max = def;
            }
        }
        // 返回最大深度
        return max;        
    }

    @Override
    public List<MNode<E>> getTreeNode() {
        List<MNode<E>> list = new ArrayList<MNode<E>>() ;
        for(int i=0;i<treeSize;i++){
            if(nodes[i]!=null){
                list.add(nodes[i]);
            }
        }       
        return list;
    }
}

四、測試類

public class TestClass {

    public static void main(String[] args){
        TestClass ts = new TestClass();
        ts.testTree();
    }

    public void testTree(){
        Student data = new Student();
        data.setId(1);
        data.setName("JY");
        data.setAge(22);

        MyTree<Student> pTree = new MyTree<Student>(data);//利用值建立樹

        // 拿到父結點
        MNode<Student> parent = new MNode<Student>(data);
        parent.setParent(-1);

        // 新增子結點
        Student data2 = new Student();
        data2.setId(2);
        data2.setName("LYH");
        data2.setAge(23);        
        pTree.addNode(data2, parent);

        Student data3 = new Student();
        data3.setId(3);
        data3.setName("YC");
        data3.setAge(23);        
        pTree.addNode(data3, parent);

        MNode<Student> parent2 = new MNode<Student>(data2);
        Student data4 = new Student();
        data4.setId(4);
        data4.setName("LAF");
        data4.setAge(23);        
        pTree.addNode(data4, parent2);

        Student data5 = new Student();
        data5.setId(5);
        data5.setName("LAF3");
        data5.setAge(23);        
        pTree.addNode(data5, parent2);

        Student data6 = new Student();
        data6.setId(6);
        data6.setName("LAF3");
        data6.setAge(23);        
        pTree.addNode(data6, parent2);



        // 遍歷所有結點
        List<MNode<Student>> children = pTree.getTreeNode();
        System.out.println("樹的全部節點為:");
        for(MNode<Student> node : children){
             System.out.println(node.toString());
        }

        System.out.println("樹深為:"+pTree.getDeepth());

        List<MNode<Student>> children2 = pTree.getChild(parent2);
        System.out.println("節點為"+pTree.getPos(parent2)+"的子節點為:");

        for (MNode<Student> node : children2) {
            System.out.println(node.toString());
        }
    }
}

五、測試結果

樹的全部節點為:
MNode [data=Student [id=1, name=JY, age=22], parent=-1]
MNode [data=Student [id=2, name=LYH, age=23], parent=0]
MNode [data=Student [id=3, name=YC, age=23], parent=0]
MNode [data=Student [id=4, name=LAF, age=23], parent=1]
MNode [data=Student [id=5, name=LAF3, age=23], parent=1]
MNode [data=Student [id=6, name=LAF3, age=23], parent=1]
樹深為:3
節點為1的子節點為:
MNode [data=Student [id=4, name=LAF, age=23], parent=1]
MNode [data=Student [id=5, name=LAF3, age=23], parent=1]
MNode [data=Student [id=6, name=LAF3, age=23], parent=1]