程序員面試之算法備忘錄(四) | 二叉樹(shù)

前言


本文是題主準(zhǔn)備面試時(shí)記錄下的筆記整理而來(lái),稍顯粗陋,還請(qǐng)各位擼友勿噴哈米罚!

Topic


  • 目錄

  • 目標(biāo)

    • 熟練使用常用數(shù)據(jù)結(jié)構(gòu)的基本操作
    • 加深對(duì)常用算法與技巧的理解
    • 面試
  • 參考

    • 《程序員面試金典》
    • 《劍指offer》
    • Leetcode
    • 《結(jié)構(gòu)之法 --July》

二叉樹(shù)篇


BTree ADT

  • 構(gòu)建二叉樹(shù)

    • TreeNode<T>* createBTree(const string &s, int &i, int method);
    • 遞歸構(gòu)建
      • 判斷傳入字符串參數(shù)是否為空
      • 遇“#”返回NULL
      • 遇其他字符髓窜,new一個(gè)二叉樹(shù)結(jié)點(diǎn)
        a. data域是該字符
        b. 左孩子遞歸調(diào)用該函數(shù),所傳標(biāo)志變量i加1
        c. 右孩子同b
    • 根據(jù)先序遍歷序列構(gòu)建二叉樹(shù)(非遞歸)
      • 判空
      • 向左深搜構(gòu)造据某,并將結(jié)點(diǎn)入棧
      • 重復(fù)執(zhí)行B直至最左葉子節(jié)點(diǎn)的左指針
      • 逐一訪問(wèn)棧頂結(jié)點(diǎn)橡娄,向右深搜構(gòu)造
      • 執(zhí)行D時(shí),檢測(cè)是否有左結(jié)點(diǎn)癣籽,有則執(zhí)行C
    • 根據(jù)后序遍歷序列構(gòu)建二叉樹(shù)(非遞歸)
      • 同先序類似挽唉,順序顛倒一下就可以了
  • 銷毀二叉樹(shù)

    • void delBTree(TreeNode<T>* &p);
  • 先序遍歷

    • void PreOrder(TreeNode<T>* p, int method);
    • 迭代策略一:
      • 向左深搜直至BTree的最左葉子節(jié)點(diǎn)的l_child指針
      • 搜的同時(shí),訪問(wèn)每一結(jié)點(diǎn)筷狼,并將結(jié)點(diǎn)入棧
      • 逐一獲取棧中結(jié)點(diǎn)的右孩子瓶籽,重復(fù)A,B
      • 每獲取一個(gè)棧中結(jié)點(diǎn)埂材,就將該結(jié)點(diǎn)彈出塑顺,直至棧空
    • 迭代策略二:
      • 將根節(jié)點(diǎn)入棧
      • 訪問(wèn)棧頂結(jié)點(diǎn)楞遏,并彈出棧頂結(jié)點(diǎn)
      • 將該棧頂結(jié)點(diǎn)的右孩子入棧,如果有的話
      • 將該棧頂結(jié)點(diǎn)的左孩子入棧,如果有的話
      • 重復(fù)BCD,直至棽缦荆空
  • 中序遍歷

    • void InOrder(TreeNode<T>* p, int method);
    • 迭代策略:
      • 向左深搜直至BTree的最左葉子節(jié)點(diǎn)的l_child指針
      • 搜的同時(shí),將結(jié)點(diǎn)入棧
      • 逐一訪問(wèn)棧頂結(jié)點(diǎn)寡喝,并將棧頂結(jié)點(diǎn)的右孩子入棧
      • 重復(fù)ABC糙俗,直至棧空
  • 后序遍歷

    • void PostOrder(TreeNode<T>* p, int method);

    • 策略一:

      • 向左深搜直至BTree的最左葉子節(jié)點(diǎn)的l_child指針
      • 搜的同時(shí)预鬓,將結(jié)點(diǎn)入棧
      • 向右深搜棧頂元素的右孩子巧骚,直至最右葉子節(jié)點(diǎn),
        • 每搜一個(gè)節(jié)點(diǎn)時(shí)格二,先重復(fù)AB
      • 將棧中元素逐個(gè)彈出劈彪,并訪問(wèn)之
      • 執(zhí)行D時(shí),需注意將p指針置空
    • 策略二:雙棧法

      • 構(gòu)建兩個(gè)棧s1,s2
      • 將根節(jié)點(diǎn)入棧s1
      • 彈出s1的棧頂元素顶猜,并將該元素入棧s2
      • 將該元素的左孩子入棧沧奴,如果有的話
      • 將該元素的右孩子入棧,如果有的話
      • 重復(fù)CDE,直至棧s1空
      • 通過(guò)棧頂指針逐一遍歷棧s2的元素
  • 層次遍歷

    • void LayerOrder(TreeNode<T> *p);
  • 查找值為et_value的二叉樹(shù)結(jié)點(diǎn)

    • TreeNode<T>* findNode(TreeNode<T> *p, T et_value);
  • 獲得二叉樹(shù)的深度

    • int getBTDepth(TreeNode<T> *p);

BST ADT

  • 構(gòu)建二叉排序樹(shù)
    • TreeNode<T>* createBST(int v[], int start, int end);
  • 插入新結(jié)點(diǎn)
    • void insertNode(T &et_value, TreeNode<T>* &p);
  • 刪除指定結(jié)點(diǎn)
    • void removeNode(T et_value, TreeNode<T>* &p);
  • 查找最大值
    • TreeNode<T>* findMax(TreeNode<T> *p);
  • 查找最小值
    • TreeNode<T>* findMin(TreeNode<T> *p);
  • 查找二叉樹(shù)是否包含指定值的結(jié)點(diǎn)
    • bool contains(T et_value, TreeNode<T> *p);

代碼示例:

