1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/joyang1-BinaryTree

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
В этом репозитории не указан файл с открытой лицензией (LICENSE). При использовании обратитесь к конкретному описанию проекта и его зависимостям в коде.
Клонировать/Скачать
Внести вклад в разработку кода
Синхронизировать код
Отмена
Подсказка: Поскольку Git не поддерживает пустые директории, создание директории приведёт к созданию пустого файла .keep.
Loading...
README.md

Двоичное дерево (Binary Tree)

Двоичное дерево — это структура дерева, в которой каждый узел имеет не более двух поддеревьев. Обычно эти поддеревья называются «левое поддерево» (left subtree) и «правое поддерево» (right subtree). Двоичные деревья часто используются для реализации двоичных деревьев поиска и двоичных куч.

В двоичном дереве у каждого узла есть максимум два поддерева (не существует узлов со степенью больше 2), двоичное дерево имеет разделение на левое и правое поддеревья, порядок нельзя изменить. В двоичном дереве i-го уровня не более 2^(i-1) узлов; в двоичном дереве глубины k не более 2^k-1 узлов; для любого двоичного дерева T, если количество его конечных узлов равно n_0, а количество узлов степени 2 равно n_2, то n_0 = n_2 + 1.

Дерево глубины k с 2^k-1 узлами называется полным двоичным деревом; дерево глубины k с n узлами является полным двоичным деревом только тогда, когда каждый его узел соответствует узлу полного двоичного дерева глубины k с номерами от 1 до n.

Создание двоичного дерева с использованием Java

//arrs - массив данных, которые будут помещены в узлы дерева, demo будет содержать данные типа int, помещённые в узлы
public List<TreeNode> initTree(int[] arrs) {
        List<TreeNode> nodes = new ArrayList<TreeNode>();
        for (int data : arrs) {
            nodes.add(new TreeNode(data));
        }
        // Здесь каждый родительский узел имеет индекс < (arrs.length / 2 - 1), что гарантирует наличие левого и правого дочерних узлов для каждого родительского узла
        for (int parentIndex = 0; parentIndex < arrs.length / 2 - 1; parentIndex++) {
            nodes.get(parentIndex).leftNode = nodes.get(parentIndex * 2 + 1);
            nodes.get(parentIndex).rightNode = nodes.get(parentIndex * 2 + 2); 
        }
        // (arrs.length / 2 - 1) - последний родительский узел, согласно определению двоичного дерева
                int lastParentIndex = arrs.length / 2 - 1;
        nodes.get(lastParentIndex).leftNode = nodes.get(lastParentIndex * 2 + 1);
        // Если arrs.length % 2 != 0, используется для определения, существует ли правый дочерний узел последнего родительского узла
                if(arrs.length % 2 != 0){
            nodes.get(lastParentIndex).rightNode = nodes.get(lastParentIndex * 2 + 2);
        }
        return nodes;
}

Объект TreeNode, упомянутый в методе выше, можно найти в коде (src.test.TreeNode).

Три способа обхода

(1). Прямой обход: «корень, левый, правый».

(2). Симметричный обход: «левый, корень, правый».

(3). Обратный обход: «левый, правый, корень».

Три способа обхода отличаются порядком обхода.

Прямой обход: корень → левый узел → правый узел.

Симметричный обход: левый узел → корень → правый узел.

Обратный обход: левый узел → правый узел → корень.

Прямой обход

Использование рекурсии:

    /*
     * Прямой обход двоичного дерева: корень, левый, правый
     *
     * @param node
     *       Обход узла
     * */
    public void preOrderTraverse(TreeNode node){
        if(node == null)
            return;
        System.out.print(node.data + " "); // Первый вход - это rootNode
        preOrderTraverse(node.leftNode);  // Рекурсивный вывод левого узла     
                preOrderTraverse(node.rightNode); // Рекурсивный вывод правого узла
    }

Использование цикла:

    /*
     * Прямой обход двоичного дерева: корень, левый, правый
     *
     * Использование цикла
     *
     * @param node
     *       Узел обхода
     * */
    public void preOrderTraverseByWhile(TreeNode node){
        LinkedList<TreeNode> stack = new LinkedList<TreeNode>();
        stack.push(node);
        TreeNode currentNode;
        while (!stack.isEmpty()) {
            currentNode = stack.pop();
            System.out.print(currentNode.data + " ");
            if(currentNode.rightNode != null){
                stack.push(currentNode.rightNode);
            }
            if (currentNode.leftNode != null) {
                stack.push(currentNode.leftNode);
            }
        }
    }

