數(shù)據(jù)結構-二叉查找樹(Binary Search Tree)

二叉查找樹擁有如下特性:

  • 若左子樹不空切揭,則左子樹上所有結點的值均小于或等于它的根結點的值妈倔;
  • 若右子樹不空及志,則右子樹上所有結點的值均大于或等于它的根結點的值攒读;
  • 左朵诫、右子樹也分別為二叉查找樹;
package com.zhuke.datastruct;

import com.alibaba.fastjson.JSON;

import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * Created by ZHUKE on 2017/9/6.
 */
public class BSTUtils<T extends Comparable<T>> {

    public static void main(String[] args) throws InterruptedException {
        BSTUtils<Integer> BST = new BSTUtils<>();

        BinaryNode<Integer> rootTree = null;

        rootTree = BST.insert(100, rootTree);
        rootTree = BST.insert(80, rootTree);
        rootTree = BST.insert(120, rootTree);
        rootTree = BST.insert(90, rootTree);
        rootTree = BST.insert(85, rootTree);
        rootTree = BST.insert(95, rootTree);
        rootTree = BST.insert(110, rootTree);
        rootTree = BST.insert(150, rootTree);
        rootTree = BST.insert(115, rootTree);
        rootTree = BST.insert(180, rootTree);
        rootTree = BST.insert(140, rootTree);

        BSTUtils<Integer> BST1 = new BSTUtils<>();
        BinaryNode<Integer> rootTree1 = null;

        rootTree1 = BST1.insertNoRecursive(-1, rootTree1);
        rootTree1 = BST1.insertNoRecursive(31, rootTree1);
        rootTree1 = BST1.insertNoRecursive(81, rootTree1);
        rootTree1 = BST1.insertNoRecursive(-36, rootTree1);
        rootTree1 = BST1.insertNoRecursive(188, rootTree1);
        rootTree1 = BST1.insertNoRecursive(-2, rootTree1);
        rootTree1 = BST1.insertNoRecursive(9, rootTree1);


        System.out.println("Search result = " + BST.search(100, rootTree).data);
        System.out.println("Search with no recursive result = " + BST.searchNoRecursive(100, rootTree).data);

        System.out.println("BST max value = " + BST.findMax(rootTree).data);
        System.out.println("BST min value = " + BST.findMin(rootTree).data);

        System.out.println("BST with no recursive max value = " + BST.findMaxNoRecursive(rootTree).data);
        System.out.println("BST with no recursive min value = " + BST.findMinNoRecursive(rootTree).data);

        ArrayList<Integer> preOrderResult = new ArrayList<>();

        BST.preOrderTraversal(rootTree, preOrderResult);
        System.out.println("PreOrder traversal result = " + JSON.toJSONString(preOrderResult));

        preOrderResult.clear();
        BST.preOrderTraversalNoRecursive(rootTree, preOrderResult);
        System.out.println("PreOrder traversal with no recursive result = " + JSON.toJSONString(preOrderResult));

        ArrayList<Integer> inOrderResult = new ArrayList<>();

        BST.inOrderTraversal(rootTree, inOrderResult);
        System.out.println("InOrder traversal result = " + JSON.toJSONString(inOrderResult));

        inOrderResult.clear();
        BST.inOrderTraversalNoRecursive(rootTree, inOrderResult);
        System.out.println("InOrder traversal with no recursive result = " + JSON.toJSONString(inOrderResult));

        ArrayList<Integer> postOrderResult = new ArrayList<>();

        BST.postOrderTraversal(rootTree, postOrderResult);
        System.out.println("PostOrder traversal result = " + JSON.toJSONString(postOrderResult));

        postOrderResult.clear();
        BST.postOrderTraversalNoRecursive(rootTree, postOrderResult);
        System.out.println("PostOrder traversal with no recursive result = " + JSON.toJSONString(postOrderResult));

        ArrayList<Integer> breadthResult = new ArrayList<>();

        BST.breadthTraversal(rootTree, breadthResult);
        System.out.println("Breadth traversal result = " + JSON.toJSONString(breadthResult));

        BST.delete(120, rootTree);

        Thread.sleep(Integer.MAX_VALUE);

    }


