算法筆記-二叉樹(1)

1、基本概念:

1) 有很多種,每個節點最多隻能有兩個子節點的一種形式稱爲二叉樹。

2)二叉樹的子節點分爲左節點和右節點

3)如果該二叉樹的所有子節點都在最後一層,並且點總數= 2^n -1 , n 爲層數,則我們稱爲滿二叉樹。

4)果該二叉樹的所有葉子節點都在最後一層或者倒數第二層,而且最後一層的葉子節點在左邊連續,倒數第二層的葉子節點在右邊連續,我們稱爲完全二叉樹。

樹的常用術語(結合示意圖理解):

1)節點

2)根節點

3)父節點

4)子節

5)子節點 (沒有子節點的節點)

6)點的權(節點值)

7)(root節點找到該節點的路線)

8)

9)子樹

10)樹的高度(最大層數)

11):多顆子樹構成森林

 

 

2.二叉樹的遍歷:

前序遍歷: 先輸出父節點,再遍歷左子樹和右子樹

序遍歷: 先遍歷左子樹,再輸出父節點,再遍歷右子樹

序遍歷: 先遍歷左子樹,再遍歷右子樹,最後輸出父節點

小結: 看輸出父節點的順序,就確定是前序,中序還是後序

實際上,二叉樹的前、中、後序遍歷就是一個遞歸的過程

3.代碼實現:

//先創建Node 節點
class Node{
    private int no;
    private String name;
    private Node left;//默認null
    private Node right;//默認null
    public Node(int no , String name){
        this.no = no;
        this.name = name;
    }

    public int getNo() {
        return no;
    }

    public void setNo(int no) {
        this.no = no;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Node getLeft() {
        return left;
    }

    public void setLeft(Node left) {
        this.left = left;
    }

    public Node getRight() {
        return right;
    }

    public void setRight(Node right) {
        this.right = right;
    }
    @Override
    public String toString() {
        return "Node [no=" + no + ", name=" + name + "]";
    }

    //遞歸刪除結點
    //1.如果刪除的節點是葉子節點,則刪除該結點
    //2.如果刪除的節點是非葉子節點,則刪除該子樹
    public void delNode(int no){

        //思路
		/*
		 * 	1. 因爲我們的二叉樹是單向的,所以我們是判斷當前結點的子結點是否需要刪除結點,而不能去判斷當前這個結點是不是需要刪除結點.
			2. 如果當前結點的左子結點不爲空,並且左子結點 就是要刪除結點,就將this.left = null; 並且就返回(結束遞歸刪除)
			3. 如果當前結點的右子結點不爲空,並且右子結點 就是要刪除結點,就將this.right= null ;並且就返回(結束遞歸刪除)
			4. 如果第2和第3步沒有刪除結點,那麼我們就需要向左子樹進行遞歸刪除
			5.  如果第4步也沒有刪除結點,則應當向右子樹進行遞歸刪除.

		 */
        //2. 如果當前結點的左子結點不爲空,並且左子結點 就是要刪除結點,就將this.left = null; 並且就返回(結束遞歸刪除)
        if(this.left != null && this.left.no == no){
            this.left = null;
            return;
        }
        //3.如果當前結點的右子結點不爲空,並且右子結點 就是要刪除結點,就將this.right= null ;並且就返回(結束遞歸刪除)
        if(this.right != null && this.right.no == no){
            this.right = null;
            return;
        }
        //4.我們就需要向左子樹進行遞歸刪除
        if(this.left != null){
            this.left.delNode(no);
        }
        //5.則應當向右子樹進行遞歸刪除
        if(this.right != null){
            this.right.delNode(no);
        }

    }




    //編寫前序遍歷的方法
    public void preOrder(){
        System.out.println(this);
        //遞歸向左子樹前序遍歷
        if(this.left !=null){
            this.left.preOrder();
        }
        //遞歸向右子樹前序遍歷
        if(this.right !=null){
            this.right.preOrder();
        }
    }
    //中序遍歷
    public void infixOrder(){
        //遞歸向左子樹中序遍歷
        if(this.left !=null){
            this.left.infixOrder();
        }
        //輸出父節點
        System.out.println(this);
        //遞歸向右子樹中序遍歷
        if(this.right !=null){
            this.right.infixOrder();
        }
    }
    //後序遍歷
    public void postOrder(){
        //遞歸向左子樹後序遍歷
        if(this.left !=null){
            this.left.postOrder();
        }
        //遞歸向右子樹中序遍歷
        if(this.right !=null){
            this.right.postOrder();
        }
        //輸出父節點
        System.out.println(this);
    }

    //前序遍歷查找
    public Node preSearch(int no){
        System.out.println("進入前序遍歷");
        //比較當前結點是不是
        if(this.no == no){
            return this;
        }
        //1.則判斷當前結點的左子節點是否爲空,如果不爲空,則遞歸前序查找
        //2.如果左遞歸前序查找,找到結點,則返回
        Node resNode = null;
        if(this.left !=null){
            resNode = this.left.preSearch(no);
        }
        //說明找到了
        if(resNode != null){
            return resNode;
        }
        //1.左遞歸前序查找,找到結點,則返回,否繼續判斷,
        //2.當前的結點的右子節點是否爲空,如果不空,則繼續向右遞歸前序查找
        if(this.right !=null){
            resNode = this.right.preSearch(no);
        }
        return resNode;
    }

    //中序遍歷查找
    public Node infixSearch(int no){
        //1.則判斷當前結點的左子節點是否爲空,如果不爲空,則遞歸前序查找
        //2.如果左遞歸前序查找,找到結點,則返回
        Node resNode = null;
        if(this.left !=null){
            resNode = this.left.infixSearch(no);
        }
        //說明找到了
        if(resNode != null){
            return resNode;
        }
        System.out.println("進入中序遍歷");
        //比較當前結點是不是
        if(this.no == no){
            return this;
        }
        //1.左遞歸前序查找,找到結點,則返回,否繼續判斷,
        //2.當前的結點的右子節點是否爲空,如果不空,則繼續向右遞歸前序查找
        if(this.right !=null){
            resNode = this.right.infixSearch(no);
        }
        return resNode;
    }

    //後序遍歷查找
    public Node postSearch(int no){
        //1.則判斷當前結點的左子節點是否爲空,如果不爲空,則遞歸前序查找
        //2.如果左遞歸前序查找,找到結點,則返回
        Node resNode = null;
        if(this.left !=null){
            resNode = this.left.postSearch(no);
        }
        //說明找到了
        if(resNode != null){
            return resNode;
        }
        //1.左遞歸前序查找,找到結點,則返回,否繼續判斷,
        //2.當前的結點的右子節點是否爲空,如果不空,則繼續向右遞歸前序查找
        if(this.right !=null){
            resNode = this.right.postSearch(no);
        }
        System.out.println("進入後序遍歷");
        //比較當前結點是不是
        if(this.no == no){
            return this;
        }
        return resNode;
    }

}
 
//創建BinaryTree二叉樹
class BinaryTree{
    private  Node root;
    public void setRoot(Node root){
        this.root = root;
    }


