сортировать массив перед добавлением в дерево двоичного поиска Java

У меня есть массив строк в порядке от A до Z. Мне было интересно, как лучше всего отсортировать их для сбалансированного двоичного дерева поиска. Моя первоначальная мысль состоит в том, чтобы разделить массив на первую половину и вторую половину, а затем отсортировать их по отдельности.

Разве я не должен использовать рекурсивный способ разделения его пополам, чтобы получить следующий узел для дерева? Я просто не могу обдумать это прямо сейчас и подумал, что спрошу, есть ли у кого-нибудь какие-нибудь идеи. чтобы привести меня в правильном направлении или привести несколько примеров. Спасибо!

я использую свой собственный класс BinaryTree и класс BinaryTreeNode. РЕДАКТИРОВАТЬ:

public class BinaryTree {
private BinaryTreeNode root;

public void insert(String text) {

root = insertNode(root, text); 

}

private BinaryTreeNode insertNode(BinaryTreeNode curNode, String text) {
if (curNode == null) {
    BinaryTreeNode newNode = new BinaryTreeNode(text);
    //newNode.value = text;
    return newNode;
} else {
    if (text.compareTo(curNode.value) < 0 ) {
        //left child
        //use of recursion to properly place Node
        curNode.left = insertNode(curNode.left, text);
        return curNode;
    }

        else {

        //right
        //use of recursion to properly place Node
        curNode.right = insertNode(curNode.right, text);
        return curNode;
    }
}

}

public BinaryTreeNode getRoot() {
return root;
}

 public void setRoot(BinaryTreeNode root) {
this.root = root;
 }
 }

будет ли это считаться самобалансирующимся двоичным деревом поиска?


person Pengume    schedule 07.11.2011    source источник


Ответы (2)


Ваше дерево, похоже, не самобалансируется. самобалансирующийся BST будет выполнять шаги после вставки или после нескольких вставок. , чтобы убедиться, что он (примерно) сбалансирован.

Если вы добавляете элементы только один раз и используете дерево только для чтения, у вас есть отсортированный массив, а затем выполните следующие действия: выберите элемент в середине. создайте корень с ним в качестве ключа, а затем рекурсивно добавьте элементы слева от него (меньшие элементы) в качестве левого поддерева вашего корня и элементы справа в качестве правого поддерева соответственно. Вы должны получить более или менее сбалансированный BST. Пример кода:

public class BinaryTree {

    /* ... */


    //each recursive call receives a pair of bounds for the part of the 
    //array it has to process: left and right
    public static BinaryTreeNode nodeFromSortedArray(String[]a,
                                           int left, int right){

        if (right<left) return null;

        if (right==left)
            return new BinaryTreeNode(a[left]);

        int mid = (left+right)/2;

        //create node from middle element
        BinaryTreeNode n = new BinaryTreeNode(a[mid]);

        //recursively add elements to the left as its right subtree
        n.left = nodeFromSortedArray(a, left, mid-1);

        //recursively add elements to the right as its right subtree
        n.right = nodeFromSortedArray(a, mid+1, right);

        return n;
    }

    public static BinaryTree fromSortedArray(String[]a){
        BinaryTree bt = new BinaryTree();
        bt.setRoot(nodeFromSortedArray(a,0,a.length-1));
        return bt;
    }

    /* ... */
}

Однако в этом случае вы можете просто сохранить свои элементы в отсортированном массиве и использовать бинарный поиск для его индексации вместо дерева. Сложность должна быть такой же, O(logn), но вам нужно меньше ссылок для хранения всего этого, а производительность кэша должна быть лучше.

Если вам нужно иметь изменяемое дерево и вы хотите сделать его эффективным, вам, вероятно, потребуется сделать его самобалансирующимся, в случае, когда порядок, в котором вы добавляете в него свои элементы, не имеет значения.

person Vlad    schedule 07.11.2011
comment
спасибо, Влад, мне действительно не нужно самобалансирующееся дерево, так как я загружаю массив из файла. Я понимаю, что ты говоришь. Чтобы выбрать середину массива в качестве корня. Но я запутался в рекурсивном прохождении левой или правой стороны. Нужно ли мне продолжать делить на 2, чтобы получать правильные значения, которые будут добавлены для левой стороны в рекурсивной функции? Это единственная часть, на которой я застрял. Я лучше всего учусь на примере. Спасибо! - person Pengume; 07.11.2011
comment
Спасибо, мне нужно больше изучать рекурсию. Теперь я лучше понимаю, хотя на вашем примере. - person Pengume; 07.11.2011
comment
Рад помочь. Рекурсия действительно ценный метод, и я думаю, вы сможете найти много документации по этой теме. Вы можете начать с чего-то простого, например с последовательности Фибоначчи, которая, хотя и медленно используется, рекурсия, может помочь вам понять. Вы даже можете отследить код вручную и выяснить вызовы и возвраты. - person Vlad; 07.11.2011
comment
Привет, Влад, у меня был быстрый вопрос. При использовании приведенного выше рекурсивного алгоритма я заметил, что некоторые конкретные узлы находятся в неправильных местах для поиска и оказываются нулевыми. Например: если корневой узел = метка, а его левый дочерний элемент = кошка, то правым дочерним элементом для кошки будет бык. В моем алгоритме поиска я использую метод CompareTo, чтобы проверить, является ли найденное слово › 0 ‹ 0, чтобы пройти по дереву и проверить правильный дочерний элемент. Но быка никогда не найдут, потому что он находится не в том месте. Любые идеи? Я не уверен, как подойти к этому. - person Pengume; 09.11.2011
comment
Если вы покажете мне массив, который вы передали fromSortedArray, я могу попробовать сам и выяснить, что пошло не так. - person Vlad; 09.11.2011
comment
О ничего себе хорошо, ну теперь, когда я оглянулся. Это была ошибка пользователя. Я читал файл, который уже был в предварительной сортировке, и это приводило к неправильному построению дерева. Просто вставив его регулярно и пройдя через отладчик, я обнаружил, что это мой алгоритм поиска. Извините, но спасибо за вашу помощь! - person Pengume; 09.11.2011

Если у вас есть бинарное дерево поиска, которое самобалансируется, вполне вероятно, что предварительная сортировка массива непродуктивна. Алгоритм оптимального добавления отсортированных данных в сбалансированное дерево сильно отличается от алгоритма добавления неупорядоченных данных.

Однако в опубликованном вами коде нет ничего «самобалансирующегося». Это обычный алгоритм вставки бинарного дерева.

person user207421    schedule 07.11.2011