Симметричный обход

Использование рекурсии:

    /*
     * Симметричный обход двоичного дерева: левый, корень, правый
     *
     * @param node
     *       Обход узла
     * */
    public void inOrderTraverse(TreeNode node){
        if(node == null)
            return;
        inOrderTraverse(node.leftNode); // Рекурсивный вывод левого узла
        System.out.print(node.data + " "); 
        inOrderTraverse(node.rightNode); // Рекурсивный вывод правого узла
    }

Использование цикла:

    /*
     * Симметричный обход двоичного дерева: левый, корень, правый
     *
     * Использование цикла
     *
     * @param node
     *       Узел обхода
     * */
    public void inOrderTraverseByWhile(TreeNode node){
        LinkedList<TreeNode> stack = new LinkedList<TreeNode>();
        TreeNode currentNode = node;
        while (currentNode != null || !stack.isEmpty()) {
            while(currentNode != null){
                stack.push(currentNode);
                currentNode = currentNode.leftNode;
            }
            if(!stack.isEmpty()){
                currentNode = stack.pop();
                System.out.print(currentNode.data + "");
                currentNode = currentNode.rightNode;
            }
        }
    }

Обратный обход

Использование рекурсии:

    /*
     * Обратный обход двоичного дерева: левый, правый, корень
     *
     * @param node
     *       Обход узла
     * */
    public void afterOrderTraverse(TreeNode node){
        if(node == null)
            return;
        afterOrderTraverse(node.leftNode);// Рекурсивный вывод левого узла
        afterOrderTraverse(node.rightNode);// Рекурсивный вывод правого узла
        System.out.print(node.data + " ");
    }

Использование цикла:

    /*
     * Обратный обход двоичного дерева: левый, правый, корень

     * */
    public void afterOrderTraverseByWhile(TreeNode node){
        LinkedList<TreeNode> stack = new LinkedList<TreeNode>();
        TreeNode currentNode = node;
        while (currentNode != null || !stack.isEmpty()) {
            while(currentNode != null){
                stack.push(currentNode);
                currentNode = currentNode.leftNode;
            }
            if(!stack.isEmpty()){
                currentNode = stack.pop();
                System.out.print(currentNode.data + "");
                currentNode = currentNode.rightNode;
            }
        }
    } ```
     * Использование цикла
     */
    public void afterOrderTraverseByWhile(TreeNode node){
        LinkedList<TreeNode> stack = new LinkedList<TreeNode>();
        TreeNode rightNode = null;
        TreeNode currentNode = node;
        while (currentNode != null || !stack.isEmpty()) {
            while(currentNode != null){
                stack.push(currentNode);
                currentNode = currentNode.leftNode;
            }
            currentNode = stack.pop();
            //когда предыдущий посещённый узел является правым потомком или текущий узел не имеет правого потомка, тогда посещаем текущий узел
            while(currentNode != null && (currentNode.rightNode == null || currentNode.rightNode == rightNode)){
                System.out.print(currentNode.data + " ");
                rightNode = currentNode;
                if(stack.isEmpty()){
                    return;
                }
                currentNode = stack.pop();
            }
            stack.push(currentNode);
            currentNode = currentNode.rightNode;
        }
    }

Как запустить код

  1. Клонируйте код на локальный компьютер и импортируйте его в Eclipse, выбрав «git project» при импорте проекта.
  2. Найдите файл src/test/RunTest.java и запустите его как Java-приложение правой кнопкой мыши.

Структура бинарного дерева, заданная в demo:

![](http://blog.tommyyang.cn/img/binary-tree.png)

Результат RunTest:

![](http://blog.tommyyang.cn/img/binarytree-xunhuanresult.png)

Комментарии ( 0 )

Вы можете оставить комментарий после Вход в систему

Введение

Описание недоступно Развернуть Свернуть
Отмена

Обновления

Пока нет обновлений

Участники

все

Недавние действия

Загрузить больше
Больше нет результатов для загрузки
1
https://api.gitlife.ru/oschina-mirror/joyang1-BinaryTree.git
git@api.gitlife.ru:oschina-mirror/joyang1-BinaryTree.git
oschina-mirror
joyang1-BinaryTree
joyang1-BinaryTree
master