/*******************************************************************************
    @ Title:            實(shí)現(xiàn)二叉樹(shù)基本操作   

    @ Description:      
                        1.C++實(shí)現(xiàn)二叉樹(shù)模板類(遞歸)
                        2.C++實(shí)現(xiàn)二叉樹(shù)模板類(非遞歸)
                        3.C++實(shí)現(xiàn)二叉排序樹(shù)模板類(遞歸)
                        4.C++實(shí)現(xiàn)二叉排序樹(shù)模板類(非遞歸)
    @ Conclusion:           
            1.構(gòu)建二叉樹(shù)(遞歸):
                A.判斷傳入字符串參數(shù)是否為空
                B.遇“#”返回NULL
                C.遇其他字符长窄,new一個(gè)二叉樹(shù)結(jié)點(diǎn)
                    a.data域是該字符
                    b.左孩子遞歸調(diào)用該函數(shù)滔吠,所傳標(biāo)志變量i加1
                    c.右孩子同b
            
            2.先序遍歷(非遞歸):
                策略一:
                    A.向左深搜直至BTree的最左葉子節(jié)點(diǎn)的l_child指針
                    B.搜的同時(shí)纲菌,訪問(wèn)每一結(jié)點(diǎn),并將結(jié)點(diǎn)入棧
                    C.逐一獲取棧中結(jié)點(diǎn)的右孩子疮绷,重復(fù)A翰舌,B
                    D.每獲取一個(gè)棧中結(jié)點(diǎn),就將該結(jié)點(diǎn)彈出冬骚,直至椧渭空
                
                策略二:
                    A.將根節(jié)點(diǎn)入棧
                    B.訪問(wèn)棧頂結(jié)點(diǎn),并彈出棧頂結(jié)點(diǎn)
                    C.將該棧頂結(jié)點(diǎn)的右孩子入棧,如果有的話
                    D.將該棧頂結(jié)點(diǎn)的左孩子入棧,如果有的話
                    E.重復(fù)BCD,直至椫欢常空

            3.中序遍歷(非遞歸)
                策略一:
                    A.向左深搜直至BTree的最左葉子節(jié)點(diǎn)的l_child指針
                    B.搜的同時(shí)庇麦,將結(jié)點(diǎn)入棧
                    C.逐一訪問(wèn)棧頂結(jié)點(diǎn),并將棧頂結(jié)點(diǎn)的右孩子入棧
                    D.重復(fù)ABC属愤,直至椗鳎空

            4.后序遍歷(非遞歸)
                策略一:
                    A.向左深搜直至BTree的最左葉子節(jié)點(diǎn)的l_child指針
                    B.搜的同時(shí),將結(jié)點(diǎn)入棧
                    C.向右深搜棧頂元素的右孩子住诸,直至最右葉子節(jié)點(diǎn)驾胆,
                        *、每搜一個(gè)節(jié)點(diǎn)時(shí)贱呐,先重復(fù)AB
                    D.將棧中元素逐個(gè)彈出丧诺,并訪問(wèn)之
                        E.執(zhí)行D時(shí),需注意將p指針置空
                
                策略二:雙棧法
                    A.構(gòu)建兩個(gè)棧s1,s2
                    B.將根節(jié)點(diǎn)入棧s1
                    C.彈出s1的棧頂元素奄薇,并將該元素入棧s2
                    D.將該元素的左孩子入棧驳阎,如果有的話
                    E.將該元素的右孩子入棧,如果有的話
                    F.重復(fù)CDE,直至棧s1空
                    G.通過(guò)棧頂指針逐一遍歷棧s2的元素

                        5.根據(jù)先序遍歷序列構(gòu)建二叉樹(shù)(非遞歸):
                            策略:
                                A.判空
                                B.向左深搜構(gòu)造馁蒂,并將結(jié)點(diǎn)入棧
                                C.重復(fù)執(zhí)行B直至最左葉子節(jié)點(diǎn)的左指針
                                D.逐一訪問(wèn)棧頂結(jié)點(diǎn)呵晚,向右深搜構(gòu)造
                                E.執(zhí)行D時(shí),檢測(cè)是否有左結(jié)點(diǎn)沫屡,有則執(zhí)行C

                        6.根據(jù)后序遍歷序列構(gòu)建二叉樹(shù)(非遞歸):
                            策略:
                                A.同5類似饵隙,順序顛倒一下就可以了
                        
                        7.求二叉樹(shù)深度(非遞歸實(shí)現(xiàn))
                        8.前中后Morris遍歷測(cè)試
                        9.測(cè)試BST相關(guān)操作 + 創(chuàng)建二叉排序樹(shù)(遞歸 & 非遞歸)
                        10.二叉樹(shù)findnode(非遞歸實(shí)現(xiàn))
            11.BST insertNode非遞歸 & removeNode非遞歸


    @ Author:       rh_Jameson

    @ Date:         2014/12/22
**********************************************************************************/

#ifndef BINARYTREE_H
#define BINARYTREE_H

#include <iostream>
#include <string>
//#include <deque>
#include<queue>
#include<stack>
#include<vector>
#include<algorithm>

using namespace std;

//二叉樹(shù)類聲明
template<typename T>class BinaryTree;

//二叉樹(shù)結(jié)點(diǎn)類
template<typename T>
class TreeNode{
private:
    TreeNode<T> *l_child,*r_child;
    T data;

public:
    TreeNode(){l_child = NULL;r_child = NULL;}
    TreeNode(T value,TreeNode<T> *left = NULL,TreeNode<T> *right = NULL){
        data = value;
        l_child = left;
        r_child = right;
    }
    friend class BinaryTree<T>;     // 將二叉樹(shù)類聲明為友元類,方便訪問(wèn)該類私有變量
};

//二叉樹(shù)類
template<typename T>
class BinaryTree{
public:
    
    /* 二叉樹(shù)常用操作 */

