日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

数据结构之线索二叉树

發布時間:2025/3/15 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 数据结构之线索二叉树 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

線索二叉樹

  • 思維導圖:
  • 線索二叉數的引入:
  • 線索二叉樹:
    • 前序遍歷的線索二叉樹:
    • 中序遍歷的線索二叉樹(常):
    • 后序遍歷的線索二叉樹:
  • 線索二叉樹的節點結構:
  • 中序線索二叉樹代碼實現
    • 中序線索二叉樹的構造:
    • 中序線索二叉樹的遍歷以及找節點p的后序節點:
    • 中序線索二叉樹的逆遍歷以及找節點p的前驅節點:
  • 先序線索二叉樹代碼實現
    • 先序線索二叉樹的構造:
    • 先序線索二叉樹的遍歷以及找節點p的后序節點:
    • 先序線索二叉樹的逆遍歷以及找節點p的前驅節點:
  • 后序線索二叉樹代碼實現
    • 后序線索二叉樹的構造:
    • 后序線索二叉樹的遍歷以及找節點p的后序節點:
    • 后序線索二叉樹的遍歷以及找節點p的前驅節點:
  • 總結:

思維導圖:

線索二叉數的引入:

先來看這樣幾個問題:
1、普通二叉樹只有指向孩子節點的指針而沒有指向雙親節點的指針,這樣就會產生一個問題,無法方便快速的找到某一節點的雙親節點
2、當我們不知道根節點的指針,而是知道某一節點(非根節點)指針,就無法對二叉樹進行遍歷

我們知道,用鏈式存儲二叉樹時,會產生n+1個空指針,我們是否可以利用這些空指針而很方便的實現上述的兩種操作呢?
為此,我們引入線索二叉樹的概念。

線索二叉樹:

在實現一顆二叉樹時,會產生空指針,個數為n+1個,若節點無左子樹,將指針指向前驅節點;若無右子樹,將指針指向后繼節點,從而實現線索化,將加上線索的二叉樹稱為線索二叉樹。即:
1、若無左子樹,將指針指向前驅節點
2、若無右子樹,將指針指向后繼節點

前序遍歷的線索二叉樹:

ps: 由遍歷序列得到圖

中序遍歷的線索二叉樹(常):

后序遍歷的線索二叉樹:

線索二叉樹的節點結構:

例如:

typedef struct ThreadNode{int data;struct ThreadNode *lchild,*rchild;int ltag,rtag; }ThreadNode , *ThreadTree;

中序線索二叉樹代碼實現

中序線索二叉樹的構造:

原理:

找前驅節點:
若左指針為線索,則其指向節點為前驅節點
若左指針為左孩子,則其左子樹的最右側節點為前驅節點
找后繼節點:
若右指針為線索,則其指向節點為后繼節點
若右指針為右孩子,則其右子樹的最左側節點為后繼節點

代碼實現:

void InThread(ThreadTree &p){if(p != NULL){InThread(p->lchild);visit(T);InThread(p->rchild);} } void visit(ThreadNode *p){if(p->lchild == NULL){p->lchild = pre;p->ltag = 1;}if(pre != NULL && pre->rchild == NULL){pre->rchild = p;pre->rtag = 1;}pre = p; }void CreateInThread(ThreadTree T){ThreadTree pre = NULL;if(T != NULL){InThread(T,pre);if(pre->rchild == NULL)pre->rtag = 1;} }

中序線索二叉樹的遍歷以及找節點p的后序節點:

1、找到以p為根的子樹中,第一個被中序遍歷的節點
2、在中序線索二叉樹中找到節點p的后繼節點
3、實現對二叉樹的中序遍歷

//找到以p為根的子樹中,第一個被中序遍歷的節點 ThreadNode *Fristnode(ThreadNode *p){//循環找到最左下節點,不一定是葉節點while(p->ltag == 0)p = p->lchild;return p; } //在中序線索二叉樹中找到節點p的后繼節點 ThreadNode *Nextnode(ThreadNode *p){if(p->rtag == 0)return Firstnode(p->rchild);elsereturn p->rchild; } //上面兩個函數實現了找到指定節點p的中序后繼,下面的函數實現對二叉樹的中序遍歷 //利用線索實現的惡非遞歸算法,空間復雜的o(1) void Inorder(ThreadNode *T){for(ThreadNode *p = Firstnode(T);p != NULL;p = Nextnode(p))visit(p); }

中序線索二叉樹的逆遍歷以及找節點p的前驅節點:

//找到以p為根的子樹中,最后一個被中序遍歷的節點 ThreadNode *Lastnode(ThreadNode *p){//循環找到最左下節點,不一定是葉節點while(p->rtag == 0)p = p->rchild;return p; } //在中序線索二叉樹中找到節點p的前驅節點 ThreadNode *Prenode(ThreadNode *p){if(p->ltag == 0)return Lasttnode(p->lchild);elsereturn p->lchild; } //上面兩個函數實現了找到指定節點p的中序后繼,下面的函數實現對二叉樹的逆中序遍歷 //利用線索實現的惡非遞歸算法,空間復雜的o(1) void Revorder(ThreadNode *T){for(ThreadNode *p = Lastnode(T);p != NULL;p = Prenode(p))visit(p); }

先序線索二叉樹代碼實現

先序線索二叉樹的構造:

代碼實現:

void PreThread(ThreadTree &p){if(p != NULL){visit(p);//當處理完p節點后會訪問p->lchild,但是經過visit(P)后p->lchild就會指向p的前驅節點,所以要對其進行判斷if(T->ltag == 0) //lchild不是前驅線索 PreThread(p->lchild);PreThread(p->rchild);} } void visit(ThreadNode *p){if(p->lchild == NULL){p->lchild = pre;p->ltag = 1;}if(pre != NULL && pre->rchild == NULL){pre->rchild = p;pre->rtag = 1;}pre = p; }void CreateInThread(ThreadTree T){ThreadTree pre = NULL;if(T != NULL){InThread(T,pre);if(pre->rchild == NULL)pre->rtag = 1;} }

先序線索二叉樹的遍歷以及找節點p的后序節點:

先序線索二叉樹的逆遍歷以及找節點p的前驅節點:

ps:在只有指向孩子節點的節點結構中無法找到前驅
解決:增加一個指向雙親節點的指針

后序線索二叉樹代碼實現

后序線索二叉樹的構造:

代碼實現:

void PostThread(ThreadTree &p){if(p != NULL){PostThread(p->lchild);PostThread(p->rchild);visit(T);} } void visit(ThreadNode *p){if(p->lchild == NULL){p->lchild = pre;p->ltag = 1;}if(pre != NULL && pre->rchild == NULL){pre->rchild = p;pre->rtag = 1;}pre = p; }void CreateInThread(ThreadTree T){ThreadTree pre = NULL;if(T != NULL){InThread(T,pre);if(pre->rchild == NULL)pre->rtag = 1;} }

后序線索二叉樹的遍歷以及找節點p的后序節點:

后序線索二叉樹的遍歷以及找節點p的前驅節點:

ps:在只有指向孩子節點的節點結構中無法找到前驅
解決:增加一個指向雙親節點的指針

總結:

總結

以上是生活随笔為你收集整理的数据结构之线索二叉树的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。