    /**
     * 在BST中插入一個數(shù)據(jù)值為data的節(jié)點
     *
     * @param data 數(shù)據(jù)值
     * @param tree 根節(jié)點
     * @return 插入了一個數(shù)據(jù)值為data的BST根節(jié)點
     */
    public BinaryNode<T> insert(T data, BinaryNode<T> tree) {
        if (tree == null) {
            tree = new BinaryNode<>(data, null, null, null);
            return tree;
        }
        int compareResult = data.compareTo(tree.data);
        if (compareResult < 0) {
            tree.leftNode = insert(data, tree.leftNode);
            tree.leftNode.parentNode = tree;
        } else if (compareResult > 0) {
            tree.rightNode = insert(data, tree.rightNode);
            tree.rightNode.parentNode = tree;
        } else {
            tree.count.incrementAndGet();
            return tree;
        }
        return tree;
    }

    /**
     * 使用非遞歸方式薄扁,在BST中插入一個數(shù)據(jù)值為data的節(jié)點
     *
     * @param data 數(shù)據(jù)值
     * @param tree 根節(jié)點
     * @return 插入了一個數(shù)據(jù)值為data的BST根節(jié)點
     */
    public BinaryNode<T> insertNoRecursive(T data, BinaryNode<T> tree) {
        if (tree == null) {
            tree = new BinaryNode<>(data, null, null, null);
            return tree;
        }
        int compareResult = data.compareTo(tree.data);
        if (compareResult == 0) {
            tree.count.incrementAndGet();
            return tree;
        } else {
            BinaryNode<T> targetInsertLocation = compareResult > 0 ? tree.rightNode : tree.leftNode;
            if (targetInsertLocation == null) {
                if (compareResult > 0) {
                    tree.rightNode = new BinaryNode<>(data, null, null, tree);
                } else {
                    tree.leftNode = new BinaryNode<>(data, null, null, tree);
                }
                return tree;
            }
            //循環(huán)遍歷到樹的末端節(jié)點剪返,判斷處理插入的正確位置
            while (true) {
                compareResult = data.compareTo(targetInsertLocation.data);
                if (compareResult == 0) {
                    targetInsertLocation.count.incrementAndGet();
                    return tree;
                } else {
                    if (compareResult > 0) {
                        if (targetInsertLocation.rightNode != null) {
                            targetInsertLocation = targetInsertLocation.rightNode;
                        } else {
                            targetInsertLocation.rightNode = new BinaryNode<>(data, null, null, targetInsertLocation);
                            return tree;
                        }
                    } else {
                        if (targetInsertLocation.leftNode != null) {
                            targetInsertLocation = targetInsertLocation.leftNode;
                        } else {
                            targetInsertLocation.leftNode = new BinaryNode<>(data, null, null, targetInsertLocation);
                            return tree;
                        }
                    }
                }
            }
        }
    }

    /**
     * 刪除節(jié)點值為data的節(jié)點
     *
     * @param data 數(shù)據(jù)值
     * @param tree 根節(jié)點
     * @return 刪除節(jié)點值為data后的BST
     */
    public BinaryNode<T> delete(T data, BinaryNode<T> tree) {

        BinaryNode<T> searchedNode = search(data, tree);

        if (searchedNode == null) {
            return tree;
        }

        //葉子節(jié)點废累,直接刪除
        if (searchedNode.leftNode == null && searchedNode.rightNode == null) {
            int parentLeftCompareResult = searchedNode.parentNode.leftNode.data.compareTo(data);
            searchedNode.parentNode = null;
            if (searchedNode.count.decrementAndGet() == 0) {
                //只有一個元素,直接刪除關聯(lián)關系
                if (parentLeftCompareResult == 0) {
                    searchedNode.leftNode = null;
                } else {
                    searchedNode.rightNode = null;
                }
            }
        } else if (searchedNode.leftNode != null && searchedNode.rightNode != null) {//同時有左子樹和右子樹
            //找到替代被刪除節(jié)點的節(jié)點脱盲,該節(jié)點需要比被刪除節(jié)點的左子樹都大邑滨,比右子樹都小
            //被刪除節(jié)點的右子樹的最小值,滿足上述要求钱反,而且該節(jié)點一定是葉子節(jié)點
            BinaryNode<T> replacedNode = findMin(searchedNode.rightNode);
            searchedNode.data = replacedNode.data;
            //替換完成后掖看,直接刪除
            replacedNode.parentNode.leftNode = null;
            replacedNode.parentNode = null;
        } else {
            /*只有左子樹或右子樹*/
            if (searchedNode.leftNode != null) {
                //只有左子樹,將左子樹和父結點相連接
                int searchedNodeCompareToParentNode = searchedNode.data.compareTo(searchedNode.parentNode.data);
                if (searchedNodeCompareToParentNode > 0) {
                    //被刪除的節(jié)點為父結點的右節(jié)點
                    searchedNode.parentNode.rightNode = searchedNode.leftNode;
                } else {
                    searchedNode.parentNode.leftNode = searchedNode.leftNode;
                }
            } else {
                //只有右子樹面哥,將右子樹和父節(jié)點想相連接
                int searchedNodeCompareToParentNode = searchedNode.data.compareTo(searchedNode.parentNode.data);
                if (searchedNodeCompareToParentNode > 0) {
                    //被刪除的節(jié)點為父結點的右節(jié)點
                    searchedNode.parentNode.rightNode = searchedNode.rightNode;
                } else {
                    searchedNode.parentNode.leftNode = searchedNode.rightNode;
                }
            }
        }
        return tree;
    }

