AVL樹

介紹

AVL樹是最常見(jiàn)的自平衡二叉搜索樹了系吩。關(guān)于二叉搜索樹大致的描述如下:

  1. 每個(gè)節(jié)點(diǎn)只有左右兩個(gè)子節(jié)點(diǎn)
  2. 每個(gè)節(jié)點(diǎn)的左子節(jié)點(diǎn)的值小于該節(jié)點(diǎn)值求晶,每個(gè)節(jié)點(diǎn)的右子節(jié)點(diǎn)的值大于該節(jié)點(diǎn)的值

AVL樹是一顆平衡二叉樹,所謂平衡的概念如下:
二叉搜索樹中任何一個(gè)節(jié)點(diǎn)舵变,左子樹的高度與右子樹的高度差小于等于1。子樹的高度定義為子樹的左右子樹中高度大的值瘦穆。

當(dāng)一個(gè)二叉搜索樹為平衡二叉樹的時(shí)候纪隙,查詢效率是很高的,時(shí)間復(fù)雜度為O(lgn)扛或。但如果對(duì)這個(gè)樹做了多次的插入與刪除操作后绵咱,這個(gè)樹就很可能失去了平衡,變成了一個(gè)鏈表結(jié)構(gòu)熙兔。

AVL樹插入與刪除節(jié)點(diǎn)后都需要重新計(jì)算當(dāng)前節(jié)點(diǎn)是否平衡悲伶,如果不平衡艾恼,則通過(guò)旋轉(zhuǎn)來(lái)使節(jié)點(diǎn)保持平衡。

旋轉(zhuǎn)

旋轉(zhuǎn)有四種情況麸锉,左旋轉(zhuǎn)兩種钠绍,右旋轉(zhuǎn)兩種,其中左旋轉(zhuǎn)與右旋轉(zhuǎn)是鏡對(duì)稱動(dòng)作花沉,我們只看左旋轉(zhuǎn)就好柳爽。參考如下兩張圖,應(yīng)該可以很清晰的說(shuō)明兩種左旋轉(zhuǎn)的過(guò)程碱屁。注意:旋轉(zhuǎn)前后磷脯,顏色相同的節(jié)點(diǎn)代表了值相同的節(jié)點(diǎn)。 右旋的操作娩脾,可以自己去畫一下赵誓。

左旋一

左旋一

左旋二

左旋二

關(guān)于刪除

突然發(fā)現(xiàn),二叉查找樹中節(jié)點(diǎn)的刪除其實(shí)也不是一個(gè)特別簡(jiǎn)單的過(guò)程柿赊。所以單開一個(gè)小節(jié)來(lái)描述一下俩功。

通用方法

當(dāng)需要?jiǎng)h除一個(gè)節(jié)點(diǎn)的時(shí)候我們需要的操作如下:

  1. 持有該節(jié)點(diǎn)的父節(jié)點(diǎn)與子節(jié)點(diǎn)
  2. 斷開父節(jié)點(diǎn)到該節(jié)點(diǎn)的連接,以及該節(jié)點(diǎn)到子節(jié)點(diǎn)的連接
  3. 如果該節(jié)點(diǎn)沒(méi)有右子節(jié)點(diǎn)闹瞧,則將該節(jié)點(diǎn)的左子節(jié)點(diǎn)設(shè)置為父節(jié)點(diǎn)的左子節(jié)點(diǎn)绑雄,結(jié)束
  4. 如果該節(jié)點(diǎn)有右子節(jié)點(diǎn),則需要從右子節(jié)點(diǎn)中找到最小值的節(jié)點(diǎn)奥邮,然后做如下操作
    4.1 如果最小值節(jié)點(diǎn)就是當(dāng)前節(jié)點(diǎn)的右子節(jié)點(diǎn)万牺,則將最小值節(jié)點(diǎn)設(shè)置為父節(jié)點(diǎn)的左子節(jié)點(diǎn),然后把原左子節(jié)點(diǎn)設(shè)置為最小值節(jié)點(diǎn)的左子節(jié)點(diǎn)洽腺,結(jié)束
    4.2 如果最小值節(jié)點(diǎn)不是當(dāng)前節(jié)點(diǎn)的右子節(jié)點(diǎn)脚粟,則需要在右子節(jié)點(diǎn)的子樹中刪除最小值節(jié)點(diǎn),然后創(chuàng)建新的最小時(shí)節(jié)點(diǎn)蘸朋,將新的最小時(shí)節(jié)點(diǎn)設(shè)置為父節(jié)點(diǎn)的左子節(jié)點(diǎn)核无,然后把原左子節(jié)點(diǎn)設(shè)置為新的最小值節(jié)點(diǎn)的左子節(jié)點(diǎn),右子節(jié)點(diǎn)為新的最小值節(jié)點(diǎn)的右子節(jié)點(diǎn)藕坯,結(jié)束团南。