    // 構(gòu)造函數(shù)
    BinaryTree(const string &s, int method);                
    // 拷貝構(gòu)造函數(shù)
    //BinaryTree(BinaryTree<T> &tree);
    // 析構(gòu)函數(shù)
    ~BinaryTree();
    // 外部刪除二叉樹(shù)函數(shù)
    bool pubForDelBTree();      
    // 外部訪問(wèn)先序遍歷
    void pubForPreOrder(int method);
    // 外部訪問(wèn)中序遍歷
    void pubForInOrder(int method);
    // 外部訪問(wèn)后序遍歷
    void pubForPostOrder(int method);
    // 外部訪問(wèn)層次遍歷
    void pubForLayerOrder();
    // 外部查找值為et_value的二叉樹(shù)結(jié)點(diǎn)
    void pubForFindNode(T et_value);
    // 獲得二叉樹(shù)的根
    TreeNode<T>* getRoot();
    // 外部獲得二叉樹(shù)的深度
    int pubForGetBTDepth();

    /* 二叉排序樹(shù)常用操作 */
    
    // 二叉排序樹(shù)構(gòu)造函數(shù)
    //BinaryTree(vector<T> v);              
    BinaryTree(int v[]);                
    // 外部插入新結(jié)點(diǎn)
    void pubForInsertNode(T &et_value);
    // 外部刪除指定結(jié)點(diǎn)
    void pubForRemoveNode(T et_value);
    // 外部查找最大值
    void pubForFindMax();
    // 外部查找最小值
    void pubForFindMin();
    // 外部查找二叉樹(shù)是否包含指定值的結(jié)點(diǎn)
    bool pubForContains(T et_value);

private:
    TreeNode<T> *root;                  //二叉樹(shù)的根指針
    
    /* 二叉樹(shù)常用操作 */

    //構(gòu)建二叉樹(shù)
    TreeNode<T>* createBTree(const string &s, int &i, int method);
    //銷毀二叉樹(shù)
    void delBTree(TreeNode<T>* &p);
    //內(nèi)部先序遍歷
    void PreOrder(TreeNode<T>* p, int method);
    //內(nèi)部中序遍歷
    void InOrder(TreeNode<T>* p, int method);
    //內(nèi)部后序遍歷
    void PostOrder(TreeNode<T>* p, int method);
    //內(nèi)部層次遍歷
        void LayerOrder(TreeNode<T> *p);  
    //內(nèi)部查找值為et_value的二叉樹(shù)結(jié)點(diǎn)
    TreeNode<T>* findNode(TreeNode<T> *p, T et_value);    
    //內(nèi)部獲得二叉樹(shù)的深度
    int getBTDepth(TreeNode<T> *p);

    /* 二叉排序樹(shù)常用操作 */

        // 構(gòu)建二叉排序樹(shù)
    TreeNode<T>* createBST(int v[], int start, int end);
    //TreeNode<T>* createBST(int v[], int start, int end);
    // 插入新結(jié)點(diǎn)
    void insertNode(T &et_value, TreeNode<T>* &p);
    // 刪除指定結(jié)點(diǎn)
    void removeNode(T et_value, TreeNode<T>* &p);
    // 查找最大值
    TreeNode<T>* findMax(TreeNode<T> *p);
    // 查找最小值
    TreeNode<T>* findMin(TreeNode<T> *p);
    // 查找二叉樹(shù)是否包含指定值的結(jié)點(diǎn)
    bool contains(T et_value, TreeNode<T> *p);
};

// 構(gòu)造函數(shù)
template <typename T>
BinaryTree<T>::BinaryTree(const string &s, int method){
    root = NULL;
    int i = 0;
    root = createBTree(s, i, method);
} 
//構(gòu)建二叉樹(shù) 
template <typename T>
TreeNode<T>* BinaryTree<T>::createBTree(const string &s, int &i,int method){
    switch(method){
        case 1:     //遞歸構(gòu)建
        {
            TreeNode<T>* BTree; 
            if(s.empty() ){
                return NULL;
            }

            if(s[i] == '#'){
                return NULL;
            }
            else{
                BTree = new TreeNode<T>();
                BTree->data = s[i];
                BTree->l_child = createBTree(s,++i, method);
                BTree->r_child = createBTree(s,++i, method);
                return BTree;
            }
        }
        case 2:     //根據(jù)先序遍歷序列構(gòu)建(非遞歸)
        {
            if(s.empty()){
                return NULL;
            }
            TreeNode<T> *BTNode = new TreeNode<T>, *head = BTNode;
            BTNode->data = s[i++];
            stack<TreeNode<T>* > SForBTree;
            while(BTNode || !SForBTree.empty() ){
                if(s[i] == '\0'){
                    break;
                }
                if(BTNode){             //向左深搜
                    SForBTree.push(BTNode);
                    if(s[i] == '#'){    //遇#置NULL
                        BTNode->l_child = NULL;
                    }
                    else{               //遇其他符號(hào)則新建結(jié)點(diǎn)
                        BTNode->l_child = new TreeNode<T>();
                        BTNode->l_child->data = s[i];
                    }
                    BTNode = BTNode->l_child;
                }
                else{                   //反過(guò)來(lái)沮脖,向右深搜
                    BTNode = SForBTree.top();
                    SForBTree.pop();
                    if(s[i] == '#'){
                        BTNode->r_child = NULL;
                    }
                    else{
                        BTNode->r_child = new TreeNode<T>();
                        BTNode->r_child->data = s[i];
                    }
                    BTNode = BTNode->r_child;
                }
                i++;
            }
            return head;
        }
        case 3:     //根據(jù)后序遍歷序列構(gòu)建二叉樹(shù)
        {
            if(s.empty()){
                return NULL;
            }
            int cur = s.size() - 1;
            stack<TreeNode<T>* > SForBTree;
            TreeNode<T> *node = new TreeNode<T>(), *head = node;
            node->data = s[cur--];
            while(node || !SForBTree.empty()){
                if(cur < 0){
                    break;
                }
                if(node){                   //向右深搜
                    SForBTree.push(node);
                    if(s[cur] == '#'){      //遇#置NULL
                        node->r_child = NULL;
                    }
                    else{                   //其他符號(hào)新建一個(gè)結(jié)點(diǎn)
                        node->r_child = new TreeNode<T>();
                        node->r_child->data = s[cur];
                    }
                    node = node->r_child;
                }
                else{                       //反過(guò)來(lái)金矛,向左深搜
                    node = SForBTree.top();
                    SForBTree.pop();
                    if(s[cur] == '#'){
                        node->l_child = NULL;
                    }
                    else{
                        node->l_child = new TreeNode<T>();
                        node->l_child->data = s[cur];
                    }
                    node = node->l_child;
                }
                --cur;
            }
            return head;
        }
    }
}