    /**
     * 查找指定值在BST中的所在節(jié)點
     *
     * @param data 數(shù)據(jù)值
     * @param tree 根節(jié)點
     * @return 節(jié)點值為data的節(jié)點
     */
    public BinaryNode<T> search(T data, BinaryNode<T> tree) {
        if (tree == null) {
            return null;
        }
        int compareResult = data.compareTo(tree.data);
        if (compareResult > 0) {
            return search(data, tree.rightNode);
        } else if (compareResult < 0) {
            return search(data, tree.leftNode);
        } else {
            return tree;
        }
    }

    /**
     * 非遞歸方式哎壳,查找指定值在BST中的所在節(jié)點
     *
     * @param data 數(shù)據(jù)值
     * @param tree 根節(jié)點
     * @return 節(jié)點值為data的節(jié)點
     */
    public BinaryNode<T> searchNoRecursive(T data, BinaryNode<T> tree) {
        if (tree == null) {
            return null;
        }
        int compareResult = data.compareTo(tree.data);
        if (compareResult == 0) {
            return tree;
        } else {
            BinaryNode<T> targetNodeLocation = compareResult > 0 ? tree.rightNode : tree.leftNode;
            //遍歷查找樹的各層節(jié)點
            while (targetNodeLocation != null) {
                compareResult = data.compareTo(targetNodeLocation.data);
                if (compareResult == 0) {
                    return targetNodeLocation;
                } else {
                    targetNodeLocation = (compareResult > 0 ? targetNodeLocation.rightNode : targetNodeLocation.leftNode);
                }
            }
            return null;
        }
    }

    /**
     * 查找BST的最小值
     *
     * @param tree 根節(jié)點
     * @return BST中的最小值
     */
    public BinaryNode<T> findMin(BinaryNode<T> tree) {
        if (tree == null) {
            return null;
        }
        if (tree.leftNode == null) {
            return tree;
        } else {
            return findMin(tree.leftNode);
        }
    }

    public BinaryNode<T> findMinNoRecursive(BinaryNode<T> tree) {
        if (tree == null) {
            return null;
        }
        if (tree.leftNode == null) {
            return tree;
        } else {
            BinaryNode<T> targetNodeLocation = tree.leftNode;
            while (true) {
                if (targetNodeLocation.leftNode == null) {
                    return targetNodeLocation;
                } else {
                    targetNodeLocation = targetNodeLocation.leftNode;
                }
            }
        }
    }

    /**
     * 查找BST的最大值
     *
     * @param tree 根節(jié)點
     * @return BST中的最大值
     */
    public BinaryNode<T> findMax(BinaryNode<T> tree) {
        if (tree == null) {
            return null;
        }
        if (tree.rightNode == null) {
            return tree;
        } else {
            return findMax(tree.rightNode);
        }
    }