看圖

紅色的節(jié)點(diǎn)表示刪除后需要重新計(jì)算高度并判斷是否需要旋轉(zhuǎn)的節(jié)點(diǎn)

步驟3的刪除操作

步驟3的場(chǎng)景

步驟4.1的刪除操作

步驟4.1的場(chǎng)景

步驟4.2的刪除操作

步驟4.2的場(chǎng)景

這個(gè)圖里,oldRight到minNode的虛線表示的意思是minNode不一定是oldRight的直接左子節(jié)點(diǎn)炼彪,有可能是很多層之后的一個(gè)子節(jié)點(diǎn)吐根。但肯定在oldRight為根的樹中,它是最左邊的辐马。

Talk is cheap

/**
 * AVL樹節(jié)點(diǎn)類
 * 節(jié)點(diǎn)中持有的對(duì)象的類必須實(shí)現(xiàn)Comparable接口
 * 此類中封裝了計(jì)算子樹高度拷橘,計(jì)算自身節(jié)點(diǎn)高度,判斷是否需要旋轉(zhuǎn),以及旋轉(zhuǎn)實(shí)現(xiàn)的方法 作為樹節(jié)點(diǎn)的基礎(chǔ)功能
 *
 * @author goofy.wang
 */
public class AVLNode<T extends Comparable> implements Comparable<AVLNode<T>>{

    private T value;

    private int leftDepth;

    private int rightDepth;

    private AVLNode<T> left;

    private AVLNode<T> right;

    public AVLNode(T value) {
        this(value, null, null);
    }


    public AVLNode(T value, AVLNode<T> left, AVLNode<T> right) {
        this.value = value;
        this.left = left;
        this.right = right;
    }

    public AVLNode<T> getLeft() {
        return this.left;
    }

    public void setLeft(AVLNode<T> left) {
        this.left = left;
    }

    public AVLNode<T> getRight() {
        return this.right;
    }

    public void setRight(AVLNode<T> right) {
        this.right = right;
    }

    public void setValue(T value){
        this.value = value;
    }


    public T getValue(){
        return this.value;
    }


    public boolean hasLeft(){
        return this.left != null;
    }


    public boolean hasRight(){
        return this.right != null;
    }

    /**
     * 獲取當(dāng)前節(jié)點(diǎn)深度的方法
     * @return
     */
    public int getDepth(){
        int maxSubDepth = this.leftDepth > this.rightDepth ? this.leftDepth : this.rightDepth;
        return maxSubDepth + 1;
    }

    /**
     * 計(jì)算左右子樹深度的方法
     */
    public void calculateDepth(){
        this.leftDepth = this.left == null ?  0 :  this.left.getDepth();
        this.rightDepth = this.right == null ?  0 :  this.right.getDepth();
    }

    /**
     * 判斷是否需要旋轉(zhuǎn)
     * @return
     */
    public boolean needRotate(){
        return Math.abs(this.leftDepth - this.rightDepth) > 1;
    }

    /**
     * 旋轉(zhuǎn)方法冗疮,內(nèi)部判斷需要左旋還是右旋
     */
    public void rotate(){
        if(this.leftDepth > this.rightDepth){
            this.leftRotateToRight();
        }else{
            this.rightRotateToLeft();
        }
        this.calculateDepth();
    }

