欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C語言數(shù)據(jù)結(jié)構(gòu)之線索二叉樹及其遍歷

 更新時間:2017年08月14日 14:35:55   作者:_Xu_shuai  
這篇文章主要介紹了C語言數(shù)據(jù)結(jié)構(gòu)之線索二叉樹及其遍歷的相關(guān)資料,為了加快查找節(jié)點(diǎn)的前驅(qū)和后繼。對二叉樹的線索化就是對二叉樹進(jìn)行一次遍歷,在遍歷的過程中檢測節(jié)點(diǎn)的左右指針是否為空,如果是空,則將他們改為指向前驅(qū)和后繼節(jié)點(diǎn)的線索,需要的朋友可以參考下

C語言數(shù)據(jù)結(jié)構(gòu)之線索二叉樹及其遍歷

遍歷二叉樹就是以一定的規(guī)則將二叉樹中的節(jié)點(diǎn)排列成一個線性序列,從而得到二叉樹節(jié)點(diǎn)的各種遍歷序列,其實質(zhì)是:對一個非線性的結(jié)構(gòu)進(jìn)行線性化。使得在這個訪問序列中每一個節(jié)點(diǎn)都有一個直接前驅(qū)和直接后繼。傳統(tǒng)的鏈?zhǔn)浇Y(jié)構(gòu)只能體現(xiàn)一種父子關(guān)系,¥不能直接得到節(jié)點(diǎn)在遍歷中的前驅(qū)和后繼¥,而我們知道二叉鏈表表示的二叉樹中有大量的空指針,當(dāng)使用這些空的指針存放指向節(jié)點(diǎn)的前驅(qū)和后繼的指針時,則可以更加方便的運(yùn)用二叉樹的某些操作。引入線索二叉樹的目的是: 為了加快查找節(jié)點(diǎn)的前驅(qū)和后繼。對二叉樹的線索化就是對二叉樹進(jìn)行一次遍歷,在遍歷的過程中檢測節(jié)點(diǎn)的左右指針是否為空,如果是空,則將他們改為指向前驅(qū)和后繼節(jié)點(diǎn)的線索。

如果二叉樹沒有被線索化,也可以使用<<非遞歸>>的代碼進(jìn)行遍歷的,但是那就需要借助于<<棧>>,但是在線索化之后,對線索化的二叉樹進(jìn)行<<非遞歸>>的遍歷就不再需要棧的輔助。

實現(xiàn)代碼:

#include<stdio.h> 
#include<stdlib.h> 
 
#define OK 1 
#define ERROR 0 
 
typedef char ElemType; 
typedef int Status; 
 
/* 定義枚舉類型,其值只能是Link和Thread 
 * Link表示的該指針指示的是孩子 
 * Thread表示的是還指針指示的是前驅(qū)或者是后綴 
 * */ 
typedef enum { 
  Link,Thread 
}PointerTag; 
 
typedef struct ThrBiTrNode{ 
  ElemType data; 
  struct ThrBiTrNode *lchild, *rchild; 
  PointerTag rTag, lTag; 
}ThrBiTrNode, *ThrBiTree; 
 
ThrBiTree Pre; 
 