    public BinaryNode<T> findMaxNoRecursive(BinaryNode<T> tree) {
        if (tree == null) {
            return null;
        }
        if (tree.rightNode == null) {
            return tree;
        } else {
            BinaryNode<T> targetNodeLocation = tree.rightNode;
            while (true) {
                if (targetNodeLocation.rightNode == null) {
                    return targetNodeLocation;
                } else {
                    targetNodeLocation = targetNodeLocation.rightNode;
                }
            }
        }
    }

    /**
     * 前序遍歷BST
     *
     * @param tree            BST根節(jié)點
     * @param traversalResult 遍歷結果
     */
    public void preOrderTraversal(BinaryNode<T> tree, List<T> traversalResult) {
        if (tree != null) {
            addTraversalToResultList(tree, traversalResult);
            preOrderTraversal(tree.leftNode, traversalResult);
            preOrderTraversal(tree.rightNode, traversalResult);
        }
    }

    /**
     * 非遞歸方式前序遍歷BST
     *
     * @param tree            BST根節(jié)點
     * @param traversalResult 遍歷結果
     */
    public void preOrderTraversalNoRecursive(BinaryNode<T> tree, List<T> traversalResult) {
        if (tree != null) {
            //使用一個棧,暫存訪問左右子樹的順序
            Stack<BinaryNode<T>> stack = new Stack<>();
            BinaryNode<T> node = tree;

            while (node != null || !stack.isEmpty()) {

                //首先訪問根節(jié)點尚卫,并將根節(jié)點入棧归榕,因為需要通過根節(jié)點進入相應的左右子樹
                while (node != null) {
                    addTraversalToResultList(node.clone(), traversalResult);
                    stack.push(node);
                    node = node.leftNode;
                }
                //上面的循環(huán)全部訪問左子樹的所有根節(jié)點,直到BST的最左下角吱涉,此時情況如下
                /*
                        x                   top_node

                        /                   /       \

                     top_node          node=null    right_node

                     /     \

                node=null   null

                */
                //因此無論何種情況都需要出棧刹泄,因為此時top_node的根節(jié)點和左葉子節(jié)點都已經(jīng)完全訪問,
                // 所以按照相同步驟遍歷訪問其右子樹
                if (!stack.isEmpty()) {
                    node = stack.pop();
                    node = node.rightNode;
                }
            }
        }
    }

    /**
     * 中序遍歷BST
     *
     * @param tree            BST根節(jié)點
     * @param traversalResult 遍歷結果
     */
    public void inOrderTraversal(BinaryNode<T> tree, List<T> traversalResult) {
        if (tree != null) {
            inOrderTraversal(tree.leftNode, traversalResult);
            addTraversalToResultList(tree, traversalResult);
            inOrderTraversal(tree.rightNode, traversalResult);
        }
    }

    /**
     * 非遞歸方式中序遍歷BST
     *
     * @param tree            BST根節(jié)點
     * @param traversalResult 遍歷結果
     */
    public void inOrderTraversalNoRecursive(BinaryNode<T> tree, List<T> traversalResult) {
        if (tree != null) {
            //使用一個棧怎爵,暫存訪問左右子樹的順序
            Stack<BinaryNode<T>> stack = new Stack<>();
            BinaryNode<T> node = tree;

            while (node != null || !stack.isEmpty()) {

                //一直遍歷到左子樹最左下角特石,邊遍歷邊保存根節(jié)點到棧中
                //需要借助保存的根節(jié)點進入右節(jié)點的遍歷過程
                while (node != null) {
                    stack.push(node);
                    node = node.leftNode;
                }
                //此時位于棧頂?shù)脑赜腥缦聝煞N情況,無論哪種情況都應將棧頂節(jié)點出棧鳖链,訪問該節(jié)點
                /*
                        x                   top_node

                        /                   /       \

                     top_node          node=null    right_node

                     /     \

                node=null   null

                */

                // 此時可以進行訪問棧頂元素
                if (!stack.isEmpty()) {
                    node = stack.pop();
                    addTraversalToResultList(node.clone(), traversalResult);
                    //如果訪問節(jié)點的根節(jié)點有右子樹县匠,則進行上層循環(huán),中序遍歷訪問右子樹的節(jié)點
                    node = node.rightNode;
                }
            }

        }
    }