//根據(jù)前序遍歷序列和中序遍歷序列構(gòu)建二叉樹(shù)
//失敗,模板類惹的禍勺届,只允許TreeNode<char>,待另寫一個(gè)cpp實(shí)現(xiàn)
/*template<typename T>
TreeNode<T>* createBTreeByPreAndInOrder(string &PreOrder, string &InOrder){
    if(PreOrder.empty() || InOrder.empty()) return NULL;
    TreeNode<T> *tmp; 
    if(PreOrder.size()){
        tmp = new TreeNode<T>();
        tmp->data = PreOrder[0];
        int idx = InOrder.find(PreOrder[0]);
        
        string PreLeft = PreOrder.substr(1, idx);
        string PreRight = PreOrder.substr(idx + 1);
        string InLeft = InOrder.substr(0, idx);
        string InRight = InOrder.substr(idx + 1);

        tmp->l_child = createBTreeByPreAndInOrder(PreLeft, InLeft);
        tmp->r_child = createBTreeByPreAndInOrder(PreRight,InRight);
    }
    return tmp;
}*/

//// 拷貝構(gòu)造函數(shù)
//template <typename T>
//BinaryTree<T>::BinaryTree(BinaryTree<T> &tree){
//  
//} 

//析構(gòu)函數(shù)
template <typename T>
BinaryTree<T>::~BinaryTree(){
    delBTree(root);
}
//外部銷毀二叉樹(shù)
template <class T>
bool BinaryTree<T>::pubForDelBTree(){
    delBTree(root);
    if(root){
        return false;
    }
    return true;
            
}
//內(nèi)部銷毀二叉樹(shù)
template<typename T>
void BinaryTree<T>::delBTree(TreeNode<T>* &p){
    
    /* 遞歸銷毀
     if(p != NULL){
        delBTree(p->l_child);
        delBTree(p->r_child);
        delete(p);
        p = NULL;
    }*/
    //待實(shí)現(xiàn):自上而下層次遍歷銷毀
    //
    //非遞歸實(shí)現(xiàn)(自下而上后續(xù)遍歷銷毀)
    stack<TreeNode<T>* > SForBTree;
    TreeNode<T> *pre;
    while(p || !SForBTree.empty() ){
        if(p){
            SForBTree.push(p);
            p = p->l_child;
        }
        else{
            p = SForBTree.top();
            if(p->r_child && p->r_child != pre ){   //有右子樹(shù)且右子樹(shù)未被訪問(wèn)過(guò)
                p = p->r_child;
            }
            else{
                pre = p;
                SForBTree.pop();
                delete p;
                p = NULL;           //!!!須置空驶俊,否則陷入死循環(huán)
                                    //反復(fù)出棧 / 入棧
            }
        }
    }
}

//外部訪問(wèn)先序遍歷
template<typename T>
void BinaryTree<T>::pubForPreOrder(int method){
    if(!root){
        cout << "空二叉樹(shù)!" << endl;
    }
    PreOrder(root, method);
}
//內(nèi)部訪問(wèn)先序遍歷
template<typename T>
void BinaryTree<T>::PreOrder(TreeNode<T>* p, int method){
    switch(method){
        case 1:     //遞歸形式
            if(p != NULL){
                cout << p->data << "\t";
                PreOrder(p->l_child, method);
                PreOrder(p->r_child, method);
            }
            break;
        case 2:     //棧的實(shí)現(xiàn)形式
            {   
                stack<TreeNode<T>* > SForBTree;
                while(p != NULL || !SForBTree.empty() ){
                    if(p != NULL){
                        cout << p->data << "\t";
                        SForBTree.push(p);
                        p = p->l_child;
                    }
                    else{
                        p = SForBTree.top();
                        SForBTree.pop();
                        p = p->r_child;
                    }
                }
                break;
            }
        case 3:     //棧實(shí)現(xiàn)形式二
            {   
                stack<TreeNode<T>* > SForBTree;
                if(p != NULL)
                    SForBTree.push(p);
                while( !SForBTree.empty() ){
                    p = SForBTree.top();
                    cout << p->data << "\t";
                    SForBTree.pop();

                    if(p->r_child){
                        SForBTree.push(p->r_child);
                    }
                    if(p->l_child){
                        SForBTree.push(p->l_child);
                    }
                }
                break;
            }
            case 4:     //Morris遍歷
            {
            TreeNode<T> *cur = p, *pre;
            while(cur){
                if(!cur->l_child){      //左孩子為空時(shí)免姿,輸出當(dāng)前結(jié)點(diǎn)饼酿,cur指向其右孩子
                    cout << cur->data << "\t";
                    cur = cur->r_child;
                }
                else{                   //左孩子不為空時(shí)
                    pre = cur->l_child;
                    //找該結(jié)點(diǎn)的中序遍歷序列的前驅(qū)結(jié)點(diǎn)
                    while(pre->r_child != NULL && pre->r_child != cur){     
                        pre = pre->r_child;
                    }
                    //前驅(qū)結(jié)點(diǎn)的右孩子指向當(dāng)前結(jié)點(diǎn),并輸出當(dāng)前節(jié)點(diǎn)胚膊,cur指向其左孩子
                    if(pre->r_child == NULL){   
                        pre->r_child = cur;
                        cout << cur->data << "\t";  //與中序遍歷唯一的不同嗜湃!
                        cur = cur->l_child;
                    }
                    //將前驅(qū)結(jié)點(diǎn)右孩子指向當(dāng)前結(jié)點(diǎn)的連接斷開(kāi)奈应,cur指向其右孩子
                    else{
                        pre->r_child = NULL;
                        cur = cur->r_child;
                    }
                }
            }
            break;
        }
    }
}

