平衡樹

百科定義

平衡二叉樹(Balanced Binary Tree)具有以下性質(zhì):它是一 棵空樹或它的左右兩個(gè)子樹的高度差的絕對(duì)值不超過(guò)1单芜,并且左右兩個(gè)子樹都是一棵平衡二叉樹壶硅。

平衡因子
二叉樹上節(jié)點(diǎn)的左子樹深度減去右子樹深度的值稱為平衡因子BF(Balance Factor)

平衡二叉樹的實(shí)現(xiàn)

調(diào)整平衡的基本思想:
當(dāng)在二叉排序樹中插入一個(gè)節(jié)點(diǎn)時(shí),首先檢查是否因插入而破壞了平衡募逞,若破壞鬼譬,則找出其中的最小不平衡二叉樹焚鹊,在保持二叉排序樹特性的情況下刃宵,調(diào)整最小不平衡子樹中節(jié)點(diǎn)之間的關(guān)系衡瓶,以達(dá)到新的平衡。
所謂最小不平衡子樹牲证,指離插入節(jié)點(diǎn)最近且以平衡因子的絕對(duì)值大于1的節(jié)點(diǎn)作為根的子樹哮针。

實(shí)現(xiàn)平衡的方法:

. 左旋

image.png

上圖中,最小不平衡子樹為結(jié)點(diǎn)3下面的樹坦袍,結(jié)點(diǎn)3 的平衡因子BF為-2十厢。
平衡方法為:以結(jié)點(diǎn)3進(jìn)行左旋,旋轉(zhuǎn)結(jié)果為圖8捂齐。旋轉(zhuǎn)后變?yōu)槠胶舛鏄?/p>


旋轉(zhuǎn)方法


左旋.png

如上圖蛮放,我們對(duì)X進(jìn)行左旋,為了方便表達(dá)辛燥,做如下初始定義筛武,保存左旋前節(jié)點(diǎn)的數(shù)據(jù):

  • X為node
  • X的父結(jié)點(diǎn)為nodeP
  • X的左結(jié)點(diǎn)為nodeL
  • X的右節(jié)點(diǎn)為NodeR
  • X的右子樹的左節(jié)點(diǎn)為nodeRL
  • X的右子樹的右節(jié)點(diǎn)位nodeRR

變換步驟:

    1. node的右節(jié)點(diǎn)改為nodeRL缝其,nodeRL的父結(jié)點(diǎn)改為node
    1. 判斷node屬于nodeP的左孩子還是右孩子挎塌,nodeP指向nodeR,nodeR的父親結(jié)點(diǎn)改為nodeP
    1. nodeR指向node内边,node的父結(jié)點(diǎn)變?yōu)閚odeR
public void left_rotate(Node<E> x) {
        if (x != null) {
            Node<E> y = x.right;
            // step 1
            x.right = y.left;
            if (y.left != null) {
                y.left.parent = x;
            }
             // step2
            y.parent = x.parent;
             if (x.parent == null) {
                root = y;
             } else {
                 if (x.parent.left == x) {
                     x.parent.left = y;
                    
                } else if(x.parent.right == x){
                    x.parent.right = y;
                }
             }
            //step 3
             y.left = x;
             x.parent = y;
        }
    }

. 右旋

image.png

上圖中榴都,節(jié)點(diǎn)3的平衡因子為2,左邊的多于右邊漠其,需要進(jìn)行右旋嘴高,把內(nèi)容分配到右邊一部分。

右旋.jpg

同左旋和屎,定義保存右旋前一些使用到節(jié)點(diǎn)的數(shù)據(jù)

  • Y 保存為node
  • Y的父結(jié)點(diǎn)保存為nodeP
  • Y的左節(jié)點(diǎn)保存為nodeL
  • Y的右節(jié)點(diǎn)保存為nodeR
  • Y的左節(jié)點(diǎn)的右孩子保存為nodeLR
  • Y的左節(jié)點(diǎn)的左孩子保存為nodeLL

步驟:

    1. node的右孩子變?yōu)閚odeLR拴驮,nodeLR父結(jié)點(diǎn)變?yōu)閚ode
    1. 判斷node屬于nodeP的左孩子還是右孩子,nodeP指向nodeL柴信,nodeL的父結(jié)點(diǎn)改為nodeP
    1. nodeL的右孩子變?yōu)閚ode套啤,node的父結(jié)點(diǎn)變?yōu)閚odeL