Status InitThreadBinaryTree(ThrBiTree* T){ 
  *T = NULL; 
  return OK; 
} 
//先序建立二叉樹,lchild和rchild都是指示做孩子和右孩子,所以lTag和rTag為Link 
Status ThreadBinaryTree_PreOrderInput(ThrBiTree* T){ 
  ElemType c; 
  scanf("%c", &c); 
  if( ' ' == c ){ 
    *T = NULL; 
  } 
  else{ 
    *T = (ThrBiTrNode*)malloc(sizeof(ThrBiTrNode)); 
    if( !*T ){ 
      return ERROR; 
    } 
    (*T)->data = c; 
    (*T)->lTag = Link; 
    (*T)->rTag = Link; 
    ThreadBinaryTree_PreOrderInput(&(*T)->lchild); 
    ThreadBinaryTree_PreOrderInput(&(*T)->rchild); 
  } 
  return OK; 
} 
//<<中序遍歷>>對二叉樹進(jìn)行<<線索化>>,但是沒有提供Pre的初始值,只是給出了 
//中間的過程,遞歸的思想和思考方式。 
//1 線索化左子樹 
//2 對雙親節(jié)點(diǎn)處理//遞歸中的base 
//3 線索化右子樹 
Status InOrderThread(ThrBiTree T){ 
  if( T != NULL ){ 
    InOrderThread(T->lchild);    //線索化左子樹 
     
    //對雙親節(jié)點(diǎn)進(jìn)行線索化處理 
    if( T->lchild == NULL ){ //如果左孩子為空,則將lchild作為索引 
            //Pre指向剛剛訪問的節(jié)點(diǎn) 
      T->lTag = Thread; 
      T->lchild = Pre; 
    } 
    if( Pre->rchild == NULL ){  //直到現(xiàn)在才知道Pre的后綴是T,所以 
            //要對Pre進(jìn)行設(shè)置,如果Pre的rchild為空 
            //則將Pre的rchild設(shè)置為后綴,指向T 
      Pre->rTag = Thread; 
      Pre->rchild = T; 
    } 
 
    Pre = T;      //標(biāo)記當(dāng)前的節(jié)點(diǎn)稱為剛剛訪問過的節(jié)點(diǎn) 
            //Pre最后會指向樹的中序遍歷的最后的 
            //一個節(jié)點(diǎn) 
 
    InOrderThread(T->rchild);  //線索化右子樹 
  } 
  return OK; 
} 
//創(chuàng)建中序線索二叉樹,為上個函數(shù)提供Pre 
Status CreateInOrderThreadBinaryTree(ThrBiTree T, ThrBiTree* headOfTree){ 
  *headOfTree = (ThrBiTrNode*)malloc(sizeof(struct ThrBiTrNode)); 
  if( !headOfTree ) 
    return ERROR; 
  (*headOfTree)->lTag = Link;   //將要指向T 
  (*headOfTree)->rTag = Thread;    //將頭節(jié)點(diǎn)的rchild用于索引 
  (*headOfTree)->rchild = *headOfTree;   //指向自身 
  if( T == NULL ){ 
    (*headOfTree)->lchild = *headOfTree; //若T為空樹,則頭節(jié)點(diǎn)的lchild 
              //指向自身 
  } 
  else{ 
    (*headOfTree)->lchild = T; 
    Pre = *headOfTree;     //賦值了全局變量Pre 
    InOrderThread(T);        //中序線索化 
    //printf("\n%c\n",Pre->data); 
            //執(zhí)行完InOrderThread之后Pre指向最后 
            //一個節(jié)點(diǎn) 
    Pre->rTag = Thread;    
    Pre->rchild = *headOfTree; 
    //(*headOfTree)->rchild = Pre; 
  } 
  return OK; 
} 
//對中序線索化后的線索二叉樹使用<<非遞歸>>的代碼進(jìn)行中序遍歷 
//并且原來的遞歸形式的代碼在這里是不再可以進(jìn)行遍歷。 
//  如果二叉樹沒有被線索化,也可以使用<<非遞歸>>的代碼進(jìn)行遍 
//  歷的,但是那就需要借助于<<棧>>,但是在線索化之后,對線索 
//  化的二叉樹進(jìn)行<<非遞歸>>的遍歷就不再需要棧的輔助。 
Status visit(ElemType c){ 
  printf("%c ", c); 
  return OK; 
} 
Status InOrderTeaverse_NoRecursion(ThrBiTree T, ThrBiTree headOfTree){ 
//headOfTree是T的頭節(jié)點(diǎn)的指針,headOfTree->lchild = T; 
  while( T != headOfTree ){ 
    while( T->lTag == Link ){  //找到樹(子樹)的最左節(jié)點(diǎn) 
            //用while接替if// 
            //用if理解while// 
      T = T->lchild; 
    }         
    visit(T->data); 
 
    while( T->rTag == Thread && T->rchild != headOfTree){ 
            //這個while和下面的T=T->rchild 
            //可用ifelse語句理解。 
            //if(rchild是線索 && 不是最后一個節(jié)點(diǎn))  
            //else(rchild不是線索)-->走到右孩子 
            //也就是代碼T=T->rchild 
      T = T->rchild; 
      visit(T->data); 
    } 
    T = T->rchild; 
  } 
  return OK; 
} 
//求中序線索二叉樹中中序序列下的第一個節(jié)點(diǎn) 
ThrBiTrNode* SeekFirstNode_InOrderThrBiTree(ThrBiTree T){ 
  if( T != NULL ){ 
    while( T->lTag == Link ){ 
      T = T->lchild; 
    } 
    return T; 
  } 
  return ERROR; 
} 
//求中序線索二叉樹中節(jié)點(diǎn)P在中序序列下的下一個節(jié)點(diǎn) 
ThrBiTrNode* GetNextNode(ThrBiTrNode* CurrentP){ 
  if( CurrentP->rTag == Link ){  //有右孩子的時候,那么下一個就是以 
          //右孩子為root的樹的最左下角元素。 
          //即seekFirstNode的返回值。 
    return SeekFirstNode_InOrderThrBiTree(CurrentP->rchild); 
  } 
  else{        //沒有右孩子,則rchild指向后綴 
    return CurrentP->rchild; 
  } 
} 
//使用上面兩個函數(shù),SeekFirstNode_InOrderThrBiTree和GetNextNode來實現(xiàn)對 
//中序先做二叉樹的遍歷 
Status InOrderTraverse_NoRecursion_Method(ThrBiTree T, ThrBiTree head){ 
  for( T = SeekFirstNode_InOrderThrBiTree(T) ; T != head ; T = GetNextNode(T) ) 
    visit(T->data); 
  return OK; 
} 
 