//外部訪問(wèn)中序遍歷
template<typename T>
void BinaryTree<T>::pubForInOrder(int method){
    if(!root){
        cout << "空二叉樹(shù)" << endl;
    }
    InOrder(root, method);
}
//內(nèi)部訪問(wèn)中序遍歷
template<typename T>
void BinaryTree<T>::InOrder(TreeNode<T>* p, int method){
    switch(method){
        case 1:     //遞歸形式
        {   if(p != NULL){
                InOrder(p->l_child, method);
                cout << p->data << "\t";                
                InOrder(p->r_child, method);
            }
            break;
        }
        case 2:     //棧的實(shí)現(xiàn)形式
        {
            stack<TreeNode<T>* > SForBTree;
            while(p != NULL || !SForBTree.empty() ){
                if(p != NULL){
                    SForBTree.push(p);
                    p = p->l_child;
                }
                else{
                    p = SForBTree.top();
                    cout << p->data << "\t";
                    SForBTree.pop();
                    p = p->r_child;
                }
            }
            break;
        }
        case 3:     //morris遍歷
        {
            TreeNode<T> *cur = p, *pre;
            while(cur){
                if(cur->l_child == NULL){
                    cout << cur->data << "\t";
                    cur = cur->r_child;
                }
                else{
                    pre = cur->l_child;
                    while(pre->r_child != NULL && pre->r_child != cur){
                        pre = pre->r_child;
                    }
                    if(pre->r_child == NULL){
                        pre->r_child = cur;
                        cur = cur->l_child;
                    }
                    else{
                        pre->r_child = NULL;
                        cout << cur->data << "\t";      //與前序遍歷代碼的不同澜掩!
                        cur = cur->r_child;
                    }
                }
            }
            break;
        }
    }
    
}

//外部訪問(wèn)后序遍歷
template<typename T>
void BinaryTree<T>::pubForPostOrder(int method){
    if(!root){
        cout << "空二叉樹(shù)购披!" << endl;
    }
    PostOrder(root, method);
}
//內(nèi)部訪問(wèn)后序遍歷
template<typename T>
void BinaryTree<T>::PostOrder(TreeNode<T> *p, int method){
    switch(method){
        case 1:     //遞歸形式實(shí)現(xiàn)
            if(p != NULL){
                PostOrder(p->l_child, method);
                PostOrder(p->r_child, method);
                cout << p->data << "\t";
            }
            break;

        case 2:     //棧形式實(shí)現(xiàn),該代碼應(yīng)該可以轉(zhuǎn)作非遞歸銷毀二叉樹(shù)
        {
            stack<TreeNode<T>* > SForBTree;
            TreeNode<T> *pre;
            while(p || !SForBTree.empty() ){
                if(p){
                    SForBTree.push(p);
                    p = p->l_child;
                }
                else{
                    p = SForBTree.top();
                    if(p->r_child && p->r_child != pre ){   //有右子樹(shù)且右子樹(shù)未被訪問(wèn)過(guò)
                        p = p->r_child;
                    }
                    else{
                        cout << p->data << "\t";    
                        pre = p;
                        SForBTree.pop();
                        p = NULL;           //!!!須置空肩榕,否則陷入死循環(huán)
                                            //反復(fù)出棧 / 入棧
                    }
                }
            }
            break;
        }
        case 3:     //雙棧形式實(shí)現(xiàn)
        {
            stack<TreeNode<T>* > s1, s2;
            if(p != NULL)   s1.push(p);
            while(!s1.empty()){
                p = s1.top();
                s1.pop();
                s2.push(p);

                if(p->l_child){
                    s1.push(p->l_child);
                }
                if(p->r_child){
                    s1.push(p->r_child);
                }
            }
            while(!s2.empty()){
                p = s2.top();
                cout << p->data << "\t";
                s2.pop();
            }
            break;
        }
        case 4:     //morris遍歷
        {
            TreeNode<T> *cur = p, *pre;
            while(cur != NULL){
                if(cur->l_child == NULL){
                    cur = cur->r_child;
                }
                else{
                    pre = cur->l_child;
                    while(pre->r_child != NULL && pre->r_child != cur){
                        pre = pre->r_child;
                    }
                    if(pre->r_child == NULL){
                        pre->r_child = cur;
                        cur = cur->l_child;
                    }
                    else{
                        //printReverse(cur->l_child, pre);
                        pre->r_child = NULL;
                        cur = cur->r_child;
                    }
                }
            }
            break;
        }
    }
}
/*Morris 后續(xù)遍歷相關(guān)函數(shù)
 * template<typename T>
void reverse(TreeNode<T> *from, TreeNode<T> *to){
    if(from = to){
        return;
    }
    TreeNode<T>  =
}
template<typename T>
void printReverse(TreeNode<T> *from, TreeNode<T> *to){
    TreeNode<T> *p = to;
    reverse(from, to);
    while(true){
        cout << p->data << "\t";
        if(p == from){
            break;
        }
        p = p->r_child;
    }
    reverse(to, from); 
}*/

//外部查找值為et_value的二叉樹(shù)結(jié)點(diǎn)
template<typename T>
void BinaryTree<T>::pubForFindNode(T et_value){
    TreeNode<T> *res = findNode(root, et_value);
    if(res == NULL){
        cout << "找不到相應(yīng)結(jié)點(diǎn)" << endl;
    }
    else{
        cout << "找到該結(jié)點(diǎn)刚陡,該結(jié)點(diǎn)值為:" << res->data << endl;
    }
    
}
//查找值為et_value的二叉樹(shù)結(jié)點(diǎn)
template<typename T>
TreeNode<T>* BinaryTree<T>::findNode(TreeNode<T> *p, T et_value){
    //遞歸實(shí)現(xiàn)
/*  if(p == NULL){
        return NULL;
    }
    if(p->data == et_value){
        return p;
    }   
    TreeNode<T> *tmp = findNode(p->l_child, et_value);
    if(tmp != NULL){
        return tmp;
    }
    else{
        return findNode(p->r_child, et_value);
    }
*/
    //非遞歸實(shí)現(xiàn)
    stack<TreeNode<T>*> s;
    while(p != NULL || !s.empty()){
        if(p != NULL){
            s.push(p);
            p = p->l_child;
        }
        else{
            p = s.top();
            s.pop();
            if(p->data == et_value) break;
            p = p->r_child;
        }
    }
    return p;
}

