バイナリツリー紙面の質問を示しています

まず、バイナリツリー&

ツリーは、ノードおよびエッジ、記憶素子のセットから構成されています。ルートノードポイント、親と子ノードの概念。

図:ツリー深さ= 4;図5は、ルートノードである; 8の関係図3は、同じ親子関係です。

16535373-1a8e4470c9e3c286.png

バイナリバイナリツリーは、その後、「バイナリ」(バイナリ)を追加し、それがツリーに区別するための手段。各サブノードは最大で2(子)、左チャイルド&右の子を持っています。多くの場合、バイナリツリーのようなバイナリツリーの使用は、算術式です。

図:左ノードは1/8であり; 2/3右ノードです。

16535373-76318b6ec690d275.png

第二に、二分探索木BST

名前が示すように、バイナリツリーは、制限検索を追加しました。その要件:各ノードは、右サブツリー要素よりも小さい、その左サブツリー要素よりも大きいです。

図:任意のノード内の各ノードは、その左の部分木より大きく、小さいその右サブツリーのいずれよりもノード

16535373-5ae91c052df75d96.png

次のようにJavaのコードは次のとおりです。

public class BinarySearchTree {
    /**
     * 根节点
     */
    public static TreeNode root;

    public BinarySearchTree() {
        this.root = null;
    }

    /**
     * 查找
     *      树深(N) O(lgN)
     *      1\. 从root节点开始
     *      2\. 比当前节点值小,则找其左节点
     *      3\. 比当前节点值大,则找其右节点
     *      4\. 与当前节点值相等,查找到返回TRUE
     *      5\. 查找完毕未找到,
     * @param key
     * @return
     */
    public TreeNode search (int key) {
        TreeNode current = root;
        while (current != null
                && key != current.value) {
            if (key < current.value )
                current = current.left;
            else
                current = current.right;
        }
        return current;
    }

    /**
     * 插入
     *      1\. 从root节点开始
     *      2\. 如果root为空,root为插入值
     *      循环:
     *      3\. 如果当前节点值大于插入值,找左节点
     *      4\. 如果当前节点值小于插入值,找右节点
     * @param key
     * @return
     */
    public TreeNode insert (int key) {
        // 新增节点
        TreeNode newNode = new TreeNode(key);
        // 当前节点
        TreeNode current = root;
        // 上个节点
        TreeNode parent  = null;
        // 如果根节点为空
        if (current == null) {
            root = newNode;
            return newNode;
        }
        while (true) {
            parent = current;
            if (key < current.value) {
                current = current.left;
                if (current == null) {
                    parent.left = newNode;
                    return newNode;
                }
            } else {
                current = current.right;
                if (current == null) {
                    parent.right = newNode;
                    return newNode;
                }
            }
        }
    }

    /**
     * 删除节点
     *      1.找到删除节点
     *      2.如果删除节点左节点为空 , 右节点也为空;
     *      3.如果删除节点只有一个子节点 右节点 或者 左节点
     *      4.如果删除节点左右子节点都不为空
     * @param key
     * @return
     */
    public TreeNode delete (int key) {
        TreeNode parent  = root;
        TreeNode current = root;
        boolean isLeftChild = false;
        // 找到删除节点 及 是否在左子树
        while (current.value != key) {
            parent = current;
            if (current.value > key) {
                isLeftChild = true;
                current = current.left;
            } else {
                isLeftChild = false;
                current = current.right;
            }

            if (current == null) {
                return current;
            }
        }

        // 如果删除节点左节点为空 , 右节点也为空
        if (current.left == null && current.right == null) {
            if (current == root) {
                root = null;
            }
            // 在左子树
            if (isLeftChild == true) {
                parent.left = null;
            } else {
                parent.right = null;
            }
        }
        // 如果删除节点只有一个子节点 右节点 或者 左节点
        else if (current.right == null) {
            if (current == root) {
                root = current.left;
            } else if (isLeftChild) {
                parent.left = current.left;
            } else {
                parent.right = current.left;
            }

        }
        else if (current.left == null) {
            if (current == root) {
                root = current.right;
            } else if (isLeftChild) {
                parent.left = current.right;
            } else {
                parent.right = current.right;
            }
        }
        // 如果删除节点左右子节点都不为空
        else if (current.left != null && current.right != null) {
            // 找到删除节点的后继者
            TreeNode successor = getDeleteSuccessor(current);
            if (current == root) {
                root = successor;
            } else if (isLeftChild) {
                parent.left = successor;
            } else {
                parent.right = successor;
            }
            successor.left = current.left;
        }
        return current;
    }

    /**
     * 获取删除节点的后继者
     *      删除节点的后继者是在其右节点树种最小的节点
     * @param deleteNode
     * @return
     */
    public TreeNode getDeleteSuccessor(TreeNode deleteNode) {
        // 后继者
        TreeNode successor = null;
        TreeNode successorParent = null;
        TreeNode current = deleteNode.right;

        while (current != null) {
            successorParent = successor;
            successor = current;
            current = current.left;
        }

        // 检查后继者(不可能有左节点树)是否有右节点树
        // 如果它有右节点树,则替换后继者位置,加到后继者父亲节点的左节点.
        if (successor != deleteNode.right) {
            successorParent.left = successor.right;
            successor.right = deleteNode.right;
        }

        return successor;
    }

