【數據結構】:二叉樹

二叉樹

二叉樹是一種特殊的樹,每一個節點最多隻能有兩個子節點。html

二叉搜索樹要求:

若它的左子樹不空,則左子樹上全部結點的值均小於它的根結點的值; 若它的右子樹不空,則右子樹上全部結點的值均大於它的根結點的值; 它的左、右子樹也分別爲二叉排序樹
image.pngspa

查找節點

查找節點從根節點開始遍歷查找code

1 、查找值比當前節點值大,則搜索右子樹;htm

二、 查找值等於當前節點值,中止搜索(終止條件);blog

三、查找值小於當前節點值,則搜索左子樹;
image.png排序

插入節點

要插入節點,必須先找到插入的位置。與查找操做類似,因爲二叉搜索樹的特殊性,待插入的節點也須要從根節點開始進行比較,小於根節點則與根節點左子樹比較,反之則與右子樹比較,直到左子樹爲空或右子樹爲空,則插入到相應爲空的位置,在比較的過程當中要注意保存父節點的信息 及 待插入的位置是父節點的左子樹仍是右子樹,才能插入到正確的位置遞歸

public boolean insert(int data) {
        count++;
        //若是第一個節點爲空 設置第一個節點
        Node newNode = new Node(data);
        if (root == null) {
            root = newNode;
            return true;
        }
        Node current = root;
        Node parentNode = null;
 
        while (current != null) {
            parentNode = current;
            //當前值比新插入值大
            if (current.data > data) {
                current = current.leftNode;
                //若左節點爲空 則直接插入便可
                if (current == null) {
                    parentNode.leftNode = newNode;
                    return true;
                }
            } else {
                //當前值小於新插入值
                current = current.rightNode;
                if (current == null) {
                    parentNode.rightNode = newNode;
                    return true;
                }
            }
        }
        return false;
    }

刪除節點

刪除節點相對於查詢和刪除稍微複雜點,主要是刪除時考慮的狀況多一點點。get

  • 刪除節點沒有子節點
    這種的話就直接刪除當前節點就行了,只需將當前節點的父節點指向的節點置爲null便可
//當前節點是否爲左節點
        boolean isLeftNode = false;

// 1 第一種狀況 此節點爲葉子節點
        if (current.leftNode == null && current.rightNode == null) {
            if (current == root) {
                root = null;
            } else if (isLeftNode) {
                //若是要刪除的節點爲父節點的左節點 把父節點的左節點置爲空
                parentNode.leftNode = null;
            } else {
                parentNode.rightNode = null;
            }
            return true;
        }
  • 刪除節點有一個子節點
    刪除有一個子節點的節點,咱們只須要將其父節點本來指向該節點的引用,改成指向該節點的子節點便可。
if (current.leftNode == null && current.rightNode != null) {
            if (root == current) {
                root = current.rightNode;
            } else if (isLeftNode) {
                parentNode.leftNode = current.rightNode;
            } else {
                parentNode.rightNode = current.rightNode;
            }
        } else if (current.leftNode != null && current.rightNode == null) {
            if (root == current) {
                root = current.leftNode;
            } else if (isLeftNode) {
                parentNode.leftNode = current.leftNode;
            } else {
                parentNode.rightNode = current.leftNode;
            }
        }
  • 刪除節點有兩個子節點
    當刪除的節點存在兩個子節點,那麼刪除以後,兩個子節點的位置咱們就沒辦法處理了。既然處理不了,咱們就想到一種辦法,用另外一個節點來代替被刪除的節點,那麼用哪個節點來代替呢?
    這實際上就是要找比刪除節點關鍵值大的節點集合中最小的一個節點,只有這樣代替刪除節點後才能知足二叉搜索樹的特性。
    程序找到刪除節點的右節點,(注意這裏前提是刪除節點存在左右兩個子節點,若是不存在則是刪除狀況的前面兩種),而後轉到該右節點的左子節點,依次順着左子節點找下去,最後一個左子節點便是後繼節點;若是該右節點沒有左子節點,那麼該右節點即是後繼節點。
    二叉樹it

    if(current.leftNode != null && current.rightNode != null){
              //獲取刪除節點的後繼結點
              Node successor = getSuccessor(current);
              if (root == current) {
                  root = successor;
              } else if (isLeftNode) {
                  parentNode.leftNode = successor;
              } else {
                  parentNode.rightNode = successor;
              }
          }
          return false;
    public Node getSuccessor(Node delNode) {
     
          Node successorParent = delNode;
          Node successor = delNode;
          Node current = delNode.rightNode;
          while (current != null) {
              successorParent = successor;
              successor = current;
              current = current.leftNode;
          }
          if (successor != delNode.rightNode) {
              successorParent.leftNode = successor.rightNode;
              successor.leftNode= delNode.leftNode;
          }
          return successor;
      }