    /**
     * 后序遍歷BST
     *
     * @param tree            BST根節(jié)點
     * @param traversalResult 遍歷結果
     */
    public void postOrderTraversal(BinaryNode<T> tree, List<T> traversalResult) {
        if (tree != null) {
            postOrderTraversal(tree.leftNode, traversalResult);
            postOrderTraversal(tree.rightNode, traversalResult);
            addTraversalToResultList(tree, traversalResult);
        }
    }

    /**
     * 非遞歸方式撒轮,后序遍歷BST
     *
     * @param tree            BST根節(jié)點
     * @param traversalResult 遍歷結果
     */
    public void postOrderTraversalNoRecursive(BinaryNode<T> tree, List<T> traversalResult) {
        if (tree != null) {
            //記錄原BST的左右子樹訪問順序
            Stack<BinaryNode<T>> stack = new Stack<>();
            //記錄后續(xù)遍歷的遍歷順序
            Stack<BinaryNode<T>> output = new Stack<>();

            stack.push(tree);
            while (!stack.isEmpty()) {
                BinaryNode<T> pop = stack.pop();

                //將根節(jié)點首先入棧到output棧底乞旦,根節(jié)點最后訪問
                output.push(pop);
                if (pop.leftNode != null) {
                    //leftNode節(jié)點先入棧stack,后入output棧题山,符合left-right-root的訪問順序
                    stack.push(pop.leftNode);
                }
                if (pop.rightNode != null) {
                    //right節(jié)點后入棧stack兰粉,先入output棧,符合left-right-root的訪問順序
                    stack.push(pop.rightNode);
                }
            }

            while (!output.isEmpty()) {
                addTraversalToResultList(output.pop(), traversalResult);
            }
        }
    }

    /**
     * 廣度優(yōu)先遍歷
     *
     * @param tree            BST
     * @param traversalResult 遍歷結果
     */
    public void breadthTraversal(BinaryNode<T> tree, List<T> traversalResult) {
        Queue<BinaryNode<T>> queue = new LinkedList<>();
        queue.add(tree);
        while (!queue.isEmpty()) {
            BinaryNode<T> node = queue.remove();
            addTraversalToResultList(node, traversalResult);
            if (node.leftNode != null) {
                queue.add(node.leftNode);
            }
            if (node.rightNode != null) {
                queue.add(node.rightNode);
            }
        }
    }

    /**
     * 對二叉排序樹進行升序排序顶瞳,即是對BST進行中序遍歷的結果
     *
     * @param tree       根節(jié)點
     * @param sortedData 升序排序的結果
     */
    public void sort(BinaryNode<T> tree, List<T> sortedData) {
        inOrderTraversal(tree, sortedData);
    }


    private void addTraversalToResultList(BinaryNode<T> node, List<T> traversalResult) {
        for (int i = 0; i < node.count.intValue(); i++) {
            traversalResult.add(node.data);
        }
    }

}

/**
 * 二叉查找樹的節(jié)點數(shù)據(jù)結構
 *
 * @param <T> 數(shù)據(jù)節(jié)點的類型玖姑,必須實現(xiàn)Comparable接口
 */
class BinaryNode<T extends Comparable<T>> {
    /**
     * 數(shù)據(jù)類型
     */
    T data;

    /**
     * 左節(jié)點
     */
    BinaryNode<T> leftNode;

    /**
     * 右節(jié)點
     */
    BinaryNode<T> rightNode;

    /**
     * 父節(jié)點
     */
    BinaryNode<T> parentNode;

    /**
     * 數(shù)據(jù)data出現(xiàn)的次數(shù),
     * 用于支持BST可以插入相同data的值慨菱,
     * 以便節(jié)點數(shù)據(jù)值的比較
     */
    AtomicInteger count;


    public BinaryNode(T data) {
        this.data = data;
    }

    public BinaryNode(T data, BinaryNode<T> leftNode, BinaryNode<T> rightNode, BinaryNode<T> parentNode) {
        this.data = data;
        this.leftNode = leftNode;
        this.rightNode = rightNode;
        this.parentNode = parentNode;
        this.count = new AtomicInteger(1);
    }