public void right_rotate(Node<E> y) {
        if (y != null) {
            Node<E> yl = y.left;
            
            //step1
            y.left= yl.right;
            if (yl.right != null) {
                yl.right.parent = y;
            }
            
            // step2
            yl.parent = y.parent;
            if (y.parent == null) {
                root = yl;
            } else {
                if (y.parent.left == y) {
                    y.parent.left = yl;
                } else if (y.parent.right == y) {
                    y.parent.right = yl;
                }
            }
            // step3
            yl.right = y;
            y.parent = yl;
        }
    }
    

插入結(jié)點(diǎn)時(shí)候,導(dǎo)致平衡樹失衡的情況分析随常,處理步驟

結(jié)點(diǎn)t的不平衡是因?yàn)樽笞訕溥^(guò)深

/**
     * 左平衡操作潜沦,即結(jié)點(diǎn)t的不平衡是因?yàn)樽笞訕溥^(guò)深
     * 
     * 1萄涯、如果新的結(jié)點(diǎn)插入到t的左孩子的左子樹中,則直接進(jìn)行右旋操作即可
     *              t                                      tl
     *             /  \         右旋操作                /      \
     *            tl   tr       ------------->       tll         t
     *           /  \                                /  \       /   \
     *          tll  tlr                           lcll  lclr  tlr   tr 
     *          /  \
     *       lcll  lclr
     *         
     * 2唆鸡、如果新的結(jié)點(diǎn)插入到t的左孩子的右子樹中涝影,則需要進(jìn)行分情況討論
     * 
     *  情況a:當(dāng)t的左孩子的右子樹根節(jié)點(diǎn)的balance = RIGHT_HIGH
     *          t                           t                           tlr
     *         /  \                        /  \                        /  \
     *        tl    6        左旋        tlr    6       右旋          tl    t
     *       /  \       ------->        /  \        -------->        /    /  \
     *      3  tlr                     tl    5                      3    5    6
     *            \                   /
     *             5                 3
     *  情況b:當(dāng)p的左孩子的右子樹根節(jié)點(diǎn)的balance = LEFT_HIGH
     * 
     *          t                              t                           tlr
     *         /  \                           /  \                         /  \
     *       tl    6            左旋        tlr    6          右旋        tl    t
     *      /  \        ------->            /          -------->         / \    \
     *     3  tlr                         tl                            3   5    6
     *          /                        / \
     *         5                        3   5
     * 
     *  情況c:當(dāng)p的左孩子的右子樹根節(jié)點(diǎn)的balance = EQUAL_HIGH
     * 
     *          t                               t                               tlr
     *         /  \                           /  \                             /   \
     *        tl    7         左旋           tlr    7          右旋           tl    t
     *        /  \          ------->        / \         -------->            / \   / \
     *       3  tlr                       tl   6                            3  5  6   7
     *           / \                     / \
     *          5   6                   3   5
     * */

結(jié)點(diǎn)t的不平衡是因?yàn)樽笞訕溥^(guò)深調(diào)整代碼

    private static final int LH = 1;
    private static final int RH = -1;
    private static final int EH = 0;
private void leftBalance(AVL<E>.Node<E> t) {
        Node<E> tl = t.left;
        switch (tl.balance) {
        case LH: // t 的左子樹的左邊有問題,直接右旋
            right_rotate(t);
            tl.balance = EH;
            t.balance = EH;
            break;
        case RH:
            Node<E> tlr = tl.right;
            switch (tlr.balance) {
            case RH:
                t.balance = EH;
                tlr.balance = EH;
                tl.balance = LH;
                break;
            case LH:
                t.balance = RH;
                tl.balance =EH;
                tlr.balance = EH;
                break;
            case EH:
                t.balance = EH;
                tl.balance = EH;
                tlr.balance =EH;
                break;
                //統(tǒng)一旋轉(zhuǎn)
            default:
                break;
            }
            left_rotate(t.left);
            right_rotate(t);
            break;
        default:
            break;
        }
        
    }

結(jié)點(diǎn)t的不平衡是因?yàn)橛易訕溥^(guò)深

