日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

真c++ 从二叉树到红黑树(1)之二叉树节点类及遍历详解

發(fā)布時間:2023/12/8 c/c++ 46 豆豆
生活随笔 收集整理的這篇文章主要介紹了 真c++ 从二叉树到红黑树(1)之二叉树节点类及遍历详解 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

??此文章為從二叉樹到紅黑樹系列文章的第一節(jié),主要介紹寫這系列文章的起因,致謝鄧?yán)蠋?#xff0c;解釋二叉樹節(jié)點類和二叉樹的四種遍歷寫法(包括遞歸和迭代寫法)


文章目錄

  • 一、前言與致謝~(點擊右邊波浪線可以返回目錄)
  • 二、本系列文章內(nèi)容基本介紹~
    • 1.與鄧?yán)蠋熢写a對比~
    • 2.主要流程(重點)~
    • 3.要看懂文章內(nèi)的代碼你需要了解的內(nèi)容~
  • 三、樹的語義規(guī)定~
    • 1.樹的高度與深度~
    • 2.樹的遍歷~
      • (1)樹的先序遍歷~
      • (2)樹的中序遍歷~
      • (3)樹的后序遍歷~
      • (4)樹的層次遍歷~
  • 四、基本二叉樹節(jié)點類~
    • (一)定義變量和接口~
      • 1.需要的變量~
      • 2.需要的接口~
      • 3.其他輔助函數(shù)~
      • 4.BinNode.h~
    • (二)通用全局靜態(tài)函數(shù)(不包含后面代碼就運行不了哦)~
      • BInNode_Macro.h~
    • (三)樹的四種遍歷~
      • (重點)借助仿函數(shù)來實現(xiàn)遍歷的高明方法~
      • 1.層次遍歷的隊列寫法~
      • 2.先序遍歷~
        • (1)先序遍歷選擇接口~
        • (2)先序遍歷的遞歸寫法~
        • (3)先序遍歷借助棧的迭代寫法1~
        • (4)先序遍歷借助棧的迭代寫法2--便于理解中序和后序的迭代寫法~
      • 3.中序遍歷~
        • (1)中序遍歷選擇接口~
        • (2)中序遍歷的遞歸寫法~
        • (3)中序遍歷借助棧的迭代寫法~
        • (4)中序遍歷不借助棧的迭代寫法--在理解了怎么求直接后繼后再來看~
      • 4.后序遍歷~
        • (1)后序遍歷選擇接口~
        • (2)后序遍歷的遞歸寫法~
        • (3)后序遍歷借助棧的迭代寫法~
          • a)找到當(dāng)前子樹后續(xù)遍歷的第一個節(jié)點~
          • b) 主遍歷函數(shù)~
          • c)后序遍歷迭代算法完整版~
    • (四)求當(dāng)前節(jié)點的直接后繼(用于中序遍歷)~
      • (1)若當(dāng)前節(jié)點有右孩子,則其直接后繼必然存在,且屬于其右子樹。~
      • (2)若當(dāng)前節(jié)點沒有右孩子,則其直接后繼若存在,并為其祖先。~
      • (3)后繼節(jié)點代碼~
    • (五)BinNode.h完整代碼~
  • 五.后序文章鏈接~

一、前言與致謝~(點擊右邊波浪線可以返回目錄)

??c++是一門與時俱進(jìn)的語言,縱觀網(wǎng)上絕大多數(shù)c++的數(shù)據(jù)結(jié)構(gòu)實現(xiàn),都是c with class,不得不說,這樣確實有利于理解和學(xué)習(xí),但對于那些想借助數(shù)據(jù)結(jié)構(gòu)來鞏固c++的人來說,不由得有點遺憾(初學(xué)直接啃stl源碼會直接自閉的)。

??在此,感謝清華的鄧俊輝老師的c++數(shù)據(jù)結(jié)構(gòu)教材和視頻,多虧了鄧?yán)蠋煹男燎诟?#xff0c;我才有幸見到現(xiàn)代化的適用于初學(xué)者的c++數(shù)據(jù)結(jié)構(gòu)代碼。在鄧?yán)蠋熃滩牡牡谖逭?#xff0c;第七章和第八章,全部是介紹樹的知識,看完和仿照敲完代碼之后,獲益匪淺,不止是對數(shù)據(jù)結(jié)構(gòu)和算法的理解更深了一步,也對c++的特性掌握的更加牢固了一步。

??筆者將其代碼中的一些特性進(jìn)行了一些更新和修改,讓其更符合現(xiàn)代風(fēng)格。由于老師對堆區(qū)數(shù)據(jù)的回收都處理的很好,有的地方用智能指針的話,需要改比較多的東西,所以還是保持原來的new和delete。

??本系列文章為了方便,會引用教材和視頻中的一些插圖(侵刪),雖然我對原代碼進(jìn)行了些許修改,但原代碼所有權(quán)依然歸鄧?yán)蠋熕?/strong>

??在寫此系列文章的時候,筆者也對文章進(jìn)行了排版,讓其更容易進(jìn)行閱讀,大家放心閱讀,筆者在適當(dāng)?shù)牡胤蕉剂袅丝招泻头侄巍?/strong>(md的排版真心沒word好= =,排個版都要敲代碼!)

??本系列文章的所有代碼,均在vs2019版本下編譯通過,如果你無法編譯過,請把編譯器的c++版本開啟c++17以上。

二、本系列文章內(nèi)容基本介紹~

1.與鄧?yán)蠋熢写a對比~