    public void toString(TreeNode root) {
        if (root != null) {
            toString(root.left);
            System.out.print("value = " + root.value + " -> ");
            toString(root.right);
        }
    }
}

/**
 * 节点
 */
class TreeNode {

    /**
     * 节点值
     */
    int value;

    /**
     * 左节点
     */
    TreeNode left;

    /**
     * 右节点
     */
    TreeNode right;

    public TreeNode(int value) {
        this.value = value;
        left  = null;
        right = null;
    }
}

ポイントをインタビュー:データ構造のTreeNodeを理解するために

ノードデータ構造、即ち、左ノードとノード点の右ノードとノード自体の値。フィギュア

1483536-4ab125a143be8af2.png

ポイント2インタビュー:バイナリツリーの最大の深さまたは最小深さを決定する方法

答え:単純な再帰実装することができ、次のように:

int maxDeath(TreeNode node){
    if(node==null){
        return 0;
    }
    int left = maxDeath(node.left);
    int right = maxDeath(node.right);
    return Math.max(left,right) + 1;
}

    int getMinDepth(TreeNode root){
        if(root == null){
            return 0;
        }
        return getMin(root);
    }
    int getMin(TreeNode root){
        if(root == null){
            return Integer.MAX_VALUE;
        }
        if(root.left == null&&root.right == null){
            return 1;
        }
        return Math.min(getMin(root.left),getMin(root.right)) + 1;
    }

ポイント3インタビュー:バイナリツリーは平衡二分木であるかどうかを確認する方法

答え:単純な再帰実装することができ、次のように:

    boolean isBalanced(TreeNode node){
        return maxDeath2(node)!=-1;
    }
    int maxDeath2(TreeNode node){
        if(node == null){
            return 0;
        }
        int left = maxDeath2(node.left);
        int right = maxDeath2(node.right);
        if(left==-1||right==-1||Math.abs(left-right)>1){
            return -1;
        }
        return Math.max(left, right) + 1;
    }

ポイントバイナリツリーは、面接後のポイントは、バイナリツリーの検索で、面接の前にあります。曹操は、バイナリコードを実行します。

public class BinarySearchTreeTest {

    public static void main(String[] args) {
        BinarySearchTree b = new BinarySearchTree();
        b.insert(3);b.insert(8);b.insert(1);b.insert(4);b.insert(6);
        b.insert(2);b.insert(10);b.insert(9);b.insert(20);b.insert(25);

        // 打印二叉树
        b.toString(b.root);
        System.out.println();

        // 是否存在节点值10
        TreeNode node01 = b.search(10);
        System.out.println("是否存在节点值为10 => " + node01.value);
        // 是否存在节点值11
        TreeNode node02 = b.search(11);
        System.out.println("是否存在节点值为11 => " + node02);

        // 删除节点8
        TreeNode node03 = b.delete(8);
        System.out.println("删除节点8 => " + node03.value);
        b.toString(b.root);

    }
}

結果は以下の通りであります:

value = 1 -> value = 2 -> value = 3 -> value = 4 -> value = 6 -> value = 8 -> value = 9 -> value = 10 -> value = 20 -> value = 25 -> 
是否存在节点值为10 => 10
是否存在节点值为11 => null
删除节点8 => 8
value = 1 -> value = 2 -> value = 3 -> value = 4 -> value = 6 -> value = 9 -> value = 10 -> value = 20 -> value = 25 ->

ポイント4インタビュー:バイナリツリーの検索を挿入する方法

挿入して、動的な変更バイナリ検索ツリーにつながる同じを削除します。比較的単純な処理ロジックを穿刺挿入反対。図ロジック挿入:

16535373-467abb3cbe58a2c4.png
  1. ルートノードから始まって
  2. ルートが空の場合、ルート値に挿入されます
  3. ループ:
  4. 値は、現在のノードが左ノードを探し、値が挿入されているよりも大きい場合
  5. 値は、現在のノードの値が挿入さ未満である場合、右のノードを見つけるために

インタビュー2.5:バイナリツリーの検索を見つける方法

そのアルゴリズムの複雑さ:O(LGN)、ツリーの深さ(N)。図ルックアップ論理:

16535373-7d48ffe945fd48f2.png
  1. ルートノードから始まって
  2. ノードの現在の値よりも小さく、そして見つけるその左ノード
  3. 大ノードの現在の値よりも、その右のノードを見つけます
  4. 現在のノードの値に等しい、trueを返しを見つけます
  5. 完全な検索が見つかりませんでした

インタビュー2.5:バイナリツリーの検索を削除する方法

より複雑な。まず、方法を探している削除されたノードを、見つける:後続ノードがノードツリー内の右ノードの最小で削除します。図は、対応する論理を削除します。

16535373-1118151ce3c4fbbf.png

結果は以下のとおりです。

1483536-1c98a826aba1a86b.png
  1. 見つかったノードを削除します。
  2. 左のノードが空の中にノードを削除した場合、右のノードはnullです
  3. ノードを削除した場合のみ、一人の子供は、左または右ノードノード
  4. あなたは左と右の子を削除した場合のノードが空ではありません

IIIの概要

人民元効率的なインタビューのプログラムとしてコードと時折、ボウルのように「古い祭壇漬け牛肉麺」の味を食べて、常に種類のは、そのようなBSTなど、言葉で表せないほどの風味をするアルゴリズムを味わいます。

おすすめ

転載: blog.csdn.net/weixin_34122810/article/details/90803526