/**
     * 右平衡操作争占,即結(jié)點(diǎn)t的不平衡是因?yàn)橛易訕溥^(guò)深
     * 
     * 1燃逻、如果新的結(jié)點(diǎn)插入到t的右孩子的右子樹中,則直接進(jìn)行左旋操作即可
     *       
     *          t                                            tr
     *        /   \                                        /     \
     *       l     tr              左旋操作               t       rr
     *           /   \          ----------->             / \     /   \
     *          rl    rr                                l  rl  rrl   rrr
     *              /   \
     *           rrl    rrr
     
     * 2燃乍、如果新的結(jié)點(diǎn)插入到p的右孩子的左子樹中唆樊,則需要進(jìn)行分情況討論 
     *  情況a:當(dāng)p的右孩子的左子樹根節(jié)點(diǎn)的balance = LEFT_HIGH
     * 
     *          t                       t                           trl
     *         /  \                    /  \                        /   \
     *        2   tr        右旋      2    trl        左旋        t     tr
     *            /  \     ------->  /     \        ------->     /  \    \
     *          trl   5             6      tr                   2   6     5 
     *          /                            \
     *         6                              5 
     * 情況b:當(dāng)p的右孩子的左子樹根節(jié)點(diǎn)的balance = RIGHT_HIGH
     * 
     *          t                       t                           trl
     *         /  \                    /  \                        /   \
     *        2   tr          右旋      2   trl           左旋     t    tr
     *            /  \     ------->          \      ------->     /    /  \
     *          trl   5                      tr                 2    6    5 
     *            \                          /  \
     *             6                        6    5
     
     * 情況C:當(dāng)p的右孩子的左子樹根節(jié)點(diǎn)的balance = EQUAL_HIGH
     *          t                       t                            trl
     *         /  \                    /  \                         /    \
     *        2   tr          右旋      2   trl       左旋         t      tr
     *            /  \     ------->       /  \      ------->      / \     / \
     *         trl    5                  6   tr                  2   6   7   5  
     *          / \                          /  \
     *         6   7                        7    5
     * */

結(jié)點(diǎn)t的不平衡是因?yàn)橛易訕溥^(guò)深調(diào)整代碼

    private static final int LH = 1;
    private static final int RH = -1;
    private static final int EH = 0;
private void rightBalance(AVL<E>.Node<E> t) {
        Node<E> tr = t.right;
        switch (tr.balance) {
        case RH:
            left_rotate(t);
            t.balance = EH;
            tr.balance = EH;
            break;
        case LH:
            Node<E> trl = tr.left;
            switch (trl.balance) {
            case LH:
                t.balance = EH;
                tr.balance = RH;
                break;
            case RH:
                t.balance = LH;
                tr.balance = EH;
                break;
            case EH:
                t.balance = EH;
                tr.balance = EH;
                break;
    
            }
            trl.balance = EH;
            right_rotate(t.right);
            left_rotate(t);
            break;
            
        default:
            break;
        }
        
    }

插入操作

public boolean inserElement(E element) {
        Node<E> t = root;
        if (t == null) {
            root = new Node<E>(element, null);
            size = 1;
            root.balance = 0;
            return true;
        } else {
            int cmp = 0;
            Node<E> parent;
            Comparable<? super E> e = (Comparable<? super E>)element;
            do {
                parent = t;
                cmp = e.compareTo(t.element);
                if (cmp < 0) {
                    t= t.left;
                } else if (cmp > 0) {
                    t= t.right;
                } else {
                    return false;
                }
            } while (t != null);
            Node<E> child = new Node<E>(element, parent);
            if (cmp < 0) {
                parent.left = child;
            } else {
                parent.right = child;
            }
            //節(jié)點(diǎn)已經(jīng)插入,
            // 檢查平衡刻蟹,回溯查找
            while (parent != null) {
                cmp = e.compareTo(parent.element);
                //元素在左邊插入
                if (cmp < 0) {
                    parent.balance++;
                } else{ //元素在右邊插入
                    parent.balance --;
                }
                
                if (parent.balance == 0) {
                    break;
                }
                if (Math.abs(parent.balance) == 2) {
                    //出現(xiàn)平衡問題
                    fixAfterInsertion(parent);
                    break;
                } else {
                    parent = parent.parent;
                }
            }
            size++;
            return true;
        }
    }

private void fixAfterInsertion(AVL<E>.Node<E> parent) {
        if (parent.balance == 2) {
            leftBalance(parent);
        } 
        if (parent.balance == -2) {
            rightBalance(parent);
        }
        
    }

全部代碼


import java.util.LinkedList;

public class AVL<E extends Comparable<E>> {

    private Node<E> root;
    private int size = 0;
    private static final int LH = 1;
    private static final int RH = -1;
    private static final int EH = 0;
    