    /**
     * 左旋方法
     * if 實(shí)現(xiàn)旋轉(zhuǎn)一
     * else 實(shí)現(xiàn)旋轉(zhuǎn)二
     */
    private void leftRotateToRight(){

        AVLNode<T> leftRight = this.left.getRight();
        T currentValue = this.getValue();

        if(leftRight == null){
            T leftValue = this.left.getValue();
            AVLNode<T> newRight = new AVLNode<T>(currentValue, null, this.getRight());
            newRight.calculateDepth();
            this.setValue(leftValue);
            this.setRight(newRight);
            this.setLeft(this.getLeft().getLeft());
        }else{
            T leftRightValue = leftRight.getValue();
            AVLNode<T> leftRightLeft = leftRight.getLeft();
            AVLNode<T> leftRightRight = leftRight.getRight();
            AVLNode<T> newRight = new AVLNode<T>(currentValue, leftRightRight, this.getRight());
            newRight.calculateDepth();
            this.setValue(leftRightValue);
            this.setRight(newRight);
            this.left.setRight(leftRightLeft);
            this.left.calculateDepth();
        }
    }


    /**
     * 右旋方法萄唇,與左旋鏡對(duì)稱
     */
    private void rightRotateToLeft(){

        AVLNode<T>  rightLeft = this.right.getLeft();
        T currentValue = this.getValue();

        if(rightLeft == null){
            T rightValue = this.right.getValue();
            AVLNode<T> newLeft = new AVLNode<T>(currentValue, this.left, null);
            newLeft.calculateDepth();
            this.setValue(rightValue);
            this.setLeft(newLeft);
            this.setRight(this.right.getRight());
        }else{
            T rightLeftValue = rightLeft.getValue();
            AVLNode<T> rightLeftLeft = rightLeft.getLeft();
            AVLNode<T> rightLeftRight = rightLeft.getRight();
            AVLNode<T> newLeft = new AVLNode<T>(currentValue, this.left,  rightLeftLeft);
            newLeft.calculateDepth();
            this.setValue(rightLeftValue);
            this.setLeft(newLeft);
            this.right.setLeft(rightLeftRight);
            this.right.calculateDepth();
        }
    }

    /**
     * 比較方法
     * @param o
     * @return
     */
    @Override
    public int compareTo(AVLNode<T> o) {
        return this.value.compareTo(o.getValue());
    }
}

/**
 * AVL樹類
 * 此類用于組織AVLNode節(jié)點(diǎn),使得這些節(jié)點(diǎn)以正確的平衡二叉樹方式關(guān)聯(lián)在一起
 * 并在添加與刪除元素后术幔,控制樹節(jié)點(diǎn)完成高度計(jì)算另萤,平衡性判斷,以及旋轉(zhuǎn)等行為
 *
 * @author goofy.wang
 */
public class AVLTree<T extends Comparable> {

    private AVLNode<T> root;

    /**
     * 添加節(jié)點(diǎn)的方法诅挑,如果值在樹中存在相等的節(jié)點(diǎn)仲墨,則將此節(jié)點(diǎn)中的值替換為當(dāng)前值
     * @param nodeValue
     */
    public void append(T nodeValue){
        AVLNode<T> newNode = new AVLNode<T>(nodeValue);
        if(this.root == null){
            this.root = newNode;
        }else{
            this.innerAppend(this.root, newNode);
        }
    }

    /**
     * 判斷樹中是否存在某個(gè)值對(duì)象的方法
     * @param nodeValue
     * @return
     */
    public boolean contains(T nodeValue){
        if(this.root == null){
            return false;
        }
        AVLNode<T> condition = new AVLNode<T>(nodeValue);
        if(root.compareTo(condition) == 0){
            return true;
        }else{
            return this.containsInChilren(this.root, condition);
        }
    }

