インタビューのアリ・第二ラウンド:手書きのJavaバイナリツリー

アリインタビュー

今、募集の開発位置の多くの企業は、彼らが事前に指示することをインタビュアーは仕事で知識とスキルを持っている必要がありますが、また、面接の過程で、同社の厳格な要件の習得のためのいくつかのスキルはまた、インタビュアーの手書きが必要になりますコードは、このリンクは基本的なスキルと強さのインタビュアーのテストです!

これは、友人が2面の過程で、アリの面接に行ってきました、他の日は準備するために、この知識がない場合には、バイナリツリー、王犬を達成するためにJavaを使用するように求められます、それを答えていない、その後、家に帰ると知らさことはできません。 。

王を利用する機会があり、犬は、バイナリツリーを説明し、私は勉強を交換するために皆のための問題で全体の共通インタビューバイナリポイントをとかし。私はあなたのインタビューを助けたいです。

二進木

これは、各ノードは2つまでの子ノードを有することができる再帰的なバイナリツリーデータ構造です。

バイナリ検索ツリーの一般的なタイプは、バイナリツリー、値が右の子ノードより大きいか左の子ノード、ノード値の値に等しく、以下となっている各ノードです。

これは、このバイナリツリーの視覚的な表現です。

実装のために、我々は、使用するノードのint値を格納するクラスを、それぞれの子ノードへの参照を保存します。

class Node {
    int value;//本节点的值
    Node left;//左边的子节点
    Node right;//右边的子节点
 
    Node(int value) {
        this.value = value;
        right = null;
        left = null;
    }
}

それでは、通称ツリーのルート追加してみましょうルートを

public class BinaryTree {
 
    Node root;
 
    // ...
}

私たちは2019面接日時の情報を収集したように、それは、9月と10月は四半期を終了している文献がある、レイダースがあり、ビデオがあります。公共の場で貧しい学生は、最新の情報を受信する[インタビュー]を送って、親友番号[Javaの]することができます!

私たちは下を達成するために協力しましょう

それでは、どのようなバイナリツリー上で実行することができ、最も一般的な操作を見てみましょうか?

要素を挿入

私たちが紹介したい最初のアクション新しいノードが挿入されています

まず第一に、私たちは木ソートに新しいノードを追加したい場所を見つけなければなりません私たちは、これらの規則に従うことをルートから起動します。

  • 新しいノードの値が現在のノードの値よりも低い場合、我々は左の子に行きます
  • 新しいノードの値が現在のノードの値よりも大きい場合、我々は右の子に移動します
  • 現在のノードがnullである、我々は葉ノードに到達している、我々はこの場所に新しいノードを挿入することができます

まず、挿入するために、再帰的なメソッドを作成します。

private Node addRecursive(Node current, int value) {
    if (current == null) {
        return new Node(value);
    }
 
    if (value < current.value) {
        current.left = addRecursive(current.left, value);
    } else if (value > current.value) {
        current.right = addRecursive(current.right, value);
    } else {
        // value already exists
        return current;
    }
 
    return current;
}

次に、我々は、ルート・ノードを作成するために、再帰的なメソッドを作成します。

public void add(int value) {
    root = addRecursive(root, value);
}

今度は、私たちの例からツリーを作成するには、このメソッドを使用する方法を見てみましょう:

private BinaryTree createBinaryTree() {
    BinaryTree bt = new BinaryTree();
 
    bt.add(6);
    bt.add(4);
    bt.add(8);
    bt.add(3);
    bt.add(5);
    bt.add(7);
    bt.add(9);
 
    return bt;
}

検索要素

今度は木が特定の値が含まれているかどうかを確認する方法を追加してみましょう。

前と同様に、我々は最初のツリーをトラバースする再帰的なメソッドを作成します。

private boolean containsNodeRecursive(Node current, int value) {
    if (current == null) {
        return false;
    } 
    if (value == current.value) {
        return true;
    } 
    return value < current.value
      ? containsNodeRecursive(current.left, value)
      : containsNodeRecursive(current.right, value);
}

ここでは、現在のノードの値と比較することにより、値を検索し、その値に応じて左または右の子ノードを見て継続し続けなければなりません。

次に、私たちが見つけて、パブリックメソッドを作成してみましょう:

public boolean containsNode(int value) {
    return containsNodeRecursive(root, value);
}

それでは、木が実際に挿入された要素が含まれていることを確認するための簡単なテストを作成してみましょう:

@Test
public void givenABinaryTree_WhenAddingElements_ThenTreeContainsThoseElements() {
    BinaryTree bt = createBinaryTree();
 
    assertTrue(bt.containsNode(6));
    assertTrue(bt.containsNode(4));
  
    assertFalse(bt.containsNode(1));
}

要素を削除します

もう一つの一般的な操作は、ツリーからノードを削除することです。

まず、前回と同様の方法で削除するノードを見つける必要があります。

private Node deleteRecursive(Node current, int value) {
    if (current == null) {
        return null;
    }
 
    if (value == current.value) {
        // Node to delete found
        // ... code to delete the node will go here
    } 
    if (value < current.value) {
        current.left = deleteRecursive(current.left, value);
        return current;
    }
    current.right = deleteRecursive(current.right, value);
    return current;
}