    public void midOrderDisplay(Node root) {
        if (root == null) {
            return;
        } else {
            midOrderDisplay(root.left);
            System.out.println("midOrder: " + root.element);
            midOrderDisplay(root.right);
        }
    }
    /**
     * node insert,check balance and keep balance
     * @author LK
     *
     * @param <E>
     */
    public boolean inserElement(E element) {
        Node<E> t = root;
        if (t == null) {
            root = new Node<E>(element, null);
            size = 1;
            root.balance = 0;
            return true;
        } else {
            int cmp = 0;
            Node<E> parent;
            Comparable<? super E> e = (Comparable<? super E>)element;
            do {
                parent = t;
                cmp = e.compareTo(t.element);
                if (cmp < 0) {
                    t= t.left;
                } else if (cmp > 0) {
                    t= t.right;
                } else {
                    return false;
                }
            } while (t != null);
            Node<E> child = new Node<E>(element, parent);
            if (cmp < 0) {
                parent.left = child;
            } else {
                parent.right = child;
            }
            //節(jié)點(diǎn)已經(jīng)插入逗旁,
            // 檢查平衡,回溯查找
            while (parent != null) {
                cmp = e.compareTo(parent.element);
                //元素在左邊插入
                if (cmp < 0) {
                    parent.balance++;
                } else{ //元素在右邊插入
                    parent.balance --;
                }
                
                if (parent.balance == 0) {
                    break;
                }
                if (Math.abs(parent.balance) == 2) {
                    //出現(xiàn)平衡問題
                    fixAfterInsertion(parent);
                    break;
                } else {
                    parent = parent.parent;
                }
            }
            size++;
            return true;
        }
    }
    
    private void fixAfterInsertion(AVL<E>.Node<E> parent) {
        if (parent.balance == 2) {
            leftBalance(parent);
        } 
        if (parent.balance == -2) {
            rightBalance(parent);
        }
        
    }

    private void rightBalance(AVL<E>.Node<E> t) {
        Node<E> tr = t.right;
        switch (tr.balance) {
        case RH:
            left_rotate(t);
            t.balance = EH;
            tr.balance = EH;
            break;
        case LH:
            Node<E> trl = tr.left;
            switch (trl.balance) {
            case LH:
                t.balance = EH;
                tr.balance = RH;
                break;
            case RH:
                t.balance = LH;
                tr.balance = EH;
                break;
            case EH:
                t.balance = EH;
                tr.balance = EH;
                break;
    
            }
            trl.balance = EH;
            right_rotate(t.right);
            left_rotate(t);
            break;
            
        default:
            break;
        }
        
    }

    private void left_rotate(AVL<E>.Node<E> t) {
        if (t != null) {
            Node tr = t.right;
            t.right = tr.left;
            if (tr.left != null) {
                tr.left.parent = t;
            }
            
            tr.parent = t.parent;
            if (t.parent == null) {
                root = tr;
            } else {
                if (t.parent.left == t) {
                    t.parent.left = tr;
                } else if (t.parent.right == t) {
                    t.parent.right = tr;
                }
            }
            tr.left = t;
            t.parent = tr;
        }
    }

    private void right_rotate(AVL<E>.Node<E> t) {
        if (t != null) {
            Node<E> tl = t.left;
            t.left =tl.right;
            if (tl.right != null) {
                tl.right.parent = t;
            }
            
            tl.parent = t.parent;
            if (t.parent == null) {
                root = tl;
            } else {
                if (t.parent.left == t) {
                    t.parent.left = tl;
                } else if (t.parent.right == t) {
                    t.parent.right = tl;
                }
            }
            
            tl.right = t;
            t.parent = tl;
        }
    }

    public Node<E> searchNode(E element) {
        if (root == null) {
            return null;
        } else {
            Node<E> cur = root;
            while(cur != null) {
                if (element.compareTo(cur.element) > 0) {
                    cur = cur.right;
                } else if (element.compareTo(cur.element) < 0) {
                    cur = cur.left;
                } else {
                    return cur;
                }
            }
        }
        return null;
    }
    
    
    private void leftBalance(AVL<E>.Node<E> t) {
        Node<E> tl = t.left;
        switch (tl.balance) {
        case LH: // t 的左子樹的左邊有問題舆瘪,直接右旋
            right_rotate(t);
            tl.balance = EH;
            t.balance = EH;
            break;
        case RH:
            Node<E> tlr = tl.right;
            switch (tlr.balance) {
            case RH:
                t.balance = EH;
                tlr.balance = EH;
                tl.balance = LH;
                break;
            case LH:
                t.balance = RH;
                tl.balance =EH;
                tlr.balance = EH;
                break;
            case EH:
                t.balance = EH;
                tl.balance = EH;
                tlr.balance =EH;
                break;
                //統(tǒng)一旋轉(zhuǎn)
            default:
                break;
            }
            left_rotate(t.left);
            right_rotate(t);
            break;
        default:
            break;
        }
        
    }
    