    /**
     * 從樹中刪除某個(gè)值對(duì)象的方法
     * @param nodeValue
     * @return 如果存在該元素且刪除完成返回true,如果不存在該元素則返回false
     */
    public boolean remove(T nodeValue){

        if(root == null){
            return false;
        }

        AVLNode<T> toBeRemove = new AVLNode<T>(nodeValue);
        if(root.compareTo(toBeRemove) == 0){
            if(root.hasRight()){

                AVLNode<T> minumumNodeFromRight = this.getMinumumNode(this.root.getRight());
                if(this.root.getRight().compareTo(minumumNodeFromRight) == 0){
                    AVLNode<T> left = this.root.getLeft();
                    this.root.getRight().setLeft(left);
                    this.root = this.root.getRight();
                }else{
                    this.innerDelete(this.root.getRight(), minumumNodeFromRight);
                    minumumNodeFromRight.setRight(this.root.getRight());
                    minumumNodeFromRight.setLeft(this.root.getLeft());
                    this.root = minumumNodeFromRight;
                }
                this.calcAndRotateIfNeeded(this.root);
            }else{
                this.root = this.root.getLeft();
            }
        }else{
            this.innerDelete(this.root, toBeRemove);
        }
        return false;
    }

    private void innerAppend(AVLNode<T> currentNode, AVLNode<T> newNode){
        int compareResult = currentNode.compareTo(newNode);
        if(compareResult > 0){
            if(currentNode.hasLeft()){
                this.innerAppend(currentNode.getLeft(), newNode);
            }else{
                currentNode.setLeft(newNode);
            }
        }else if(compareResult < 0){
            if(currentNode.hasRight()){
                this.innerAppend(currentNode.getRight(), newNode);
            }else{
                currentNode.setRight(newNode);
            }
        }else{
            currentNode.setValue(newNode.getValue());
        }

        /**
         *
         * 此方法是標(biāo)準(zhǔn)的二叉樹插入操作揍障,唯一要注意的是下面這行代碼
         * 因?yàn)槲覀兪沁f歸調(diào)用innerAppend方法,直到把要插入的節(jié)點(diǎn)放到正確的位置上
         * 所以在節(jié)點(diǎn)被放置完畢后,此節(jié)點(diǎn)的所有父節(jié)點(diǎn)都需要重新計(jì)算一次高度俩由,并在必要時(shí)進(jìn)行旋轉(zhuǎn)
         *
         * 只有一個(gè)例外毒嫡,就是當(dāng)節(jié)點(diǎn)是更新操作的時(shí)候,是不需要執(zhí)行下面這行代碼的
         * 其實(shí)我們可以通過(guò)boolean變量來(lái)控制是否要執(zhí)行幻梯,不過(guò)我比較懶
         *
         */
        this.calcAndRotateIfNeeded(currentNode);
    }


    private boolean containsInChilren(AVLNode<T> currentNode, AVLNode<T> condition){

        if(currentNode == null){
            return false;
        }

        int compareResult = currentNode.compareTo(condition);
        if(compareResult > 0){
            return this.containsInChilren(currentNode.getLeft(), condition);
        }else if(compareResult < 0){
            return this.containsInChilren(currentNode.getRight(), condition);
        }else{
            return true;
        }
    }


    /**
     * 刪除方法兜畸,因?yàn)槲覀冊(cè)趫?zhí)行刪除邏輯的時(shí)候,需要處理當(dāng)前節(jié)點(diǎn)的父節(jié)點(diǎn)與子節(jié)點(diǎn)的關(guān)系碘梢,所以把父節(jié)點(diǎn)作為參數(shù)傳遞進(jìn)來(lái)
     * 方法內(nèi)不判斷是否要?jiǎng)h除父節(jié)點(diǎn)咬摇,而是判斷是否要?jiǎng)h除父節(jié)點(diǎn)的子節(jié)點(diǎn)
     * @param parentNode
     * @param condition
     * @return
     */
    private boolean innerDelete(AVLNode<T> parentNode, AVLNode<T> condition){

        int compareResult = parentNode.compareTo(condition);
        boolean deleted = false;

        if(compareResult > 0 && parentNode.hasLeft()){
            /**
             * 如果父節(jié)點(diǎn)比當(dāng)前要?jiǎng)h除的節(jié)點(diǎn)大,并且當(dāng)前父節(jié)點(diǎn)存在左節(jié)點(diǎn)
             * 則判斷當(dāng)前父節(jié)點(diǎn)的左節(jié)點(diǎn)是否是要?jiǎng)h除的節(jié)點(diǎn)煞躬,如果是就刪除當(dāng)前父節(jié)點(diǎn)的左節(jié)點(diǎn)
             * 如果不是則遞歸
             */
            AVLNode<T> leftSub = parentNode.getLeft();
            if(leftSub.compareTo(condition) == 0){
                this.realDeleteLeft(parentNode);
                deleted = true;
            }else{
                deleted = this.innerDelete(leftSub, condition);
            }
        }else if(parentNode.hasRight()){
            AVLNode<T> rightSub = parentNode.getRight();
            if(rightSub.compareTo(condition) == 0){
                this.realDeleteRight(parentNode);
                deleted = true;
            }else{
                deleted = this.innerDelete(rightSub, condition);
            }
        }

        /**
         * 如果確實(shí)刪除了當(dāng)前節(jié)點(diǎn)的某個(gè)層級(jí)子節(jié)點(diǎn)肛鹏,則當(dāng)前節(jié)點(diǎn)需要重新計(jì)算高度,并有可能完成旋轉(zhuǎn)
         */
        if(deleted){
            this.calcAndRotateIfNeeded(parentNode);
        }
        return deleted;
    }