私たちは、ノードを削除することが見つかったら、三つの主要な異なる状況があります。

  • ノードが子を持たない -これは最も単純なケースであり、我々はその親に必要なヌルこのノードを置き換えます
  • 唯一の子ノードは、 -親ノードでは、我々はその唯一の子を持つノードを交換してください。
  • ノードは、2人の子供を持っている -これは最も複雑なケースで、それは木の再編成を必要とするため、

ノードは、我々は最初のケースを達成する方法のリーフノードであるとき見てみましょう:

if (current.left == null && current.right == null) {
    return null;
}

それでは、議論ノードは、例の子ノードを持っていきましょう:

if (current.right == null) {
    return current.left;
}
 
if (current.left == null) {
    return current.right;
}

ここでは、返すnull以外の親にそれを割り当てるために、子ノードを。

最後に、我々は、ノードが2つのつの子ノードを持っている状況に対処しなければなりません。

まず、我々は、交換ノードが削除された見つける必要があります。私たちは、子どもの権利を削除するには、最小のノードツリーのノードを使用します。

private int findSmallestValue(Node root) {
    return root.left == null ? root.value : findSmallestValue(root.left);
}

私たちは、その後、削除するノードの最小値に割り当てられます、そして、我々は、サブツリーの右側からそれを削除します。

int smallestValue = findSmallestValue(current.right);
current.value = smallestValue;
current.right = deleteRecursive(current.right, smallestValue);
return current;

最後に、私たちは削除する一般的な方法を作成してみましょう:

public void delete(int value) {
    root = deleteRecursive(root, value);
}

それでは、期待どおりに動作している削除チェックしてみましょう:

@Test
public void givenABinaryTree() {
    BinaryTree bt = createBinaryTree();
 
    assertTrue(bt.containsNode(9));
    bt.delete(9);
    assertFalse(bt.containsNode(9));
}

変換ツリー

ここでは、深さ優先と幅優先探索を詳述し、ツリーを横断する別の方法が表示されます。

我々は以前に使用したのと同じツリーを使用します、そして私たちは、それぞれの場合のトラバーサルの順序が表示されます。

深さ優先探索

深さ優先探索は、探検する、それぞれの子の深いトラバーサルの前に、できるだけ多くの兄弟です。

イン・オーダー、プリオーダーとポスト順:深さ優先探索を行うにはいくつかの方法があります。

で次:まず、左のサブツリーを訪問し、その後、根、右部分木の最後の訪問を参照してください。

public void traverseInOrder(Node node) {
    if (node != null) {
        traverseInOrder(node.left);
        System.out.print(" " + node.value);
        traverseInOrder(node.right);
    }
}

私たちは、このメソッドを呼び出すと、コンソール出力:

3 4 5 6 7 8 9

プリオーダー:まず、ルートノードにアクセスし、左側のサブツリー、そして最終的には右のサブツリー:

public void traversePreOrder(Node node) {
    if (node != null) {
        System.out.print(" " + node.value);
        traversePreOrder(node.left);
        traversePreOrder(node.right);
    }
}

私たちは、このメソッドを呼び出すと、コンソール出力:

6 4 3 5 8 7 9

ポスト順序:左サブツリー、右部分木、根最後の訪問を参照してください。

public void traversePostOrder(Node node) {
    if (node != null) {
        traversePostOrder(node.left);
        traversePostOrder(node.right);
        System.out.print(" " + node.value);
    }
}

私たちは、このメソッドを呼び出すと、コンソール出力:

3 5 4 7 9 8 6

BFS

これは、それを横断する別の一般的なタイプであるすべてのノードが次のレベルに入る前のレベルにアクセスショーで

また、これはレベル横断順序によって参照されると、ツリーのすべてのレベルにアクセスするには、左から右へ、ルートから開始されます。

実装のために、我々は、使用するキューを各レベルのノードを節約するために。私たちは、リストから、各ノードを抽出し、その値を印刷した後、キューにその子ノードを追加します。

public void traverseLevelOrder() {
    if (root == null) {
        return;
    }
 
    Queue<Node> nodes = new LinkedList<>();
    nodes.add(root);
 
    while (!nodes.isEmpty()) {
 
        Node node = nodes.remove();
 
        System.out.print(" " + node.value);
 
        if (node.left != null) {
            nodes.add(node.left);
        }
 
        if (node.right!= null) {
            nodes.add(node.right);
        }
    }
}

この場合には、ノードの順序は次のようになります。

6 4 8 3 5 7 9

遂に

この記事では、ソートされたバイナリツリーとJavaで最も一般的な操作を実装する方法を学びました。あなたはそれから得ていますか?あなたも嬉しく、この小さなシリーズでは、少し経験を積むことができたとしても!

どこにでも夢の馬の生息地:あなたが未来になることを期待して「短いステップ、千マイル」!、ジュニアさあ!


いいえ公共の懸念:「ジャワの親友」、更新毎日のJavaの知識はああ、あなたの到着を楽しみにしていません!

  • 「送信1024無料30冊の古典的なプログラミングの本を受け取るために」。
  • 「送信グループを 10万人のプログラマーとの進展を」。
  • 「送信インタビューを情報BATJのインタビュー、ビデオインタビューレイダースを受け取るために」。
  • 「送信のJavaEE戦闘ビデオチュートリアルの」受信「のJavaEE戦闘」シリーズを。
  • 「送信楽しいアルゴリズムをビデオチュートリアルの「楽しいアルゴリズム」シリーズを受け取るために」。

おすすめ

転載: www.cnblogs.com/java-friend/p/11506106.html