//外部獲得二叉樹(shù)的深度
template<typename T>
int BinaryTree<T>::pubForGetBTDepth(){
    return getBTDepth(root);
}
//獲得二叉樹(shù)的深度
template<typename T>
int BinaryTree<T>::getBTDepth(TreeNode<T> *p){
    /* 遞歸實(shí)現(xiàn)1 
    int depth = 0;
    if(p != NULL){
        int l_child_depth = getBTDepth(p->l_child);
        int r_child_depth = getBTDepth(p->r_child);
        depth =  (l_child_depth >= r_child_depth) ? (l_child_depth + 1) : (r_child_depth + 1);
        //depth = 1 + (l_child_depth >= r_child_depth ? l_child_depth : r_child_depth);
    }
    return depth;   
    */
    /* 遞歸實(shí)現(xiàn)2 
    if(p == NULL) return 0;
    return 1 + max(getBTDepth(p->l_child), getBTDepth(p->r_child));
    */
    //非遞歸實(shí)現(xiàn)
/*    int depth = 0, maxDepth = 0;
    stack<TreeNode<T>*> *s = new stack<TreeNode<T>*>();
    while(p != NULL || !s->empty()){
        if(p != NULL){
            s->push(p);
            ++depth;
            p = p->l_child;
        }
        else{
            p = s->top();
            s->pop();
            p = p->r_child;
            if(p == NULL){
                if(depth > maxDepth){
                    maxDepth = depth;
                }   
                depth--;
            }
        }
    }
    return maxDepth - 1;
*/
    /* 雙棧形式 
    if (p == NULL) return 0;
    stack<TreeNode<T> *> gray;
    stack<int> depth;
    int maxDepth = 0;

    gray.push(p);
    depth.push(1);
    while (!gray.empty()) {
        TreeNode<T> *tmp = gray.top();
        int num = depth.top();
        gray.pop();
        depth.pop();
        if (tmp->l_child == NULL && tmp->r_child == NULL) {
            maxDepth = num > maxDepth ? num : maxDepth;
        }
        else {
            if (tmp->l_child != NULL) {
                gray.push(tmp->l_child);
                depth.push(num + 1);
            }
            if (tmp->r_child != NULL) {
                gray.push(tmp->r_child);
                depth.push(num + 1);
            }
        }
    }
    return maxDepth;
    */

    /* 隊(duì)列層次遍歷實(shí)現(xiàn) 
    int height = 0,rowCount = 1;
    if(root == NULL){
        return 0;
    }
    queue<TreeNode<T>*> queue;
    queue.push(p);
    while(!queue.empty()){
        TreeNode<T> *node = queue.front();
        queue.pop();
        //一層的元素個(gè)數(shù)減1,一層遍歷完高度加1
        rowCount --;
        if(node->l_child){
            queue.push(node->l_child);
        }
        if(node->r_child){
            queue.push(node->r_child);
        }
        //一層遍歷完
        if(rowCount == 0){
            //高度加1
            height++;
            //下一層元素個(gè)數(shù)
            rowCount = queue.size();
        }
    }
    return height;
    */
    /* 層次遍歷樹(shù)的層數(shù),NULL為每一層節(jié)點(diǎn)的分割標(biāo)志 */
    if(p == NULL)return 0;
    int res = 0;
    queue<TreeNode<T>*> Q;
    Q.push(p);
    Q.push(NULL);
    while(Q.empty() == false)
    {
        TreeNode<T> *p = Q.front();
        Q.pop();
        if(p != NULL)
        {
            if(p->l_child)Q.push(p->l_child);
            if(p->r_child)Q.push(p->r_child);
        }
        else
        {
            res++;
            if(Q.empty() == false)Q.push(NULL);
        }
    }
    return res;
}

//外部訪問(wèn)層次遍歷
template<typename T>
void  BinaryTree<T>::pubForLayerOrder(){
    LayerOrder(root);
}
//內(nèi)部層次遍歷
template<typename T>
void  BinaryTree<T>::LayerOrder(TreeNode<T> *p){
    if(p == NULL){
        cout << "空樹(shù)株汉!" << endl;
        return;
    }
    queue<TreeNode<T> *> queueTreeNode;
    queueTreeNode.push(p);
    while(queueTreeNode.size() ){
        TreeNode<T> *tmp = queueTreeNode.front();
        queueTreeNode.pop();
        cout << tmp->data << "\t";

        if(tmp->l_child != NULL){
            queueTreeNode.push(tmp->l_child);
        }
        if(tmp->r_child != NULL){
            queueTreeNode.push(tmp->r_child);
        }
    }
    /*deque雙向隊(duì)列版
    deque<TreeNode<T> *> dequeTreeNode;
    dequeTreeNode.push_back(p);
    while(dequeTreeNode.size() ){
        TreeNode<T> *tmp = dequeTreeNode.front();
        dequeTreeNode.pop_front();
        cout << tmp->data << "\t";

        if(tmp->l_child != NULL){
            dequeTreeNode.push_back(tmp->l_child);
        }
        if(tmp->r_child != NULL){
            dequeTreeNode.push_back(tmp->r_child);
        }
    }*/
}

//獲得二叉樹(shù)的根
template<typename T>
TreeNode<T>* BinaryTree<T>::getRoot(){
    return root;
}


/* 二叉排序樹(shù)常用操作 */

// 二叉排序樹(shù)構(gòu)造函數(shù)
template<typename T>
BinaryTree<T>::BinaryTree(int v[]){
    //vector<int> vv(v, v + sizeof(v)/sizeof(v[0]));
    /*vector<int> vv(v, v + 10);
    if(!vv.size()){
        cout << "生成失敗筐乳,原因:空數(shù)組" << "\t";
        return;
    }
    sort(vv.begin(), vv.end());
    */
    sort(v, v + 9);
    /*if(sizeof(v) / sizeof(int)){
        cout << "生成失敗,原因:空數(shù)組" << "\t";
        return;
    }*/

    root = createBST(v, 0, 9 - 1);
}
 // 構(gòu)建二叉排序樹(shù)