我主要對以下幾點進(jìn)行了更新和修改

  • 將所有的宏定義換成了c++11的constexpr和inline。有的換成了全局靜態(tài)函數(shù),有的換成了類中使用的函數(shù)。
  • 大概是處于教學(xué)需要,鄧公用的都是自定義的stack和queue,筆者就偷懶,直接用stl現(xiàn)成的stack和queue了,實現(xiàn)上大致相同。
  • 將原來的某些代碼進(jìn)行了增減,這樣更便于呈現(xiàn)主要內(nèi)容。
  • 所有主要代碼都有迭代形式,主要代碼流程中沒有遞歸,有的代碼會分別給出遞歸和迭代的形式,以便于理解。
  • 2.主要流程(重點)~

    筆者根據(jù)代碼的內(nèi)容不同,將分六部分來展現(xiàn)

  • 基本二叉樹節(jié)點,通用函數(shù)
  • 基本二叉樹類的定義和實現(xiàn)
  • BST(二叉搜索樹的實現(xiàn))
  • AVL(二叉平衡搜索樹的實現(xiàn))
  • B樹的實現(xiàn)(如果你只想了解B樹,可以跳過所有章節(jié),直接看B樹)
  • 紅黑樹的實現(xiàn)
  • ??強烈建議按照流程進(jìn)行瀏覽,只有這樣,你才能真正了解紅黑樹!

    ??但若你沒有時間,也沒關(guān)系,我會在一些重點部分,涉及到之前知識點的地方弄一個提示,去指明你去哪才能看到相關(guān)的內(nèi)容。

    3.要看懂文章內(nèi)的代碼你需要了解的內(nèi)容~

  • 掌握c++的引用,指針,類的基本使用
  • 知道什么是指針引用
  • 了解命名空間,using聲明,using別名。
  • 了解c++的模板,仿函數(shù)的使用
  • 熟悉stl中stack和queue容器的用法
  • 對constexpr和inline不陌生
  • 對樹有一定的了解
  • ??要完全看懂本系列文章,如果你是初次接觸,不要妄想能在兩三個小時內(nèi)弄懂此系列文章所有內(nèi)容,沒人可以做的到,正確的方法是一天抽一兩個小時研究其中一篇文章,對于紅黑樹可能需要更長的時間,你才能真正的看懂代碼,如果你看過鄧?yán)蠋煹慕坛痰脑?#xff0c;會更能體會到我這段話的意思。

    ??如果你嫌長,大可以看其他的文章,但我相信,弄懂本系列文章之后,不僅你的數(shù)據(jù)結(jié)構(gòu)的功底,還是c++的功底,都可以更上一層樓。(針對c++初學(xué)者)。

    三、樹的語義規(guī)定~

    1.樹的高度與深度~

    在此系列文章中,會大量用到樹的高度和深度的概念,在此做一個強調(diào)

    深度: 從根到該節(jié)點的唯一路徑長,根的深度為0;從上到下數(shù)
    高度 從該節(jié)點到葉節(jié)點的最長路徑,所有樹葉的高度為0;從下往上數(shù)

    另外,規(guī)定空樹的高度為-1

    所以,若只有根節(jié)點存在,根節(jié)點的高度為0。

    2.樹的遍歷~

    (1)樹的先序遍歷~

    先訪問根節(jié)點,再依次遍歷左子樹和右子樹 即根左右(一直左到底再右) 3102546

    (2)樹的中序遍歷~

    先訪問左子樹,再依次遍歷根和右子樹 即左根右(即將各個節(jié)點映射到一條直線上) 0123456

    (3)樹的后序遍歷~

    先訪問左子樹,再依次遍歷右子樹和根 即左右根 0214653

    (4)樹的層次遍歷~

    從上而下,從左到右訪問樹中各個節(jié)點 3150246

    四、基本二叉樹節(jié)點類~

    (一)定義變量和接口~

    1.需要的變量~

    T _data;//存放數(shù)據(jù) BinNodePtr _parent; BinNodePtr _lchild; BinNodePtr _rchild; int _height;//高度(通用) RBColor _color;//紅黑樹專用

    2.需要的接口~

    四種遍歷 取得當(dāng)前節(jié)點的直接后繼(BST,AVL,RedBlack用)

    3.其他輔助函數(shù)~

    判等器等操作符重載

    4.BinNode.h~

    namespace {enum class RBColor { RED, BLACK };}//===二叉樹節(jié)點類===//template<typename T = int>class BinNode {public:using BinNodePtr = BinNode<T>*;public:T _data;//存放數(shù)據(jù)BinNodePtr _parent;BinNodePtr _lchild;BinNodePtr _rchild;int _height;//高度(通用)RBColor _color;//紅黑樹專用public:BinNode() :_data(0), _parent(nullptr),_lchild(nullptr), _rchild(nullptr), _height(0), _color(RBColor::RED) {}BinNode(const T& data, const BinNodePtr parent = nullptr, const BinNodePtr lchild=nullptr, const BinNodePtr rchild=nullptr,const int &height=0, const RBColor& color = RBColor::RED):_data(data), _parent(parent), _lchild(lchild), _rchild(rchild),_height(height),_color(color) {}public:constexpr bool operator==(const BinNode& bN)const {return this->_data == bN._data;}constexpr bool operator!=(const BinNode& bN)const {return !(this->_data == bN._data);}constexpr bool operator<(const BinNode& bN)const {return this->_data < bN._data;}constexpr bool operator>(const BinNode& bN)const {return this->_data > bN._data;}constexpr bool operator<=(const BinNode& bN)const {return !(this->_data > bN._data);}constexpr bool operator>=(const BinNode& bN)const {return !(this->_data < bN._data);}public:BinNodePtr succ();//取得中序遍歷當(dāng)前節(jié)點的直接后繼,必然無左孩子public:template <typename VST> void travLevel(VST); //子樹層次遍歷template <typename VST> void travPre(VST,const int &method=1); //子樹先序遍歷template <typename VST> void travPost(VST,const int&method=1); //子樹后序遍歷template <typename VST> void travIn(VST,const int&method=1); //子樹中序遍歷};//class BinNode

    (二)通用全局靜態(tài)函數(shù)(不包含后面代碼就運行不了哦)~

    ??鄧?yán)蠋煏系暮甓x有很多個,我將用的多的封裝成相應(yīng)的constexpr和inline函數(shù),將用的少的放入對應(yīng)的樹的類中,這樣更有利于管理和應(yīng)用。

    BInNode_Macro.h~

    #pragma once/******************************************************************************************* BinNode狀態(tài)與性質(zhì)的判斷******************************************************************************************/#include<algorithm> using std::max;namespace mytree_marcro {template<typename BinNodePtr>static constexpr bool IsRoot(const BinNodePtr& x) {return !(x->_parent);}template<typename BinNodePtr>static constexpr bool IsLChild(const BinNodePtr& x) {return (!IsRoot(x) && (x == x->_parent->_lchild));}template<typename BinNodePtr>static constexpr bool IsRChild(const BinNodePtr& x) {return (!IsRoot(x) && (x == x->_parent->_rchild));//不是根節(jié)點,并且其地址跟其父親的右孩子地址相同}template<typename BinNodePtr>static constexpr bool HasLChild(const BinNodePtr& x) {return (x == nullptr) ? false : x->_lchild;}template<typename BinNodePtr>static constexpr bool HasRChild(const BinNodePtr& x) {return (x == nullptr) ? false : x->_rchild;}template<typename BinNodePtr>static constexpr int stature(const BinNodePtr& x) {//獲取高度return x ? x->_height : -1;//空指針高度為-1}}// namespace mytree_marcro

    (三)樹的四種遍歷~

    (重點)借助仿函數(shù)來實現(xiàn)遍歷的高明方法~

    ??對于老手和善用stl的人而言, 這種利用回調(diào)函數(shù)來進(jìn)行訪問對應(yīng)節(jié)點的方式,再正常不過。在鄧?yán)蠋煹谋闅v代碼中,就高明的用了這種方式,通過這種高內(nèi)聚,低耦合的方式,從而能對節(jié)點進(jìn)行更多的操作,而并非僅僅是cout就完事。在之后的BST,AVL和RedBlack中,我都會提供一些測試用的仿函數(shù),讀者可根據(jù)自己的需要進(jìn)行改進(jìn)。

    1.層次遍歷的隊列寫法~

    ??根節(jié)點入隊,然后彈出根節(jié)點,并將其左右節(jié)點入隊。直至隊列為空。

    template<typename T>template<typename VST> void BinNode<T>::travLevel(VST visit) {if (this == nullptr)//提前判斷是否為空樹return;queue<BinNodePtr> Q;Q.push(this);//根節(jié)點入隊BinNodePtr current = nullptr;//防止多次調(diào)用構(gòu)造析構(gòu),故在循環(huán)為創(chuàng)建臨時變量while (!Q.empty()) {//如果隊列不為空current = Q.front();visit(current);Q.pop();if (HasLChild(current))Q.push(current->_lchild);if (HasRChild(current))Q.push(current->_rchild);} }

    2.先序遍歷~

    (1)先序遍歷選擇接口~

    由于有三種先序遍歷的寫法,因此創(chuàng)建一個接口函數(shù),并且默認(rèn)調(diào)用迭代版的先序遍歷

    template<typename T>template<typename VST> void BinNode<T>::travPre(VST visit,const int& method) {using mytree_trav::travPre_1;using mytree_trav::travPre_2;using mytree_trav::travPre_R;if (this == nullptr)//提前判斷是否為空樹return;switch (method){case 0:travPre_1(this, visit); break;case 1:travPre_2(this, visit); break;default:travPre_R(this, visit); break;} }

    (2)先序遍歷的遞歸寫法~

    以根左右的順序,進(jìn)行遞歸先序遍歷

    /*先序遍歷遞歸版*/ template<typename BinNodePtr, typename VST> static void travPre_R(BinNodePtr x, VST visit) {if (x == nullptr)return;visit(x);travPre_R(x->_lchild, visit);travPre_R(x->_rchild, visit); }

    (3)先序遍歷借助棧的迭代寫法1~

    ??尾遞歸轉(zhuǎn)化為循環(huán)。如果只有一個遞歸體,那么直接轉(zhuǎn)循環(huán)就可以。因為此處有兩個遞歸體,因此,還需要借助一個輔助棧來實現(xiàn)。

    ??遞歸時,分成3部分來看,第一部分基本語句,第二部分遞歸調(diào)用左孩子,第三部分遞歸調(diào)用右孩子。
    ??從遞歸時函數(shù)調(diào)用的堆棧分析來看,相當(dāng)于先把最后一個語句,也就是遍歷右孩子入棧,再把倒數(shù)第二個語句,也就是遍歷左孩子入棧,下一步就是取出棧頂元素進(jìn)行遍歷。重復(fù)循環(huán)。理解了此點,你就能很快的理解為什么需要一個輔助棧!

    //-----------先序遍歷--------------// /*迭代版1*//*遞歸轉(zhuǎn)迭代*//*此法與迭代2在效率上,沒什么區(qū)別,但是此法只適用于先序*而迭代2的方式,可以適用于中序和后序遍歷*/ template<typename BinNodePtr, typename VST> static void travPre_1(BinNodePtr x, VST visit) {stack<BinNodePtr> S;S.push(x);while (!S.empty()) {x = S.top();S.pop();visit(x);if (HasRChild(x))//入棧次序為先右后左S.push(x->_rchild);if (HasLChild(x))S.push(x->_lchild);} }

    (4)先序遍歷借助棧的迭代寫法2–便于理解中序和后序的迭代寫法~

    ??從書上虛線的的路徑,不難發(fā)現(xiàn)遍歷過程中的一個套路,即遍歷可以等價的理解成,從當(dāng)前節(jié)點從上到下訪問左子樹并visit對應(yīng)的節(jié)點,直到訪問到左子樹為空為止,同時在途中將右孩子均存入棧中。當(dāng)左子樹訪問到根節(jié)點時,就取出棧頂元素,繼續(xù)做一次從上到下的向左遍歷。

    /*迭代版2*/ template<typename BinNodePtr, typename VST> static void visitLeft_Pre(BinNodePtr x, VST visit, stack<BinNodePtr>& S) {while (x) {visit(x);//訪問當(dāng)前節(jié)點if (HasRChild(x))//右孩子入棧暫存S.push(x->_rchild);x = x->_lchild;} }template<typename BinNodePtr, typename VST> static void travPre_2(BinNodePtr x, VST visit) {stack<BinNodePtr> S;while (true) {visitLeft_Pre(x, visit, S);//從當(dāng)前節(jié)點出發(fā),從上到下,向左訪問。if (S.empty())//直到棧空break;x = S.top();//若棧不空,則取出棧頂節(jié)點繼續(xù)循環(huán)S.pop();} }

    3.中序遍歷~

    (1)中序遍歷選擇接口~

    由于有三種中序遍歷的寫法,因此創(chuàng)建一個接口函數(shù),并且默認(rèn)調(diào)用迭代版的中序遍歷

    template<typename T>template<typename VST> void BinNode<T>::travIn(VST visit, const int& method) {using mytree_trav::travIn_1;using mytree_trav::travIn_2;using mytree_trav::travIn_R;if (this == nullptr)//提前判斷是否為空樹return;switch (method){case 1:travIn_1(this, visit); break;//1相對普通樹最快case 2:travIn_2(this, visit); break;default:travIn_R(this, visit); break;} }

    (2)中序遍歷的遞歸寫法~

    以左根右的順序,進(jìn)行遞歸中序遍歷

    /*遞歸版*/ template<typename BinNodePtr,typename VST> static void travIn_R(BinNodePtr x, VST visit) {if (x == nullptr)return;travIn_R(x->_lchild,visit);visit(x);travIn_R(x->_rchild,visit); }

    (3)中序遍歷借助棧的迭代寫法~


    ??從上圖可以看出,我們遍歷時第一個訪問的必然是最左邊的節(jié)點a,但我們的傳入的節(jié)點一般為根節(jié)點,即都是從i開始進(jìn)行中序遍歷的。因此,首先也必須要到最左邊的節(jié)點a,即要做一次從上到下的向左訪問左子樹,而沿途的節(jié)點都不妨存入棧中,方便之后使用。

    ??每從棧中彈出一個節(jié)點,就對其進(jìn)行visit,都需要對其有沒有右孩子進(jìn)行檢查,如果有右孩子,則右孩子入棧,并且對右孩子也做一次從上到下的向左遍歷,將沿途的節(jié)點全部存入棧中。

    ??這樣一直到棧為空為止。

    //---------中序遍歷---------// template<typename BinNodePtr> static void visitLeft_In(BinNodePtr x, stack<BinNodePtr>& S) {//將所有左孩子插入棧中while (x) {S.push(x);x = x->_lchild;} }/*迭代版1*/ template<typename BinNodePtr, typename VST> static void travIn_1(BinNodePtr x, VST visit) {stack<BinNodePtr> S;while (true) {visitLeft_In(x, S);//將所有左孩子插入棧中if (S.empty())break;x = S.top();visit(x);S.pop();x = x->_rchild;//如果棧頂元素有右孩子,則對右孩子的左子樹進(jìn)行visitLeft_In,若右孩子為空,則直接結(jié)束visitLeft_In} }

    (4)中序遍歷不借助棧的迭代寫法–在理解了怎么求直接后繼后再來看~

    ??本方法實際上本人不推薦使用,因為其每一次遍歷都需要去求后繼,無疑相對前面一種迭代方法而言,增加了不必要的代價。

    ??因此,此法有興趣者可以看看。此法最重要的是一種利用后繼來遍歷的思想,這點對于線索二叉樹而言非常有效。有興趣的讀者可以看看本人按照大話數(shù)據(jù)結(jié)構(gòu)改編的線索二叉樹的c++代碼https://blog.csdn.net/bioinformatique/article/details/106082423

    /*迭代版2*/ template<typename BinNodePtr, typename VST> static void travIn_2(BinNodePtr x, VST visit) {while (true) {if (HasLChild(x)) {//若有左子樹,則x = x->_lchild;//深入左子樹}else {visit(x);//訪問當(dāng)前節(jié)點,并while (!HasRChild(x)) {//不斷地在無右分支處if (x = x->succ())//回溯至直接后繼,注意此處為賦值visit(x);//如果有后繼,則訪問elsereturn; //(在沒有后繼的末節(jié)點處,直接退出)}x = x->_rchild;//(直至有右分支處)轉(zhuǎn)向非空的右子樹}} }

    4.后序遍歷~

    (1)后序遍歷選擇接口~

    由于有兩種后序遍歷的寫法,因此創(chuàng)建一個接口函數(shù),并且默認(rèn)調(diào)用迭代版的后序遍歷

    template<typename T>template<typename VST> void BinNode<T>::travPost(VST visit, const int& method) {using mytree_trav::travPost_1;using mytree_trav::travPost_R;if (this == nullptr)//提前判斷是否為空樹return;switch (method){case 1:travPost_1(this, visit); break;default:travPost_R(this, visit); break;} }

    (2)后序遍歷的遞歸寫法~

    以左右根的順序,進(jìn)行遞歸后序遍歷

    /*遞歸版*/ template<typename BinNodePtr, typename VST> static void travPost_R(BinNodePtr x, VST visit) {if (x == nullptr)return;travPost_R(x->_lchild, visit);travPost_R(x->_rchild, visit);visit(x); }

    (3)后序遍歷借助棧的迭代寫法~


    ??后序遍歷與中序和先序遍歷不同的是,后序遍歷的第一個被訪問的節(jié)點稍有不同,其沒有先序(必然為根節(jié)點)和中序(必然為最左孩子)這樣的規(guī)律性。

    ??1. 若最左邊孩子沒有右子樹(最左邊孩子顯然沒有左子樹),則最左邊節(jié)點是第一個被訪問的節(jié)點。
    ??2. 若最左邊孩子有右子樹,則是最左邊的節(jié)點的右子樹的最左邊的節(jié)點。

    ??首先,無論如何,都需要找到第一個節(jié)點。并且沿途的節(jié)點也要像中序和前序遍歷一樣很好地利用起來。幸運的是,鄧?yán)蠋熞呀?jīng)幫我們解決了這個難題。

    a)找到當(dāng)前子樹后續(xù)遍歷的第一個節(jié)點~

    ??方法就是從當(dāng)前節(jié)點開始,先看其有沒有右孩子,如果有右孩子,則將右孩子入棧,然后再看有沒有左孩子,如果有左孩子,則將左孩子再入棧,并且將左孩子當(dāng)做“當(dāng)前節(jié)點”繼續(xù)循環(huán)。

    ??如果當(dāng)前節(jié)點沒有左孩子,則看這個節(jié)點的右孩子有沒有孩子,如果這個節(jié)點的右孩子有孩子,則把這個節(jié)點作為“當(dāng)前節(jié)點”,繼續(xù)進(jìn)行循環(huán)。

    ??直到“當(dāng)前節(jié)點”沒有孩子為止。那么,此時的棧頂元素,必將為當(dāng)前樹(子樹)的后序遍歷應(yīng)該訪問的第一個節(jié)點。

    如下圖,第一個節(jié)點顯然是a



    代碼實現(xiàn)為

    template<typename BinNodePtr> static void visitLeft_Post(stack<BinNodePtr>& S) {BinNodePtr x = S.top();//將棧頂節(jié)點作為當(dāng)前節(jié)點while (true) {//判斷是否有左右孩子,并且先插入右孩子if (HasRChild(x)) {S.push(x->_rchild);}if (HasLChild(x)) {S.push(x->_lchild);}if (x == S.top())//說明棧沒有插入任何元素,即抵達(dá)此子樹應(yīng)該被訪問的第一個節(jié)點break;x = S.top();//否則就將棧頂元素給當(dāng)前的x} }
    b) 主遍歷函數(shù)~

    ??在解決了找到當(dāng)前子樹的相對后繼遍歷的第一個節(jié)點后,就解決了后繼遍歷的絕大多數(shù)問題。并且,并非在遍歷過程中,所有的節(jié)點都需要去執(zhí)行visitLeft_Post函數(shù)。

    再來觀看此圖,以及此時的棧結(jié)構(gòu)



    我們需要對b進(jìn)行一次visitLeft_Post函數(shù)么,顯然不需要,因為其沒有左子樹。
    因此直接訪問b。

    下一個被訪問的元素為G么?,顯然不是G,其左右子樹也都沒有在棧中,因此,我們需要以G為子樹進(jìn)行一次visitLeft_Post函數(shù),從而找到c。

    從上面3個圖可以看出,訪問b前不需要進(jìn)行visitLeft_Post函數(shù),訪問c時需要進(jìn)行visitLeft_Post函數(shù)。那么,到底什么時候需要進(jìn)行visitLeft_Post函數(shù)?

    ??不妨看一下父子關(guān)系。b是a的父親,而G不是b的父親,反而,G是b的兄弟節(jié)點!

    ??不妨可以得出結(jié)論,只有當(dāng)此時棧頂元素不是剛剛彈出的棧頂元素的父親時(必然為剛彈出元素的兄弟),才會進(jìn)行visitLeft_Post函數(shù),將新的節(jié)點插入棧中。

    下面給出后序遍歷迭代版的算法

    /*迭代版*/ template<typename BinNodePtr, typename VST> static void travPost_1(BinNodePtr x, VST visit) {stack<BinNodePtr> S;S.push(x);while (!S.empty()) {//若棧頂節(jié)點不是父親節(jié)點,即必為其兄弟節(jié)點(除了根節(jié)點以外),//若為其兄弟節(jié)點,則對兄弟節(jié)點進(jìn)行visitLeft_Post的操作。if (S.top() != x->_parent)visitLeft_Post(S);visit(S.top());x = S.top();//將x設(shè)為棧頂元素S.pop();} }
    c)后序遍歷迭代算法完整版~
    //--------------后序遍歷--------------// template<typename BinNodePtr> static void visitLeft_Post(stack<BinNodePtr>& S) {BinNodePtr x = S.top();//將棧頂節(jié)點作為當(dāng)前節(jié)點while (true) {//判斷是否有左右孩子,并且先插入右孩子if (HasRChild(x)) {S.push(x->_rchild);}if (HasLChild(x)) {S.push(x->_lchild);}if (x == S.top())//說明棧沒有插入任何元素,即抵達(dá)此子樹應(yīng)該被訪問的第一個節(jié)點break;x = S.top();//否則就將棧頂元素給當(dāng)前的x} }/*迭代版*/ template<typename BinNodePtr, typename VST> static void travPost_1(BinNodePtr x, VST visit) {stack<BinNodePtr> S;S.push(x);while (!S.empty()) {//若棧頂節(jié)點不是父親節(jié)點,即必為其兄弟節(jié)點(除了根節(jié)點以外),//若為其兄弟節(jié)點,則對兄弟節(jié)點進(jìn)行visitLeft_Post的操作。if (S.top() != x->_parent)visitLeft_Post(S);visit(S.top());x = S.top();//將x設(shè)為棧頂元素S.pop();} }

    (四)求當(dāng)前節(jié)點的直接后繼(用于中序遍歷)~

    succ()取得當(dāng)前節(jié)點的后繼節(jié)點

    ??與所有遍歷一樣,中序遍歷的實質(zhì)功能也可理解為,為所有節(jié)點賦予一個次序,從而將半線性的二叉樹轉(zhuǎn)化為線性結(jié)構(gòu)。于是一旦指定了遍歷策略,即可與向量和列表一樣,在二叉樹的節(jié)點之間定義后繼關(guān)系。其中沒有后繼)的節(jié)點稱作末節(jié)點。

    ??對于后面將要介紹的BST,AVL,RedBlack,中序遍歷的作用至關(guān)重要。相關(guān)算法必需的一項基本操作,就是定位任一節(jié)點在中序遍歷序列中的直接后繼。

    ??分析一個節(jié)點的后繼,不妨分做兩種情況分別進(jìn)行考慮。

    (1)若當(dāng)前節(jié)點有右孩子,則其直接后繼必然存在,且屬于其右子樹。~

    ??在這種情況下,當(dāng)前節(jié)點的直接后繼,必然沒有左孩子。

    如下圖a的右孩子b存在,b沒有左孩子,即b為a的直接后繼

    如下圖d的右孩子h存在,h有左孩子,即e為d的直接后繼

    (2)若當(dāng)前節(jié)點沒有右孩子,則其直接后繼若存在,并為其祖先。~

    如下圖b的右孩子不存在,則其直接后繼若存在,必為其某一祖先,即c為b的直接后繼

    如下圖p的右孩子不存在,但其已經(jīng)為全樹的最右節(jié)點,因此其沒有后繼

    讀者們可以根據(jù)中序遍歷來進(jìn)一步體會節(jié)點的后繼

    (3)后繼節(jié)點代碼~

    //-------取得當(dāng)前節(jié)點的直接后繼----------// template<typename T> BinNode<T>* BinNode<T>::succ() {using BinNodePtr = BinNode<T>*;BinNodePtr s = this;if (HasRChild(s)) {//當(dāng)前節(jié)點有右孩子s = s->_rchild;while (HasLChild(s))//這個右孩子有沒有左孩子,直到?jīng)]有左孩子為止s = s->_lchild;}else {//必須分是否是右孩子來判斷,因為這對應(yīng)不同的情況,如果這個節(jié)點不為右孩子,則返回其父親//如果這個節(jié)點是右孩子,則需要不斷向上找其父親,直到不為右孩子為止(即為左孩子或根節(jié)點)while (IsRChild(s))s = s->_parent;s = s->_parent;//再往上找一格,就能找到后繼。//當(dāng)然,如果已經(jīng)到了根節(jié)點,根節(jié)點的父親當(dāng)然為空。所以返回空。同時也說明這個節(jié)點是最后一個節(jié)點。}return s; }

    (五)BinNode.h完整代碼~

    #pragma once#include<queue> #include<stack> #include "BinNode_Macro.h"using std::queue; using std::stack;namespace mytree {using namespace mytree_marcro;namespace {enum class RBColor { RED, BLACK };}//===二叉樹節(jié)點類===//template<typename T = int>class BinNode {public:using BinNodePtr = BinNode<T>*;public:T _data;//存放數(shù)據(jù)BinNodePtr _parent;BinNodePtr _lchild;BinNodePtr _rchild;int _height;//高度(通用)RBColor _color;//紅黑樹專用public:BinNode() :_data(0), _parent(nullptr),_lchild(nullptr), _rchild(nullptr), _height(0), _color(RBColor::RED) {}BinNode(const T& data, const BinNodePtr parent = nullptr, const BinNodePtr lchild=nullptr, const BinNodePtr rchild=nullptr,const int &height=0, const RBColor& color = RBColor::RED):_data(data), _parent(parent), _lchild(lchild), _rchild(rchild),_height(height),_color(color) {}public:constexpr bool operator==(const BinNode& bN)const {return this->_data == bN._data;}constexpr bool operator!=(const BinNode& bN)const {return !(this->_data == bN._data);}constexpr bool operator<(const BinNode& bN)const {return this->_data < bN._data;}constexpr bool operator>(const BinNode& bN)const {return this->_data > bN._data;}constexpr bool operator<=(const BinNode& bN)const {return !(this->_data > bN._data);}constexpr bool operator>=(const BinNode& bN)const {return !(this->_data < bN._data);}public:BinNodePtr succ();//取得中序遍歷當(dāng)前節(jié)點的直接后繼,必然無左孩子public:template <typename VST> void travLevel(VST); //子樹層次遍歷template <typename VST> void travPre(VST,const int &method=1); //子樹先序遍歷template <typename VST> void travPost(VST,const int&method=1); //子樹后序遍歷template <typename VST> void travIn(VST,const int&method=1); //子樹中序遍歷};//class BinNode//--------------遍歷------------------//namespace mytree_trav {//-----------先序遍歷--------------///*迭代版1*//*遞歸轉(zhuǎn)迭代*//*此法與迭代2在效率上,沒什么區(qū)別,但是此法只適用于先序*而迭代2的方式,可以適用于中序和后序遍歷*/template<typename BinNodePtr, typename VST>static void travPre_1(BinNodePtr x, VST visit) {stack<BinNodePtr> S;S.push(x);while (!S.empty()) {x = S.top();S.pop();visit(x);if (HasRChild(x))//入棧次序為先右后左S.push(x->_rchild);if (HasLChild(x))S.push(x->_lchild);}}/*迭代版2*/template<typename BinNodePtr, typename VST>static void visitLeft_Pre(BinNodePtr x, VST visit, stack<BinNodePtr>& S) {while (x) {visit(x);//訪問當(dāng)前節(jié)點if (HasRChild(x))//右孩子入棧暫存S.push(x->_rchild);x = x->_lchild;}}template<typename BinNodePtr, typename VST>static void travPre_2(BinNodePtr x, VST visit) {stack<BinNodePtr> S;while (true) {visitLeft_Pre(x, visit, S);//從當(dāng)前節(jié)點出發(fā),從上到下,向左訪問。if (S.empty())//直到棧空break;x = S.top();//若棧不空,則取出棧頂節(jié)點繼續(xù)循環(huán)S.pop();}}/*先序遍歷遞歸版*/template<typename BinNodePtr, typename VST>static void travPre_R(BinNodePtr x, VST visit) {if (x == nullptr)return;visit(x);travPre_R(x->_lchild, visit);travPre_R(x->_rchild, visit);}//--------------后序遍歷--------------//template<typename BinNodePtr>static void visitLeft_Post(stack<BinNodePtr>& S) {BinNodePtr x = S.top();//將棧頂節(jié)點作為當(dāng)前節(jié)點while (true) {//判斷是否有左右孩子,并且先插入右孩子if (HasRChild(x)) {S.push(x->_rchild);}if (HasLChild(x)) {S.push(x->_lchild);}if (x == S.top())//說明棧沒有插入任何元素,即抵達(dá)此子樹應(yīng)該被訪問的第一個節(jié)點break;x = S.top();//否則就將棧頂元素給當(dāng)前的x}}/*迭代版*/template<typename BinNodePtr, typename VST>static void travPost_1(BinNodePtr x, VST visit) {stack<BinNodePtr> S;S.push(x);while (!S.empty()) {//若棧頂節(jié)點不是父親節(jié)點,即必為其兄弟節(jié)點(除了根節(jié)點以外),若為其兄弟節(jié)點,則對兄弟節(jié)點進(jìn)行visitLeft_Post的操作。if (S.top() != x->_parent)visitLeft_Post(S);visit(S.top());x = S.top();//將x設(shè)為棧頂元素S.pop();}}/*遞歸版*/template<typename BinNodePtr, typename VST>static void travPost_R(BinNodePtr x, VST visit) {if (x == nullptr)return;travPost_R(x->_lchild, visit);travPost_R(x->_rchild, visit);visit(x);}//---------中序遍歷---------//template<typename BinNodePtr>static void visitLeft_In(BinNodePtr x, stack<BinNodePtr>& S) {//將所有左孩子插入棧中while (x) {S.push(x);x = x->_lchild;}}/*迭代版1*/template<typename BinNodePtr, typename VST>static void travIn_1(BinNodePtr x, VST visit) {stack<BinNodePtr> S;while (true) {visitLeft_In(x, S);//將所有左孩子插入棧中if (S.empty())break;x = S.top();visit(x);S.pop();x = x->_rchild;//如果棧頂元素有右孩子,則對右孩子的左子樹進(jìn)行visitLeft_In,若右孩子為空,則直接結(jié)束visitLeft_In}}/*迭代版2*/template<typename BinNodePtr, typename VST>static void travIn_2(BinNodePtr x, VST visit) {while (true) {if (HasLChild(x)) {//若有左子樹,則x = x->_lchild;//深入左子樹}else {visit(x);//訪問當(dāng)前節(jié)點,并while (!HasRChild(x)) {//不斷地在無右分支處if (x = x->succ())//回溯至直接后繼,注意此處為賦值visit(x);//如果有后繼,則訪問elsereturn; //(在沒有后繼的末節(jié)點處,直接退出)}x = x->_rchild;//(直至有右分支處)轉(zhuǎn)向非空的右子樹}}}/*遞歸版*/template<typename BinNodePtr,typename VST>static void travIn_R(BinNodePtr x, VST visit) {if (x == nullptr)return;travIn_R(x->_lchild,visit);visit(x);travIn_R(x->_rchild,visit);}}//namespace mytree_travtemplate<typename T>template<typename VST>void BinNode<T>::travLevel(VST visit) {if (this == nullptr)//提前判斷是否為空樹return;queue<BinNodePtr> Q;Q.push(this);//根節(jié)點入隊BinNodePtr current = nullptr;//防止多次調(diào)用構(gòu)造析構(gòu),故在循環(huán)為創(chuàng)建臨時變量while (!Q.empty()) {//如果隊列不為空current = Q.front();visit(current);Q.pop();if (HasLChild(current))Q.push(current->_lchild);if (HasRChild(current))Q.push(current->_rchild);}}template<typename T>template<typename VST>void BinNode<T>::travPre(VST visit,const int& method) {using mytree_trav::travPre_1;using mytree_trav::travPre_2;using mytree_trav::travPre_R;if (this == nullptr)//提前判斷是否為空樹return;switch (method){case 0:travPre_1(this, visit); break;case 1:travPre_2(this, visit); break;default:travPre_R(this, visit); break;}}template<typename T>template<typename VST>void BinNode<T>::travPost(VST visit, const int& method) {using mytree_trav::travPost_1;using mytree_trav::travPost_R;if (this == nullptr)//提前判斷是否為空樹return;switch (method){case 1:travPost_1(this, visit); break;default:travPost_R(this, visit); break;}}template<typename T>template<typename VST>void BinNode<T>::travIn(VST visit, const int& method) {using mytree_trav::travIn_1;using mytree_trav::travIn_2;using mytree_trav::travIn_R;if (this == nullptr)//提前判斷是否為空樹return;switch (method){case 1:travIn_1(this, visit); break;//1相對普通樹最快case 2:travIn_2(this, visit); break;default:travIn_R(this, visit); break;}}//-------取得當(dāng)前節(jié)點的直接后繼----------//template<typename T>BinNode<T>* BinNode<T>::succ() {using BinNodePtr = BinNode<T>*;BinNodePtr s = this;if (HasRChild(s)) {//當(dāng)前節(jié)點有右孩子s = s->_rchild;while (HasLChild(s))//這個右孩子有沒有左孩子,直到?jīng)]有左孩子為止s = s->_lchild;}else {//必須分是否是右孩子來判斷,因為這對應(yīng)不同的情況,如果這個節(jié)點不為右孩子,則返回其父親//如果這個節(jié)點是右孩子,則需要不斷向上找其父親,直到不為右孩子為止(即為左孩子或根節(jié)點)while (IsRChild(s))s = s->_parent;s = s->_parent;//再往上找一格,就能找到后繼。//當(dāng)然,如果已經(jīng)到了根節(jié)點,根節(jié)點的父親當(dāng)然為空。所以返回空。同時也說明這個節(jié)點是最后一個節(jié)點。}return s;} }//namespace mytree

    五.后序文章鏈接~

  • 基本二叉樹節(jié)點,通用函數(shù) 二叉樹節(jié)點
  • 基本二叉樹類的定義和實現(xiàn) 二叉樹基類
  • BST(二叉搜索樹的實現(xiàn)) BST
  • AVL(二叉平衡搜索樹的實現(xiàn))AVL
  • B樹的實現(xiàn)(如果你只想了解B樹,可以跳過所有章節(jié),直接看B樹)B樹
  • 紅黑樹的實現(xiàn) RedBlack
  • 學(xué)一個東西,不知道其道理,不高明!

    總結(jié)

    以上是生活随笔為你收集整理的真c++ 从二叉树到红黑树(1)之二叉树节点类及遍历详解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

    中文字幕高清在线 | 在线看一级片 | 国产69精品久久久久久 | 国产资源网站 | 人人爽人人爽人人 | 天天色天天 | 97超碰人人澡 | 在线观看亚洲精品 | www.久艹 | 美女网站色在线观看 | 在线成人免费av | 久久精久久精 | 精品在线播放 | 婷婷在线五月 | 丁香九月激情 | 日韩免费视频观看 | 永久免费视频国产 | 免费一级特黄毛大片 | 日韩精品久久久久久久电影竹菊 | 国产精在线 | 美女视频黄免费网站 | 国产资源在线视频 | 国产视频欧美视频 | 国产理论在线 | 日韩欧美精品一区 | 中文字幕一二 | 国产成人在线播放 | 日韩三级视频在线观看 | 天堂av免费观看 | 视频国产一区二区三区 | 国产精品免费人成网站 | 久在线观看视频 | 日韩在线精品 | 国外av在线 | 天天碰天天操 | 天堂av在线免费观看 | 午夜久久影视 | 五月婷丁香 | 91.dizhi永久地址最新 | 国内揄拍国产精品 | 91视频国产高清 | 久久99九九99精品 | 免费久久片| av线上免费观看 | 天天操天天干天天爱 | 久久九九国产精品 | 日韩在线短视频 | 91在线视频免费播放 | 97精品国产91久久久久久久 | 香蕉久草在线 | 国产精品美女免费 | 午夜私人影院久久久久 | av免费电影在线观看 | 天天在线操 | 香蕉视频免费在线播放 | 狠狠干夜夜爽 | 欧美日韩在线视频观看 | 免费视频 三区 | 九九有精品 | 天堂在线一区二区三区 | 日韩精品在线视频免费观看 | 手机av资源 | 日韩夜夜爽 | 91精品久久久久久粉嫩 | 91大片成人网| 成人免费视频网站在线观看 | 国产精品久久99 | 91精品久久久久久综合乱菊 | 天天爽夜夜爽精品视频婷婷 | 亚洲乱码中文字幕综合 | 欧美成人久久 | 一级黄毛片 | 天干啦夜天干天干在线线 | 欧美日韩在线视频免费 | 超碰在线97国产 | 国内揄拍国内精品 | 在线免费观看羞羞视频 | 久久综合免费 | 国产美女精品视频 | 天天操天天操 | 中文字幕在线观看的网站 | 国产精品每日更新 | 97超碰人人澡人人爱 | 成人黄在线| 91自拍91| 成人免费观看大片 | 日韩免费视频 | 国产一区影院 | 久久国产精品99精国产 | 亚洲动漫在线观看 | 丁香婷婷激情国产高清秒播 | 久久成电影 | 91最新在线视频 | 99国产精品免费网站 | 久久久久久久99 | 黄色影院在线免费观看 | 西西人体www444 | 在线看国产精品 | 国产黄av | 9797在线看片亚洲精品 | 99热免费在线 | 欧美夫妻性生活电影 | 国语麻豆| 国产精品久久久久久久久久直播 | 天天色天天 | 久久精品99久久久久久 | 国产精华国产精品 | 操高跟美女| 国产精品永久免费观看 | 欧美一区二区精美视频 | 欧美va天堂va视频va在线 | 亚洲香蕉在线观看 | 精品免费国产一区二区三区四区 | 五月婷婷综合在线视频 | 欧美视频国产视频 | 成人福利在线播放 | 国产中文在线播放 | 午夜精品99久久免费 | 99精品国产亚洲 | 狠狠色丁香久久婷婷综 | 在线精品亚洲一区二区 | 狠狠精品 | 中文字幕乱码亚洲精品一区 | 97人人模人人爽人人喊网 | 一级片视频免费观看 | 日韩高清av在线 | 午夜电影中文字幕 | 最新日韩在线观看 | 中文字幕久久精品一区 | 波多野结衣小视频 | 久久久久国产一区二区三区四区 | 久久精品久久综合 | 美女视频久久黄 | 国产精品久久久久久超碰 | 97超碰免费在线 | 日韩爱爱片 | 综合天天久久 | 香蕉网在线观看 | 中日韩免费视频 | 国产精品久久久久亚洲影视 | 国内精品久久久久影院优 | 国产中文字幕亚洲 | 91香蕉视频在线下载 | 人人看黄色 | 久久精品欧美一区二区三区麻豆 | 一级大片在线观看 | 日韩手机视频 | 午夜精品影院 | 亚洲国内精品在线 | 成人理论在线观看 | 成人avav| 免费观看性生活大片3 | 色婷婷精品大在线视频 | 国产精品一区二区久久国产 | 国产美女精品 | 婷婷5月色| 日本一区二区免费在线观看 | 成人免费观看完整版电影 | 中文字幕在线国产精品 | 激情欧美国产 | 国内精品久久久久久久影视麻豆 | 夜夜摸夜夜爽 | 日韩在线电影观看 | 欧美激情视频在线观看免费 | 久久国产精品精品国产色婷婷 | 91精品日韩 | 黄色日本免费 | 中文字幕综合在线 | 奇米影音四色 | 免费在线观看污 | 欧美日韩国产一区 | 天天干天天操天天射 | 在线精品视频免费播放 | 国产一级免费观看 | 中文字幕高清在线 | 丁香婷婷综合激情 | 中文字幕二区 | 99精品视频在线看 | 成人久久久久久久久久 | 手机在线看永久av片免费 | 在线观看网站你懂的 | 国产a网站 | 久久久久国产成人免费精品免费 | 俺要去色综合狠狠 | 日韩美女黄色片 | 国产午夜在线观看 | 在线高清一区 | 久久在线观看 | 成人h视频在线播放 | 国产高清久久 | 国产精品毛片久久久久久 | 日韩精品欧美专区 | 久久福利 | 国内精品久久久久影院一蜜桃 | 国产麻豆成人传媒免费观看 | 欧美一区二区三区免费观看 | 欧美xxxx性xxxxx高清 | 亚洲精品网页 | 久久人人爽爽 | 日韩最新在线 | 国产精品久久久久影视 | 超碰在线日韩 | 国产在线观看免费 | 九九视频一区 | 精品久久毛片 | 欧美怡红院 | 婷婷久月 | 国产精品原创在线 | 中文字幕日本电影 | 怡红院av久久久久久久 | 国产乱对白刺激视频在线观看女王 | 国产亚洲aⅴaaaaaa毛片 | 色婷av| 五月婷婷一区二区三区 | 91成人蝌蚪 | 日日操夜夜操狠狠操 | 国产视频69 | 欧美成人aa| 日本少妇久久久 | 九九爱免费视频在线观看 | 日韩免费电影 | 精品国产人成亚洲区 | 麻豆影音先锋 | av片子在线观看 | 成人免费视频网站 | 欧美aa级| 81精品国产乱码久久久久久 | 亚洲精品tv久久久久久久久久 | 在线观看色视频 | 久久久免费| 欧美久久电影 | 天天爽天天射 | 免费看的黄网站软件 | 欧美日韩高清在线观看 | 一二三区在线 | 国产精品久久99综合免费观看尤物 | 国产成人亚洲精品自产在线 | 99久久99视频 | 欧美国产亚洲精品久久久8v | 久久久久免费电影 | 在线观看久久久久久 | 色欲综合视频天天天 | 久久这里有精品 | 久久视频在线视频 | 成年人黄色大全 | 五月婷婷综合激情网 | 麻豆视频免费播放 | 久久天天操 | 在线看黄网站 | 人人爽人人看 | 日韩精品在线观看视频 | 久久精彩免费视频 | 岛国一区在线 | 黄色在线免费观看网址 | 五月激情综合婷婷 | 国产精品免费麻豆入口 | 99免费在线观看视频 | 91av视频在线观看免费 | 性色av一区二区三区在线观看 | 九九色综合 | 欧美一区二区三区特黄 | 日韩久久午夜一级啪啪 | 毛片播放网站 | 一级免费观看 | 99在线播放| 91福利免费 | 成人永久在线 | 免费黄色一区 | 美女福利视频网 | 夜夜躁天天躁很躁波 | 婷婷色网站 | 丁香色综合| 国产精品国产亚洲精品看不卡15 | 亚洲激情综合 | 五月天婷婷狠狠 | 国产一区在线精品 | 激情综合五月婷婷 | 91av在线不卡 | 精品久久久久免费极品大片 | 国产69久久精品成人看 | 亚洲视频,欧洲视频 | 在线播放精品一区二区三区 | 一区二区欧美在线观看 | av在线免费播放网站 | 中文字幕一区二区三区在线播放 | 国产亚洲成av人片在线观看桃 | 91中文视频| 精品久久久久久亚洲综合网站 | 91精品国产91 | 日韩在线视频在线观看 | 在线播放日韩av | 国产精品片| 免费视频黄 | 久久香蕉国产精品麻豆粉嫩av | 色狠狠婷婷 | 精品96久久久久久中文字幕无 | 成人v| 不卡的av片 | 欧美久草网 | 国产黄色观看 | 日韩在线观看小视频 | 欧美精品久久久 | 国产伦精品一区二区三区四区视频 | 日本公妇在线观看高清 | 色婷五月| 中文字幕av免费 | 91在线免费观看国产 | 成人久久国产 | 婷婷丁香色 | 免费欧美高清视频 | 精品国产伦一区二区三区观看体验 | 国产精品毛片完整版 | 97伊人网 | 久久97超碰 | 日韩av一区二区三区在线观看 | 欧美日韩性视频在线 | 日韩国产精品久久 | 色激情五月| 在线av资源| 狠狠综合网 | 天堂av在线网站 | 日韩精品视 | 亚州av一区| 中文字幕永久免费 | 97精品国自产拍在线观看 | 日韩在线精品一区 | 激情五月***国产精品 | 又爽又黄又无遮挡网站动态图 | 久草网在线视频 | 最新精品国产 | 精品欧美在线视频 | 色是在线视频 | 欧美日韩大片在线观看 | 日韩欧美一区二区三区视频 | 精品久久久久亚洲 | 国产涩图 | 欧美精彩视频在线观看 | 91热这里只有精品 | 蜜桃视频精品 | 国产精品久久久一区二区三区网站 | 国产精品免费久久久久久 | 亚洲免费国产 | 手机成人在线电影 | 日韩久久片 | 免费不卡中文字幕视频 | 亚洲欧洲xxxx | av网址在线播放 | 日韩免费视频一区二区 | av在线播放中文字幕 | av免费成人 | 国产三级久久久 | 日本九九视频 | 免费观看性生活大片 | 91在线日韩| 丁香花在线观看视频在线 | 成人免费观看视频网站 | 国产在线免费 | 久久久www成人免费毛片 | 中文字幕在线视频一区二区三区 | 国产精品欧美精品 | 91色九色 | 中国一级片免费看 | 中文字幕免费在线 | 激情丁香综合 | 中文字幕乱码在线播放 | 久久tv视频 | 日日夜夜精品视频 | 中文字幕在线不卡国产视频 | 黄色tv视频| 91人人干| 久久国产视频网站 | 久久激情五月激情 | 久久高清国产视频 | 国产精选在线观看 | 69视频国产| 天天操天天色综合 | 亚洲精选在线观看 | 一级黄毛片 | 青草草在线视频 | 久久综合婷婷 | 97超碰成人在线 | 亚洲jizzjizz日本少妇 | 99精品国产99久久久久久福利 | av中文字幕不卡 | 日韩av电影免费观看 | 日韩理论片中文字幕 | 日韩在线免费不卡 | 天天摸天天弄 | 久爱综合 | a级国产乱理论片在线观看 特级毛片在线观看 | 国产91探花 | 久久精品一区二区 | 精品国产一二三四区 | 日本精品久久久久久 | 国产一区二区免费在线观看 | 美女免费网视频 | 91精品人成在线观看 | h久久| 四虎影视成人永久免费观看视频 | 国产精品久久久久久久久久东京 | jizzjizzjizz亚洲| 亚洲国产日韩一区 | 五月天视频网 | 成人午夜免费福利 | 中日韩欧美精彩视频 | 九九热在线免费观看 | 91在线视频免费91 | 一区二区不卡 | 欧美日韩国产在线一区 | 在线а√天堂中文官网 | 久久久久免费精品视频 | 五月天,com| 丁香花中文在线免费观看 | 久久久久9999亚洲精品 | 伊人色综合久久天天网 | 欧美日韩国产在线精品 | 天天色天天干天天色 | 日韩网站中文字幕 | 热re99久久精品国产66热 | 国产不卡av在线播放 | 中文字幕人成人 | 大荫蒂欧美视频另类xxxx | 精品国产人成亚洲区 | 久草免费在线观看视频 | 9999亚洲| 国产精品久久久久久久久久久久午 | 国产一区欧美在线 | 亚洲精品久久久久58 | 天天射射天天 | 在线观看免费av片 | 天堂麻豆 | av黄色亚洲 | 免费在线成人 | 狠狠躁日日躁狂躁夜夜躁 | 国产精品免费久久久久影院仙踪林 | 91.精品高清在线观看 | 丁香资源影视免费观看 | 色综合中文综合网 | 亚洲在线资源 | 热久久免费视频精品 | 婷婷丁香七月 | 国产精品久久久久一区二区三区 | 黄色av高清 | 麻豆国产精品永久免费视频 | 欧美国产精品一区二区 | 欧美精品在线观看免费 | 日韩国产欧美在线视频 | 中文字幕在线观看免费观看 | 国产成人亚洲在线观看 | 亚洲视频在线播放 | 女人18片 | 欧美性生活免费看 | 亚洲婷婷在线视频 | 91成年人在线观看 | 91精品推荐 | 高清日韩一区二区 | 国产精品18久久久久vr手机版特色 | 91在线免费视频观看 | 丁香5月婷婷久久 | 高清视频一区 | 亚洲精品乱码久久久久久久久久 | 国产欧美在线一区 | 国产一区二区影院 | 婷婷精品国产欧美精品亚洲人人爽 | 成人av中文字幕 | 日本精品视频在线播放 | 一色屋精品视频在线观看 | 日本一区二区不卡高清 | 九九热只有这里有精品 | 欧美日韩大片在线观看 | 亚洲精品国产品国语在线 | 亚洲最大激情中文字幕 | 黄色天堂在线观看 | 狠狠地日 | 日韩欧美在线影院 | 在线观看中文字幕第一页 | 午夜视频色 | 久久久久观看 | 视频国产| 亚洲黄色免费电影 | 日韩动漫免费观看高清完整版在线观看 | 狠狠色丁香婷婷综合久小说久 | www.91av在线 | 国产精品久久久久久久电影 | 成人av免费电影 | 在线精品在线 | 久久免费试看 | 在线看日韩 | 日韩精品一区二区三区高清免费 | 天天摸天天操天天舔 | 九九免费观看全部免费视频 | 国产精品成人一区二区 | 国产亚洲精品久久久久久久久久 | 国产99re | 久久久久看片 | 欧美日韩中文国产一区发布 | 日韩精品在线免费观看 | 最新日韩电影 | 蜜桃视频日韩 | 国产一性一爱一乱一交 | 青青五月天 | 日韩免费中文 | 91视频免费视频 | 99久久精品免费一区 | 午夜精品一区二区三区在线播放 | 欧美日韩一区二区三区不卡 | 亚一亚二国产专区 | 国内精品久久久久影院男同志 | 亚洲天堂网在线观看视频 | 欧美一级视频在线观看 | 91自拍视频在线观看 | 免费视频资源 | 97免费视频在线 | 超碰伊人网 | 伊人激情综合 | 99精品国产亚洲 | 免费看一级黄色大全 | 亚洲五月综合 | 天天插狠狠插 | www.久久91| 人人草天天草 | 91精品一区二区三区久久久久久 | www久久九 | 99免费看片 | 欧美激情精品久久久久久免费印度 | 亚洲一区二区三区91 | 国产手机av在线 | 久久精品国亚洲 | 九九热在线视频免费观看 | 一本一道久久a久久综合蜜桃 | 国产99久久久国产精品免费看 | 黄色软件网站在线观看 | 狠狠干狠狠久久 | 日韩小视频 | 久久艹人人 | 日韩av成人在线观看 | 美女视频黄是免费的 | 激情综合网天天干 | 亚洲国产精品女人久久久 | 黄色三级免费观看 | 国产精品久久久久久久午夜片 | 亚洲激情综合 | 精品国自产在线观看 | 久久网页| 国产黄色特级片 | 五月婷婷综合在线观看 | 久久成视频 | 亚洲国产日韩一区 | 免费精品国产va自在自线 | 97在线精品视频 | 国偷自产视频一区二区久 | 91香蕉视频在线 | www.av小说| 五月天欧美精品 | 久久综合免费视频 | 香蕉视频在线免费看 | 天天色天天骑天天射 | 91精品视频在线观看免费 | 中文字幕二区三区 | 天天操夜夜操 | 欧美日韩一区二区三区不卡 | 日韩高清网站 | 狠狠色香婷婷久久亚洲精品 | 欧美日一级片 | 综合久久久 | 久久激情小视频 | 久久久www成人免费毛片 | 欧美性黄网官网 | 亚洲国产成人久久综合 | 激情电影在线观看 | 在线免费观看黄 | 精品国产一区二区三区久久久蜜月 | 久久超级碰| 欧美日韩在线免费观看 | 免费国产在线观看 | 午夜精品视频一区二区三区在线看 | 狠狠干五月天 | 精品99久久 | 久久精品国产第一区二区三区 | 人人爽人人爽 | 国产一区二区精品久久 | 久久久这里有精品 | 久久久久看片 | 亚洲va在线va天堂va偷拍 | 91aaa在线观看 | 欧美日韩免费一区二区三区 | 日韩在线观看视频一区二区三区 | 亚洲欧美日韩国产一区二区三区 | 日本中文一区二区 | 激情婷婷 | 极品美女被弄高潮视频网站 | 国产在线观看不卡 | 欧美成年人在线视频 | 久久久久久久影院 | 超碰公开在线观看 | 一区二区三区中文字幕在线 | 日韩丝袜 | 99视频一区 | 久久精品一级片 | 久久久午夜精品福利内容 | 欧美另类tv | 久久成人精品电影 | 开心色插 | 香蕉视频最新网址 | 久久久久久久国产精品影院 | 久久久久亚洲精品男人的天堂 | 久久久久久久久久久久久久免费看 | 外国av网| 国产精品美女网站 | 国产不卡毛片 | 91自拍成人 | 国产成人精品a | 久久成人毛片 | 久久99亚洲网美利坚合众国 | 国产精品久久久久一区二区三区 | 免费看三片 | 日韩在线大片 | 日本精品视频在线观看 | 国产精品淫片 | a级国产乱理伦片在线播放 久久久久国产精品一区 | 国产精品精品 | 免费观看特级毛片 | 激情综合色综合久久 | 天天操操| 97超碰人人爱 | 人人干干人人 | 日韩大片在线 | 91丨九色丨国产在线观看 | 国产成人精品国内自产拍免费看 | 成人h视频在线播放 | 色婷婷亚洲综合 | 亚洲美女在线国产 | 成人午夜在线观看 | 人人插人人做 | 亚洲激情婷婷 | 91高清免费观看 | 精品亚洲免费 | 97激情影院 | 国产aaa免费视频 | 精品嫩模福利一区二区蜜臀 | 欧美性春潮 | 久久99久久久久久 | 91在线91拍拍在线91 | 中文资源在线播放 | 久久伊人国产精品 | a√天堂中文在线 | 久久久国产电影 | 久久一区二区三区超碰国产精品 | 久久99久久99精品免观看粉嫩 | 免费看一级一片 | 日韩一区精品 | 91丨九色丨91啦蝌蚪老版 | 91传媒在线观看 | 成人资源网 | 色播激情五月 | 视频在线99 | 最近2019好看的中文字幕免费 | 狠狠色丁香婷综合久久 | 韩日av一区二区 | 国产成人一区在线 | 在线观看国产91 | av成人在线网站 | 日本中文不卡 | 91视频3p | 五月婷婷黄色 | 国产中文字幕一区 | 成年人看片网站 | 色av男人的天堂免费在线 | 91在线观看黄 | 久久刺激视频 | 欧美另类交在线观看 | 美女网站黄在线观看 | 欧美亚洲精品一区 | 六月激情丁香 | 国产区av在线 | 西西4444www大胆无视频 | 91av免费观看 | 狠狠狠色丁香婷婷综合激情 | 欧美 亚洲 另类 激情 另类 | 狠狠狠狠狠狠天天爱 | 免费男女羞羞的视频网站中文字幕 | 欧美三级在线播放 | 国产视频一区精品 | 成人毛片在线观看视频 | 超碰在线97免费 | 黄色大全视频 | 中国成人一区 | 在线午夜| 日韩国产欧美在线播放 | 99久久99久久精品国产片 | 日日日日 | 日韩电影一区二区在线观看 | 免费av观看网站 | 日韩精品久久久免费观看夜色 | 国产午夜精品一区二区三区欧美 | 日韩a级黄色 | 色99在线 | 色综合激情久久 | av黄在线播放 | 午夜久久精品 | 日韩精品视频在线免费观看 | 91精品在线看 | 91一区二区在线 | 日韩欧美精品免费 | 国产精品18久久久久vr手机版特色 | 久久九九免费视频 | 久久久久国产成人免费精品免费 | 中文字幕电影网 | 久久精品视频免费 | 在线播放日韩av | 国产一级片不卡 | 国产美女免费看 | 激情影音 | 日韩免费在线播放 | 天干啦夜天干天干在线线 | 久久精品视频国产 | 婷婷www| 国产精品夜夜夜一区二区三区尤 | av网站在线观看播放 | 日韩一区二区三区在线看 | 中文字幕在线观看视频一区二区三区 | 国产三级在线播放 | 四虎影视成人精品国库在线观看 | 97人人爽人人 | 天天操夜夜叫 | 人人干在线 | 五月天伊人| 精品久久国产一区 | 麻豆91精品| 人人看人人| 亚洲97在线 | 人人爽人人爽人人爽学生一级 | 91精品啪啪| 人人搞人人爽 | 中文字幕国内精品 | 97超碰人人澡 | 国产精品久久婷婷六月丁香 | 99久久激情| 伊人久久国产 | 久久综合九色综合欧美狠狠 | 久久丁香 | 韩国一区二区三区视频 | 波多野结衣在线播放视频 | 久久久资源网 | 国产日产精品久久久久快鸭 | 国产精品综合久久久 | 五月天综合色 | 日韩在线免费 | 91麻豆精品国产自产在线游戏 | 色播五月激情五月 | 婷婷在线网站 | freejavvideo日本免费 | 日本三级吹潮在线 | 午夜黄网 | 亚洲精品一区二区三区新线路 | 一区二区三区在线免费观看视频 | 热久久这里只有精品 | 9色在线视频 | 97成人精品 | 久久久在线 | 高潮毛片无遮挡高清免费 | 欧美黄在线 | 欧美-第1页-屁屁影院 | 在线观看麻豆av | 国产小视频91 | 精品产品国产在线不卡 | 中文在线字幕免费观看 | 国产一线天在线观看 | 超碰999| 天天躁日日躁狠狠躁av麻豆 | 欧美极品一区二区三区 | 国产永久免费 | 麻豆av一区二区三区在线观看 | 精品国产一区二区三区日日嗨 | 91av视频在线播放 | 日韩久久午夜一级啪啪 | 亚洲欧美日韩国产精品一区午夜 | av线上看| 精品亚洲免费视频 | 毛片网站免费 | 中文字幕在线高清 | 国色天香永久免费 | 国产精品免费久久久 | 天天色欧美 | 国产精品国产三级国产aⅴ9色 | 在线视频中文字幕一区 | 蜜臀91丨九色丨蝌蚪老版 | 69av视频在线| 久久国产精品免费一区 | 国产中文字幕一区二区三区 | 久热电影| 国产伦理久久 | 久久久久日本精品一区二区三区 | 国产免费不卡av | 最近能播放的中文字幕 | 日日插日日干 | 中文字幕在线免费观看视频 | 麻豆观看 | 国产高清成人 | 手机av在线免费观看 | 国产免费一区二区三区最新 | 国产高清免费视频 | 婷婷六月丁 | 超碰在线亚洲 | 人人爽久久久噜噜噜电影 | 久99久在线视频 | 97超碰成人 | 999国产在线 | 色橹橹欧美在线观看视频高清 | 国产精品久久久久久久久免费看 | 午夜精品久久久99热福利 | 精品久久久久久一区二区里番 | 粉嫩av一区二区三区四区五区 | 日韩久久久久久久久 | 欧美性爽爽 | 狠狠狠色 | 久久精品人人做人人综合老师 | 亚洲成人影音 | 视频二区在线 | 99久热在线精品视频 | 亚洲人人爱 | 99re6热在线精品视频 | 99视频+国产日韩欧美 | 成人va视频 | 黄色av大片 | 手机成人在线电影 | 久草视频精品 | 在线午夜电影神马影院 | 成年人国产在线观看 | 制服丝袜一区二区 | 久久私人影院 | 91免费高清观看 | 国产成人精品av在线观 | 夜夜躁日日躁狠狠久久88av | 亚洲精品一区二区18漫画 | 国产一级一片免费播放放a 一区二区三区国产欧美 | 午夜精品视频福利 | 日韩高清片 | 九色91视频 | 天天色天天射天天综合网 | 亚洲综合激情五月 | 在线免费观看不卡av | 这里有精品在线视频 | 国产 成人 久久 | 日韩精品一区二区在线观看 | 亚洲综合欧美日韩狠狠色 | 亚洲天堂激情 | 国产三级在线播放 | 欧美激情综合五月色丁香小说 | 91精品成人| 亚洲黄在线观看 | 久久成人免费视频 | 91精品成人 | 精品一区二区av | 免费裸体视频网 | 久久天天躁夜夜躁狠狠躁2022 | www.日韩免费 | 国产视频在线观看一区二区 | 国产成人精品久 | 成人福利在线 | 五月花丁香婷婷 | 98福利在线 | 中文字幕在线观看一区二区三区 | 色婷婷在线观看视频 | 亚洲91精品在线观看 | 狠狠色丁香婷婷综合久小说久 | 久久婷婷国产色一区二区三区 | 国产小视频在线播放 | 久久精品成人热国产成 | 久久午夜视频 | 成人黄色免费在线观看 | 九九精品视频在线观看 | 成人一区二区三区中文字幕 | 91在线小视频 | 亚洲一级电影 | 99色免费视频 | 婷婷色伊人 | 免费观看版 | 操操操日日 | 一级成人免费视频 | 99激情网 | 在线视频手机国产 | 国产亚洲va综合人人澡精品 | 51久久成人国产精品麻豆 | 超碰97国产精品人人cao | 激情欧美一区二区免费视频 | 国产香蕉久久精品综合网 | 国产高清一区二区 | av黄色一级片 | 日日躁夜夜躁aaaaxxxx | 国产精品久久久久久久久久免费 | 色91在线| 欧美一级高清片 | 91久久精品日日躁夜夜躁国产 | 欧美精品久久久久久久久老牛影院 | 免费在线精品视频 | 99re久久资源最新地址 | 日本一区二区三区视频在线播放 | 日韩欧美在线免费 | 综合色在线 | 五月激情姐姐 | 欧美精品在线观看 | 中文字幕精 | 99久久精品午夜一区二区小说 | 亚洲女欲精品久久久久久久18 | 九九九九九九精品 | 日韩最新在线 | 国产福利一区二区三区视频 | 色黄视频免费观看 | 国产成人黄色网址 | 欧美日韩国语 | 99久久精品免费看国产一区二区三区 | 999久久久免费精品国产 | 免费h精品视频在线播放 | 国产精品视频免费 | 国产露脸91国语对白 | 99热精品在线 | 精品亚洲欧美无人区乱码 | 国内亚洲精品 | 亚洲妇女av | 久久人人97超碰国产公开结果 | 免费看网站在线 | 激情电影在线观看 | 国产精品久久久久永久免费 | 亚洲九九九在线观看 | 欧美色久 | 日韩专区 在线 | 欧美精品久久久久久久久久白贞 | 日本精品一区二区 | av直接看 | 国产成人高清av | 在线观看激情av | 婷婷色在线资源 | 亚洲香蕉视频 | 亚洲草视频 | 亚洲国产精品电影在线观看 | 欧美日韩亚洲在线观看 | 国产成在线观看免费视频 | 99精品欧美一区二区三区 | 国产成年人av | 友田真希x88av | 欧美日韩视频一区二区三区 | 国产精美视频 | 国产黄色免费看 | 国产视频一区二区三区在线 | 99久热在线精品视频成人一区 | 久久久久亚洲精品中文字幕 | 国产成人亚洲在线观看 | 成人精品国产 | 国产精品成人国产乱一区 | 婷婷久久婷婷 | 91精品国产高清自在线观看 | 中文字幕中文字幕在线中文字幕三区 | 激情图片qvod | 免费看黄色大全 | 国产精品毛片久久久久久久 | 夜夜骑首页| 精品中文字幕视频 | 在线看片中文字幕 | 一级黄色电影网站 | 国产一区二区免费在线观看 | 香蕉日日 | 久久草精品 | 日韩精品视频免费在线观看 | 国产女教师精品久久av | 国产麻豆视频免费观看 | 五月婷婷六月综合 | 亚洲一区精品二人人爽久久 | 国产黄色片久久久 | 国产精品va在线播放 | 久久人人添人人爽添人人88v | 最近更新的中文字幕 | 久久久久久久久久久久久久电影 | 2023年中文无字幕文字 | 成人一级电影在线观看 | 久久久www成人免费毛片麻豆 | 久久精品国产精品亚洲 | 肉色欧美久久久久久久免费看 | 久久草在线免费 | 色偷偷97 | 久久99亚洲精品久久 | 久久精品亚洲精品国产欧美 | 在线中文字幕观看 | 日韩一级理论片 | 成人在线观看网址 | 欧美一级电影在线观看 | 精品在线免费观看 | 国产亚洲亚洲 | 久久亚洲精品国产亚洲老地址 | 精品久久久久久久久亚洲 | 欧美在线不卡一区 | 亚洲精品一区二区三区四区高清 | 免费一级黄色 | 欧美整片sss| 日韩免费在线视频观看 | 一级国产视频 | 激情小说网站亚洲综合网 | 午夜三级毛片 |