    class NodeBF {

        int level;
        Node<E> node;
        public NodeBF(Node node, int lev) {
            this.node = node;
            level = lev;
        }
        
    }

    class Node<E extends Comparable<E>>{
        E element; // data 
        int balance = 0; // balance value
        Node<E> left;
        Node<E> right;
        Node<E> parent;
        public Node(E element, Node<E> parent) {
            this.element = element;
            this.parent = parent;
        }
        
        @Override
        public String toString() {
            // TODO Auto-generated method stub
            return element + "BF: " + balance;
        }

        public E getElement() {
            return element;
        }

        public void setElement(E element) {
            this.element = element;
        }

        public int getBalance() {
            return balance;
        }

        public void setBalance(int balance) {
            this.balance = balance;
        }

        public Node<E> getLeft() {
            return left;
        }

        public void setLeft(Node<E> left) {
            this.left = left;
        }

        public Node<E> getRight() {
            return right;
        }

        public void setRight(Node<E> right) {
            this.right = right;
        }

        public Node<E> getParent() {
            return parent;
        }

        public void setParent(Node<E> parent) {
            this.parent = parent;
        }


        
        
    }
    
    public Node<E> getRoot() {
        return root;
    }
    
    public void levelDisplay(Node root) {
        LinkedList<NodeBF> list = new LinkedList<>();
        NodeBF nodeBF = new NodeBF(root, 0);
        list.offer(nodeBF);
        while (!list.isEmpty()) {
            NodeBF node = list.pop();
            System.out.println(node.node.element + " level: " + node.level);
            if (node.node.left != null) {
                NodeBF nodel = new NodeBF(node.node.left, node.level + 1);
                list.offer(nodel);
            }
            if (node.node.right != null) {
                NodeBF noder = new NodeBF(node.node.right, node.level + 1);
                list.offer(noder);
            }
        }
    }
    public static void main(String[] args) {
//      Integer[] nums = {5, 8, 2, 0, 1, -2, -9, 100};
        Integer[] nums = {5, 8, 2, 0, 1, -2};
        AVL<Integer> vAvlTree = new AVL();
        for (int i = 0; i < nums.length; i++) {
            vAvlTree.inserElement(nums[i]);
        }
//      vAvlTree.midOrderDisplay(vAvlTree.root);
        vAvlTree.levelDisplay(vAvlTree.root);
        System.out.println(vAvlTree.root.element);
    }
}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末片效,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子英古,更是在濱河造成了極大的恐慌淀衣,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,406評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件召调,死亡現(xiàn)場(chǎng)離奇詭異膨桥,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)唠叛,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門只嚣,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人艺沼,你說(shuō)我怎么就攤上這事册舞。” “怎么了障般?”我有些...
    開封第一講書人閱讀 163,711評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵调鲸,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我挽荡,道長(zhǎng)藐石,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,380評(píng)論 1 293
  • 正文 為了忘掉前任定拟,我火速辦了婚禮于微,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己角雷,他們只是感情好祸穷,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,432評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著勺三,像睡著了一般雷滚。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上吗坚,一...
    開封第一講書人閱讀 51,301評(píng)論 1 301
  • 那天祈远,我揣著相機(jī)與錄音,去河邊找鬼商源。 笑死车份,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的牡彻。 我是一名探鬼主播扫沼,決...
    沈念sama閱讀 40,145評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼庄吼!你這毒婦竟也來(lái)了缎除?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,008評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤总寻,失蹤者是張志新(化名)和其女友劉穎器罐,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體渐行,經(jīng)...
    沈念sama閱讀 45,443評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡轰坊,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,649評(píng)論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了祟印。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片肴沫。...
    茶點(diǎn)故事閱讀 39,795評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖旁理,靈堂內(nèi)的尸體忽然破棺而出樊零,到底是詐尸還是另有隱情我磁,我是刑警寧澤孽文,帶...
    沈念sama閱讀 35,501評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站夺艰,受9級(jí)特大地震影響芋哭,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜郁副,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,119評(píng)論 3 328
  • 文/蒙蒙 一减牺、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦拔疚、人聲如沸肥隆。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,731評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)栋艳。三九已至,卻和暖如春句各,著一層夾襖步出監(jiān)牢的瞬間吸占,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,865評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工凿宾, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留矾屯,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,899評(píng)論 2 370
  • 正文 我出身青樓初厚,卻偏偏與公主長(zhǎng)得像件蚕,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子产禾,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,724評(píng)論 2 354