template<typename T>
TreeNode<T>* BinaryTree<T>::createBST(int sorted_Vec[],int start,int end){    
    //遞歸實(shí)現(xiàn)
    if(end < start){
        return NULL;
    }
    int mid = (start + end) / 2;
    TreeNode<T> *node = new TreeNode<T>();
    node->data = sorted_Vec[mid];
    node->l_child = createBST(sorted_Vec, start, mid - 1);
    node->r_child = createBST(sorted_Vec, mid + 1, end);
    return node;
    
    //非遞歸實(shí)現(xiàn)
/*失敗乔妈,每個(gè)結(jié)點(diǎn)的start和end都需記住蝙云,該模板無(wú)相應(yīng)屬性
 * 為避免大量修改代碼,放棄實(shí)現(xiàn)~~
 *  mid = (start + end) / 2;
    stack<TreeNode<T>* > s = new stack<TreeNode<T>* >();
    stack<int> mid_s = new stack<int>();
    TreeNode<T> *node = new TreeNode<T>();
    mid_s.push(end);
    while(mid >= 0 || !s.empty()){
        if(mid >= 0){
            node = new TreeNode<T>();
            node->data = sorted_Vec[mid];
            mid_s.push(mid);
            s.push(node);
            node = node->l_child;
            mid = (0 + mid - 1) / 2;
        }
        else{
            mid = mid_s.top();
            node = s.top();
            mid_s.pop();
            s.pop();
            
        }
    }
*/
}


// 外部插入新結(jié)點(diǎn)
template<typename T>
void BinaryTree<T>::pubForInsertNode(T &et_value){
    insertNode(et_value, root);
}
// 插入新結(jié)點(diǎn)
template<typename T>
void BinaryTree<T>::insertNode(T &et_value, TreeNode<T>* &p){
    //遞歸實(shí)現(xiàn)
/*  if(p == NULL){
        p = new TreeNode<T>();
        p->data = et_value;
    }
    else if(et_value < p->data){
        insertNode(et_value, p->l_child);
    }
    else if(et_value > p->data){
        insertNode(et_value, p->r_child);
    }
    else    //相等(重復(fù))則不做任何操作
        ;
    */
    //非遞歸實(shí)現(xiàn)
    TreeNode<T> *cur = p, *parent = NULL, *newNode = new TreeNode<T>();
    newNode->data = et_value;
    if(p == NULL){              //二叉樹(shù)為空的情況
        p = newNode;
        return;
    }           
    while(true){
        if(cur == NULL){
            if(et_value < parent->data)         //插入到葉子節(jié)點(diǎn)的左孩子
                parent->l_child = newNode;
            else
                parent->r_child = newNode;
            return;
        }
        parent = cur;
        if(et_value < cur->data)
            cur = cur->l_child;
        else if(et_value > cur->data)
            cur = cur->r_child;
        else
            return;     //重復(fù)路召,不插入勃刨,直接退出
    }
}

// 外部刪除指定結(jié)點(diǎn)
template<typename T>
void BinaryTree<T>::pubForRemoveNode(T et_value){
    removeNode(et_value, root);
}
// 刪除指定結(jié)點(diǎn)
template<typename T>
void BinaryTree<T>::removeNode(T et_value, TreeNode<T> * &p){
    //遞歸實(shí)現(xiàn)
/*  if(p == NULL){
        return;     //該值未找到,停止
    }
    if(et_value < p->data){
        removeNode(et_value, p->l_child);
    }
    else if(et_value > p->data){
        removeNode(et_value, p->r_child);
    }
    else if(p->l_child != NULL && p->r_child != NULL){      //待刪結(jié)點(diǎn)有兩個(gè)孩子的情況
        p->data = findMin(p->r_child)->data;        //需琢磨另一種寫法
        removeNode(p->data, p->r_child);
    }
    else{       //無(wú)孩子或有一個(gè)孩子情況
        TreeNode<T> *tmp = p;
        p = (p->l_child != NULL) ? p->l_child : p->r_child;
        delete tmp;
    }
*/

    //非遞歸實(shí)現(xiàn) 
/*  TreeNode<T> *cur = p, *pre, *tmp, *child;
    if(p->data == et_value && !p->l_child && !p->r_child){  //只有一個(gè)節(jié)點(diǎn)的情況
        p = NULL;
        return;
    }
    while(true){        
        if(cur == NULL) break;
        if(et_value < cur->data){
            pre = cur;
            cur = cur->l_child;
        }else if(et_value > cur->data){ 
            pre = cur;
            cur = cur->r_child;
        }else if(cur->l_child != NULL && cur->r_child != NULL){     //待刪結(jié)點(diǎn)有兩個(gè)孩子的情況
            tmp = findMin(cur->r_child); 
            cur->data = tmp->data;
            child = tmp->r_child;           //暫存其右孩子
            pre = cur->r_child;
            while(pre->l_child != tmp)      //找倒數(shù)第二小的結(jié)點(diǎn)
                pre = pre->l_child;
            pre->l_child = child;
            delete tmp;
            break;
        }
        else{       //無(wú)孩子或有一個(gè)孩子情況
            tmp = cur;
            cur = (cur->l_child != NULL) ? cur->l_child : cur->r_child;
            (pre->l_child == tmp) ? pre->l_child = cur : pre->r_child = cur;
            delete tmp;
            break;
        }
    }
*/
    //非遞歸實(shí)現(xiàn) 
    TreeNode<T> *cur = p, *pre, *tmp, *child;
    if(p->data == et_value && !p->l_child && !p->r_child){  //只有一個(gè)節(jié)點(diǎn)的情況
        p = NULL;
        return;
    }
    while(true){        
        if(cur == NULL) break;      //找不到或BST為空
        if(et_value < cur->data){
            pre = cur;
            cur = cur->l_child;
        }
        else if(et_value > cur->data){  
            pre = cur;
            cur = cur->r_child;
        }
        else{       
            if(cur->l_child != NULL && cur->r_child != NULL){   //待刪結(jié)點(diǎn)有兩個(gè)孩子的情況
                tmp = findMin(cur->r_child); 
                cur->data = tmp->data;
                child = tmp->r_child;           //暫存其右孩子
                pre = cur->r_child;
                while(pre->l_child != tmp)  pre = pre->l_child; //找倒數(shù)第二小的結(jié)點(diǎn) 
                pre->l_child = child;
            }
            else{       //無(wú)孩子或有一個(gè)孩子情況
                tmp = cur;
                cur = (cur->l_child != NULL) ? cur->l_child : cur->r_child;
                (pre->l_child == tmp) ? pre->l_child = cur : pre->r_child = cur;

            }
            delete tmp;
            break;
        }
    }
}