    //刪除結點
    public void delNode(int no){
        if(root != null){
            //如果只有一個root結點, 這裏立即判斷root是不是就是要刪除結點
            if(root.getNo() == no){
                root = null;
            }else{
                //遞歸刪除
                root.delNode(no);
            }
        }else{
            System.out.println("空樹,不能刪除~");
        }
    }

    //前序遍歷
    public void preOrder(){
        if(this.root != null){
            this.root.preOrder();
        }else{
            System.out.println("二叉樹爲空,無法遍歷");

        }
    }

    //中序遍歷
    public void infixOrder(){
        if(this.root != null){
            this.root.infixOrder();
        }else{
            System.out.println("二叉樹爲空,無法遍歷");

        }
    }

    //後序遍歷
    public void postOrder(){
        if(this.root != null){
            this.root.postOrder();
        }else{
            System.out.println("二叉樹爲空,無法遍歷");

        }
    }

    //前序查找
    public Node preSearch(int no){
        if(root != null){
            return root.preSearch(no);
        }else{
            return null;
        }
    }

    //中序查找
    public Node infixSearch(int no){
        if(root != null){
            return root.infixSearch(no);
        }else{
            return null;
        }
    }

    //後序查找
    public Node postSearch(int no){
        if(root != null){
            return root.postSearch(no);
        }else{
            return null;
        }
    }
}
//測試
public static void main(String[] args) {
        //創建一個二叉樹
        BinaryTree binaryTree = new BinaryTree();
        //
        Node root = new Node(1,"趙");
        Node node2 = new Node(2,"錢");
        Node node3 = new Node(3,"孫");
        Node node4 = new Node(4,"李");
        Node node5 = new Node(5,"王");
        Node node6 = new Node(6,"王");

        Node node7 = new Node(7,"王");

        //我們先手動創建該二叉樹,後面我們學習遞歸的方式創建二叉樹
        root.setLeft(node2);
        root.setRight(node3);
        node2.setRight(node5);
        node2.setLeft(node4);
        node3.setRight(node7);
        node3.setLeft(node6);
        binaryTree.setRoot(root);
        //System.out.println("前序遍歷"); // 1,2,3,5,4
       // binaryTree.preOrder();
        System.out.println("中序遍歷"); // 2,1,5,3,4
        binaryTree.infixOrder();
        //System.out.println("後序遍歷"); // 2,5,4,3,1
        //binaryTree.postOrder();
        //測試刪除
        //System.out.println("刪除前,前序遍歷");
        //binaryTree.preOrder();
       // binaryTree.delNode(5);
       // System.out.println("刪除後,前序遍歷");
       // binaryTree.preOrder();//1,2,3,4
    }

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章