//test 
/* ShowThread函數(shù)的目的是想在將T中序線索化之后,使用函數(shù)InOrderTraverse 
 * 函數(shù)中序遍歷,輸出一下節(jié)點(diǎn)中的信息以檢驗線索化,但是失敗。原因是:在 
 * 線索化之后,空指針域都被應(yīng)用,所有InOrderTraverse函數(shù)中的if( T )是滿 
 * 足不了的,故失敗。 
Status ShowThread(ThrBiTree C){ 
  printf("%d %d %d %d\n",(C->lchild)->data,(C->rchild)->data,C->lTag,C->rTag); 
  printf("%d %d\n",C->lTag,C->rTag); 
  return OK; 
 * */ 
 
//中序遍歷二叉樹 
Status InOrderTraverse(ThrBiTree T){ 
  if( T ){ 
    InOrderTraverse(T->lchild); 
    visit(T->data); 
    InOrderTraverse(T->rchild); 
  } 
  return OK; 
} 
int main(){ 
  ThrBiTree T,R,Head = NULL; 
  InitThreadBinaryTree(&T); 
 
  printf("Please Input Binary Tree By PreOrder\n  "); 
  ThreadBinaryTree_PreOrderInput(&T); 
 
  printf("  InOrder Traverse before Thread with Recursion\n"); 
  InOrderTraverse(T); 
  printf("\n"); 
 
  CreateInOrderThreadBinaryTree(T,&Head); 
  printf("  InOrder Traverse after Thread with no-Recursion\n"); 
  InOrderTeaverse_NoRecursion(T,Head); 
  printf("\n"); 
 
  printf("The root is %c \n", T->data);  //不能夠通過指針形參的值改變指針實參的值 
            //或者說,對指針形參的改變不會作用到指針 
            //實參上。 
 
  ThrBiTrNode *firstOfInOrder = NULL,*secondOfInOrder = NULL; 
  if( SeekFirstNode_InOrderThrBiTree(T) != ERROR ){ 
    firstOfInOrder = SeekFirstNode_InOrderThrBiTree(T); 
    printf("the value of First Node of InOrderThreadBinaryTree is %c\n", firstOfInOrder->data); 
  } 
  secondOfInOrder = GetNextNode(firstOfInOrder); 
  printf("the value of Node after D is: %c \n", secondOfInOrder->data); 
  secondOfInOrder = GetNextNode(secondOfInOrder); 
  printf("the value of Node after B is: %c \n", secondOfInOrder->data); 
  secondOfInOrder = GetNextNode(secondOfInOrder); 
  printf("the value of Node after E is: %c \n", secondOfInOrder->data); 
  secondOfInOrder = GetNextNode(secondOfInOrder); 
  printf("the value of Node after A is: %c \n", secondOfInOrder->data); 
  secondOfInOrder = GetNextNode(secondOfInOrder); 
  printf("the value of Node after C is: %c \n", secondOfInOrder->data); 
  secondOfInOrder = GetNextNode(secondOfInOrder); 
  printf("the value of Node after G is: %c \n", secondOfInOrder->data); 
  secondOfInOrder = GetNextNode(secondOfInOrder); 
  printf("the value of Node after root is: %c \n", secondOfInOrder->data); 
 
  printf("  InOrder Traverse after Thread with no-Recursion Method_2\n"); 
  InOrderTraverse_NoRecursion_Method(T,Head); 
 
  return 0; 
} 