// 外部查找最大值
template<typename T>
void BinaryTree<T>::pubForFindMax(){
    cout << "該二叉樹(shù)的最大值為:" << findMax(root)->data << endl;
}
// 查找最大值
template<typename T>
TreeNode<T>* BinaryTree<T>::findMax(TreeNode<T> *p){
    /* 遞歸實(shí)現(xiàn) */
/*  if(p == NULL){
        return NULL;
    }
    if(p->r_child == NULL){
        return p;
    }
    return findMax(p->r_child);
*/  
    /* 非遞歸實(shí)現(xiàn) */
/*  while(p != NULL){
        if(p->r_child == NULL){
            return p;
        }
        p = p->r_child;
    }
    return NULL; 
*/
    /* 非遞歸實(shí)現(xiàn)2 */
    if(p != NULL){
        while(p->r_child != NULL){
            p = p->r_child;
        }
    }
    return p;
    
}

// 外部查找最小值
template<typename T>
void BinaryTree<T>::pubForFindMin(){
    cout << "該二叉樹(shù)的最小值為:" << findMin(root)->data << endl;
}
// 查找最小值
template<typename T>
TreeNode<T>* BinaryTree<T>::findMin(TreeNode<T> *p){
    /* 遞歸實(shí)現(xiàn) */
/*  if(p == NULL){
        return NULL;
    }
    //if(p->l_child == NULL || *((unsigned int *)p->l_child) == 0xFEEEFEEE ){
    if(p->l_child == NULL){
        p->l_child = NULL;
        return p;
    }
    return findMin(p->l_child);
*/
    /* 非遞歸實(shí)現(xiàn) 
    while(p != NULL){
        if(p->l_child == NULL){
            return p;
        }
        p = p->l_child;
    }
    return NULL; 
*/
    /* 非遞歸實(shí)現(xiàn)2 */
    if(p != NULL){
        while(p->l_child != NULL){
            p = p->l_child;
        }
    }
    return p;
}

// 外部查找二叉樹(shù)是否包含指定值的結(jié)點(diǎn)
template<typename T>
bool BinaryTree<T>::pubForContains(T et_value){
    return contains(et_value, root);
}
// 查找二叉樹(shù)是否包含指定值的結(jié)點(diǎn)
template<typename T>
bool BinaryTree<T>::contains(T et_value, TreeNode<T> *p){
    //遞歸實(shí)現(xiàn)
/*  if(p == NULL){
        return false;
    }
    if(et_value < p->data){
        contains(et_value, p->l_child);
    }
    else if(et_value > p->data){
        contains(et_value, p->r_child);
    }
    else{
        return true;
    }
*/
    //非遞歸實(shí)現(xiàn)
    while(p != NULL){
        if(et_value < p->data)
            p = p->l_child;
        else if(et_value > p->data)
            p = p->r_child;
        else
            return true;
    }
    return false;

}

#endif


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末股淡,一起剝皮案震驚了整個(gè)濱河市身隐,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌唯灵,老刑警劉巖贾铝,帶你破解...
    沈念sama閱讀 206,311評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異埠帕,居然都是意外死亡垢揩,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門敛瓷,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)叁巨,“玉大人,你說(shuō)我怎么就攤上這事琐驴》郑” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 152,671評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵绝淡,是天一觀的道長(zhǎng)宙刘。 經(jīng)常有香客問(wèn)我,道長(zhǎng)牢酵,這世上最難降的妖魔是什么悬包? 我笑而不...
    開(kāi)封第一講書人閱讀 55,252評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮馍乙,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘狗超。我一直安慰自己菇爪,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,253評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布棵譬。 她就那樣靜靜地躺著,像睡著了一般预伺。 火紅的嫁衣襯著肌膚如雪订咸。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 49,031評(píng)論 1 285
  • 那天酬诀,我揣著相機(jī)與錄音脏嚷,去河邊找鬼。 笑死瞒御,一個(gè)胖子當(dāng)著我的面吹牛父叙,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播肴裙,決...
    沈念sama閱讀 38,340評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼趾唱,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了践宴?” 一聲冷哼從身側(cè)響起鲸匿,我...
    開(kāi)封第一講書人閱讀 36,973評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎阻肩,沒(méi)想到半個(gè)月后带欢,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,466評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡烤惊,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,937評(píng)論 2 323
  • 正文 我和宋清朗相戀三年乔煞,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片柒室。...
    茶點(diǎn)故事閱讀 38,039評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡渡贾,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出雄右,到底是詐尸還是另有隱情空骚,我是刑警寧澤,帶...
    沈念sama閱讀 33,701評(píng)論 4 323
  • 正文 年R本政府宣布擂仍,位于F島的核電站囤屹,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏逢渔。R本人自食惡果不足惜肋坚,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,254評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧智厌,春花似錦诲泌、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,259評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至吝沫,卻和暖如春呻澜,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背惨险。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留脊髓,地道東北人辫愉。 一個(gè)月前我還...
    沈念sama閱讀 45,497評(píng)論 2 354
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像将硝,于是被迫代替她去往敵國(guó)和親恭朗。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,786評(píng)論 2 345

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