前序遍歷

前序遍歷:首先訪問根結點,而後遍歷左子樹,最後遍歷右子樹(根->左->右)io

順序:訪問根節點->前序遍歷左子樹->前序遍歷右子樹

中序遍歷

中序遍歷:首先遍歷左子樹,而後訪問根節點,最後遍歷右子樹(左->根->右)

順序:中序遍歷左子樹->訪問根節點->中序遍歷右子樹

後序遍歷

後序遍歷:首先遍歷左子樹,而後遍歷右子樹,最後訪問根節點(左->右->根)

順序:後序遍歷左子樹->後序遍歷右子樹->訪問根節點

層序遍歷;按層從左到右訪問

前序中序後序
image.png
前序遍歷:根->左->右:12473568
中序遍歷:左->根->右:47215386
後序遍歷:左->右->根:74258631

重構二叉樹

image.png

/**
 * Definition for binary tree
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
public class Solution {
   //前序遍歷序列{1,2,4,7,3,5,6,8}和中序遍歷序列{4,7,2,1,5,3,8,6}
    public TreeNode reConstructBinaryTree(int[] pre, int[] in) {

        int len = pre.length;

        TreeNode root = new TreeNode(pre[0]);
        //說明只剩下一個了,表示葉子節點,遞歸能夠退出了
        if (pre.length == 1) {
            root.left = null;
            root.right = null;
            return root;
        }

        //中間值 在{4,7,2,1,5,3,8,6} 這個中間值第一次應該是3
        int flag = 0;
        for (int i = 0; i < len; i++) {
            //在中序中找到
            if (pre[0] == in[i]) {
                flag = i;
                break;
            }
        }
        if (flag > 0) {
            //左子樹的先序
            int[] leftPre = new int[flag];
            //左子樹的中序
            int[] leftIn = new int[flag];
            for (int j = 0; j < flag; j++) {
                leftPre[j] = pre[j + 1];
            }
            for (int j = 0; j < flag; j++) {
                leftIn[j] = in[j];
            }
            //左子樹遞歸
            root.left = reConstructBinaryTree(leftPre, leftIn);
        } else {
            root.left = null;
        }
        if (pre.length - flag - 1 > 0) {
            //右子樹的先序,長度爲 總-根-左子樹
            int[] rightPre = new int[pre.length - 1 - flag];
            //右子樹的中序
            int[] rightIn = new int[pre.length - 1 - flag];

            for (int j = flag + 1; j < len; j++) {
                //右子樹中序,爲何要j-flag-1呢 由於個人rightIn要從0開始 而j是k+1開始的 ,因此很尷尬,只能用j-flag-1
                rightIn[j - flag - 1] = in[j];

                rightPre[j - flag - 1] = pre[j];
            }

            root.right = reConstructBinaryTree(rightPre, rightIn);
        } else {
            root.right = null;
        }

        return root;

    }
 
}
相關文章
相關標籤/搜索