以上就是線索二叉樹及遍歷的實例,如有疑問請留言或者到本站社區(qū)交流討論,感謝閱讀,希望能幫助到大家,謝謝大家對本站的支持!

相關(guān)文章

  • 純C語言實現(xiàn)火車售票系統(tǒng)

    純C語言實現(xiàn)火車售票系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了純C語言實現(xiàn)火車售票系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-12-12
  • C 語言中strstr函數(shù)實例詳解

    C 語言中strstr函數(shù)實例詳解

    這篇文章主要介紹了C 語言中strstr函數(shù)實例詳解的相關(guān)資料,需要的朋友可以參考下
    2017-07-07
  • C++容器map和pair對組實例詳解

    C++容器map和pair對組實例詳解

    pair?是一種模板類,允許將兩個不同類型的值組合在一起,它由兩個數(shù)據(jù)成員first和second組成,分別用來保存這兩個值,這篇文章主要介紹了C++容器——map和pair對組,需要的朋友可以參考下
    2024-05-05
  • 淺析c#中WebBrowser控件的使用方法

    淺析c#中WebBrowser控件的使用方法

    以下是對c#中WebBrowser控件的使用方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-07-07
  • C++實現(xiàn)在文本中找出某個單詞的位置信息

    C++實現(xiàn)在文本中找出某個單詞的位置信息

    本文給大家分享的是使用C++實現(xiàn)在文本中找出某個單詞的位置信息,就是給出此單詞所在的行和列,有需要的小伙伴可以參考下。
    2016-02-02
  • VC實現(xiàn)五子棋游戲的一個算法示例

    VC實現(xiàn)五子棋游戲的一個算法示例

    這篇文章主要介紹了VC實現(xiàn)五子棋游戲的一個算法示例,對于學(xué)習(xí)數(shù)據(jù)結(jié)構(gòu)與算法的朋友有一定的借鑒價值,需要的朋友可以參考下
    2014-08-08
  • 基于C++實現(xiàn)五子棋小游戲

    基于C++實現(xiàn)五子棋小游戲

    這篇文章主要為大家詳細(xì)介紹了基于C++實現(xiàn)五子棋小游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-05-05
  • C++11?constexpr使用詳解

    C++11?constexpr使用詳解

    constexpr是一種比const?更嚴(yán)格的束縛,?它修飾的表達(dá)式本身在編譯期間可知,?并且編譯器會盡可能的?evaluate?at?compile?time,本文重點(diǎn)給大家介紹C++11?constexpr使用,需要的朋友可以參考下
    2021-12-12
  • Qt使用SQLite數(shù)據(jù)庫實現(xiàn)數(shù)據(jù)增刪改查

    Qt使用SQLite數(shù)據(jù)庫實現(xiàn)數(shù)據(jù)增刪改查

    這篇文章主要為大家詳細(xì)介紹了Qt如何使用SQLite數(shù)據(jù)庫實現(xiàn)數(shù)據(jù)增刪改查功能,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起了解一下
    2023-06-06
  • C++中用棧來判斷括號字符串匹配問題的實現(xiàn)方法

    C++中用棧來判斷括號字符串匹配問題的實現(xiàn)方法

    這篇文章主要介紹了C++中用棧來判斷括號字符串匹配問題的實現(xiàn)方法,是一個比較實用的算法技巧,包含了關(guān)于棧的基本操作,需要的朋友可以參考下
    2014-08-08

最新評論