    @Override
    protected BinaryNode<T> clone() {
        BinaryNode<T> clonedNode = new BinaryNode<>(this.data, null, null, null);
        clonedNode.count = new AtomicInteger(this.count.intValue());
        return clonedNode;
    }
}

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末焰络,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子符喝,更是在濱河造成了極大的恐慌闪彼,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,548評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異畏腕,居然都是意外死亡缴川,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,497評論 3 399
  • 文/潘曉璐 我一進店門描馅,熙熙樓的掌柜王于貴愁眉苦臉地迎上來把夸,“玉大人,你說我怎么就攤上這事铭污×等眨” “怎么了?”我有些...
    開封第一講書人閱讀 167,990評論 0 360
  • 文/不壞的土叔 我叫張陵嘹狞,是天一觀的道長谚鄙。 經(jīng)常有香客問我,道長刁绒,這世上最難降的妖魔是什么闷营? 我笑而不...
    開封第一講書人閱讀 59,618評論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮知市,結果婚禮上傻盟,老公的妹妹穿的比我還像新娘。我一直安慰自己嫂丙,他們只是感情好娘赴,可當我...
    茶點故事閱讀 68,618評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著跟啤,像睡著了一般诽表。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上隅肥,一...
    開封第一講書人閱讀 52,246評論 1 308
  • 那天竿奏,我揣著相機與錄音,去河邊找鬼腥放。 笑死泛啸,一個胖子當著我的面吹牛,可吹牛的內容都是我干的秃症。 我是一名探鬼主播候址,決...
    沈念sama閱讀 40,819評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼种柑!你這毒婦竟也來了岗仑?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,725評論 0 276
  • 序言:老撾萬榮一對情侶失蹤聚请,失蹤者是張志新(化名)和其女友劉穎荠雕,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,268評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡舞虱,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,356評論 3 340
  • 正文 我和宋清朗相戀三年欢际,在試婚紗的時候發(fā)現(xiàn)自己被綠了母市。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片矾兜。...
    茶點故事閱讀 40,488評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖患久,靈堂內的尸體忽然破棺而出椅寺,到底是詐尸還是另有隱情,我是刑警寧澤蒋失,帶...
    沈念sama閱讀 36,181評論 5 350
  • 正文 年R本政府宣布返帕,位于F島的核電站,受9級特大地震影響篙挽,放射性物質發(fā)生泄漏荆萤。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,862評論 3 333
  • 文/蒙蒙 一铣卡、第九天 我趴在偏房一處隱蔽的房頂上張望链韭。 院中可真熱鬧,春花似錦煮落、人聲如沸敞峭。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,331評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽旋讹。三九已至,卻和暖如春轿衔,著一層夾襖步出監(jiān)牢的瞬間沉迹,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,445評論 1 272
  • 我被黑心中介騙來泰國打工害驹, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留胚股,地道東北人。 一個月前我還...
    沈念sama閱讀 48,897評論 3 376
  • 正文 我出身青樓裙秋,卻偏偏與公主長得像琅拌,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子摘刑,可洞房花燭夜當晚...
    茶點故事閱讀 45,500評論 2 359

推薦閱讀更多精彩內容

  • 數(shù)據(jù)結構與算法--從平衡二叉樹(AVL)到紅黑樹 上節(jié)學習了二叉查找樹进宝。算法的性能取決于樹的形狀,而樹的形狀取決于...
    sunhaiyu閱讀 7,651評論 4 32
  • 數(shù)據(jù)結構與算法--二叉查找樹 上節(jié)中學習了基于鏈表的順序查找和有序數(shù)組的二分查找枷恕,其中前者在插入刪除時更有優(yōu)勢党晋,而...
    sunhaiyu閱讀 1,873評論 0 9
  • 定義 若任意節(jié)點的左子樹不空,則左子樹上所有節(jié)點的值均小于它的根節(jié)點的值; 若任意節(jié)點的右子樹不空未玻,則右子樹上所有...
    None_Ling閱讀 647評論 0 1
  • 第一章 緒論 什么是數(shù)據(jù)結構灾而? 數(shù)據(jù)結構的定義:數(shù)據(jù)結構是相互之間存在一種或多種特定關系的數(shù)據(jù)元素的集合。 第二章...
    SeanCheney閱讀 5,781評論 0 19
  • 是非止于智者 一言折盡平生福 總有為活躍氣氛而充當喜感角色的扳剿,而喜劇的本質就是故意顯得又蠢又笨旁趟,...
    賀氏育發(fā)堂閱讀 269評論 0 0