    private void realDeleteLeft(AVLNode<T> parentNode){

        AVLNode<T> toBeDelete = parentNode.getLeft();
        AVLNode<T> oldLeft = toBeDelete.getLeft();
        AVLNode<T> oldRight = toBeDelete.getRight();

        if(oldRight == null) {
            /**
             * 當(dāng)前要?jiǎng)h除的節(jié)點(diǎn)不存在右子樹
             * 刪除邏輯3的場(chǎng)景
             */
            parentNode.setLeft(oldLeft);
        }else{
            AVLNode<T> minumumNodeFromRight = this.getMinumumNode(oldRight);
            if(minumumNodeFromRight.compareTo(oldRight) == 0){
                /**
                 * 要?jiǎng)h除的右子樹的根節(jié)點(diǎn)沒(méi)有左節(jié)點(diǎn)
                 * 刪除邏輯4.1的場(chǎng)景
                 */
                parentNode.setLeft(oldRight);
                oldRight.setLeft(oldLeft);
            }else{
                /**
                 * 要?jiǎng)h除的節(jié)點(diǎn)的右子樹的根節(jié)點(diǎn)存在比根節(jié)點(diǎn)還小的子節(jié)點(diǎn)
                 * 但是這個(gè)要找的節(jié)點(diǎn)的位置還不確定恩沛,所以我偷懶用遞歸從右子樹中刪除最小節(jié)點(diǎn)
                 * 刪除邏輯4.2的場(chǎng)景
                 */
                this.innerDelete(oldRight, minumumNodeFromRight);
                parentNode.setLeft(minumumNodeFromRight);
                minumumNodeFromRight.setLeft(oldLeft);
                minumumNodeFromRight.setLeft(oldRight);
            }
            this.calcAndRotateIfNeeded(parentNode.getLeft());
        }
    }


    private void realDeleteRight(AVLNode<T> parentNode){

        AVLNode<T> toBeDelete = parentNode.getRight();
        AVLNode<T> oldLeft = toBeDelete.getLeft();
        AVLNode<T> oldRight = toBeDelete.getRight();

        if(oldRight == null){
            parentNode.setRight(oldLeft);
        }else{

            AVLNode<T> minumumNodeFromRight = this.getMinumumNode(oldRight);
            if(oldRight.compareTo(minumumNodeFromRight) == 0) {
                /**
                 * 走入這個(gè)分支在扰,說(shuō)明要?jiǎng)h除的節(jié)點(diǎn)的右子樹的根節(jié)點(diǎn)沒(méi)有左子樹
                 */
                parentNode.setRight(oldRight);
                oldRight.setLeft(oldLeft);
            }else{
                this.innerDelete(oldRight, minumumNodeFromRight);
                parentNode.setRight(minumumNodeFromRight);
                minumumNodeFromRight.setRight(oldRight);
                minumumNodeFromRight.setLeft(oldLeft);
            }

            this.calcAndRotateIfNeeded(parentNode.getRight());
        }
    }

    /**
     * 給定一個(gè)節(jié)點(diǎn),從這個(gè)節(jié)點(diǎn)和這個(gè)節(jié)點(diǎn)的所有子節(jié)點(diǎn)中找到值最小的節(jié)點(diǎn)
     * @param currentNode
     * @return
     */
    private AVLNode<T> getMinumumNode(AVLNode<T> currentNode){
        if(currentNode.hasLeft()){
            return this.getMinumumNode(currentNode.getLeft());
        }else{
            return currentNode;
        }
    }

    /**
     * 重新計(jì)算節(jié)點(diǎn)高度雷客,并在需要旋轉(zhuǎn)時(shí)控制節(jié)點(diǎn)進(jìn)行旋轉(zhuǎn)的方法
     * 當(dāng)某個(gè)節(jié)點(diǎn)的子節(jié)點(diǎn)高度發(fā)生變化的時(shí)候芒珠,會(huì)調(diào)用這個(gè)方法
     * @param node
     */
    private void calcAndRotateIfNeeded(AVLNode<T> node){
        node.calculateDepth();
        if(node.needRotate()){
            node.rotate();
        }
    }

}

預(yù)告

接下來(lái)我想寫的是多路查找樹中的2-3樹

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市搅裙,隨后出現(xiàn)的幾起案子皱卓,更是在濱河造成了極大的恐慌,老刑警劉巖部逮,帶你破解...
    沈念sama閱讀 218,640評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件娜汁,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡甥啄,警方通過(guò)查閱死者的電腦和手機(jī)存炮,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,254評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人穆桂,你說(shuō)我怎么就攤上這事宫盔。” “怎么了享完?”我有些...
    開封第一講書人閱讀 165,011評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵灼芭,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我般又,道長(zhǎng)彼绷,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,755評(píng)論 1 294
  • 正文 為了忘掉前任茴迁,我火速辦了婚禮寄悯,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘堕义。我一直安慰自己猜旬,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,774評(píng)論 6 392
  • 文/花漫 我一把揭開白布倦卖。 她就那樣靜靜地躺著洒擦,像睡著了一般。 火紅的嫁衣襯著肌膚如雪怕膛。 梳的紋絲不亂的頭發(fā)上熟嫩,一...
    開封第一講書人閱讀 51,610評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音褐捻,去河邊找鬼掸茅。 笑死,一個(gè)胖子當(dāng)著我的面吹牛舍扰,可吹牛的內(nèi)容都是我干的倦蚪。 我是一名探鬼主播,決...
    沈念sama閱讀 40,352評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼边苹,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼陵且!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起个束,我...
    開封第一講書人閱讀 39,257評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤慕购,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后茬底,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體沪悲,經(jīng)...
    沈念sama閱讀 45,717評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,894評(píng)論 3 336
  • 正文 我和宋清朗相戀三年阱表,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了殿如。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片贡珊。...
    茶點(diǎn)故事閱讀 40,021評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖涉馁,靈堂內(nèi)的尸體忽然破棺而出门岔,到底是詐尸還是另有隱情,我是刑警寧澤烤送,帶...
    沈念sama閱讀 35,735評(píng)論 5 346
  • 正文 年R本政府宣布寒随,位于F島的核電站,受9級(jí)特大地震影響帮坚,放射性物質(zhì)發(fā)生泄漏妻往。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,354評(píng)論 3 330
  • 文/蒙蒙 一试和、第九天 我趴在偏房一處隱蔽的房頂上張望讯泣。 院中可真熱鬧,春花似錦阅悍、人聲如沸钉赁。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,936評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)孤钦。三九已至悦昵,卻和暖如春肴茄,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背但指。 一陣腳步聲響...
    開封第一講書人閱讀 33,054評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工寡痰, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人棋凳。 一個(gè)月前我還...
    沈念sama閱讀 48,224評(píng)論 3 371
  • 正文 我出身青樓拦坠,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親剩岳。 傳聞我的和親對(duì)象是個(gè)殘疾皇子贞滨,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,974評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容