線索二叉樹

二叉樹在連接存儲表示中,空鏈的數目是大於非空鏈的數目,即在2n個空鏈中,有n+1個是空鏈,如果利用這些空鏈來指向二叉樹其他結點的指針,這結點稱爲線索,具體建立線索樹過程:

  • 如果結點的左兒子ptr->left_child爲空,則在中序遍歷中,用指向在ptr之前訪問的結點的指針代替ptr->left_child,即用指向ptr的中序遍歷的前驅結點的指針代替空鏈。
  • 如果結點的右兒子ptr->right_child爲空,則在中序遍歷中,用指向在ptr之後訪問的結點的指針代替ptr->right_child,即用指向ptr的中序遍歷的後驅結點的指針代替空鏈。
    現在有一顆二叉樹,其結構如圖:
    這裏寫圖片描述
    如果中序遍歷這顆二叉樹,訪問結點的順序是H,D,I,B,E,A,F,C,G,這裏以結點E爲例,來說明線索建立的過程吧:
    由於結點E的左兒子是一個空鏈,所以,用指向在結點之前訪問的結點(即B結點)的指針代替這個空鏈,類似地,由於結點E的右兒子也爲空,所以,用在中序遍歷中指向E後面結點(即結點A)的指針代替這個空鏈。
    該二叉樹轉換爲線索二叉樹後,該結構如圖:
    這裏寫圖片描述
    爲了能在內存表示線索二叉樹,我們需要增加兩個附加域:left_thread和right_thread來區分指針是線索指針還是正常指針,假設ptr是任意一個結點,如果ptr->left_thread=TRUE,那麼ptr->left_child是一個線索,否則它就是指向其左兒子的正常指針,right_threadl也類似。構造線索樹還加一個額外的頭結點,其頭結點結構爲:
    這裏寫圖片描述
    現在假設已經構建好了上面的中序線索二叉樹,那麼我們就可以使用該線索二叉樹實現中序遍歷,其思路:
    對每一個結點ptr來說,如果ptr->right_thread=TRUE,那麼根據線索定義,結點ptr的中序後繼結點,是ptr->right_child,否則,結點ptr的中序後繼結點是從其右兒子開始,沿着左兒子鏈到達left->thread=TRUE的結點。整個算法時間 複雜度還是O(n)。
    代碼實現:
typedef struct thread_tree *thread_pointer;
//線索二叉樹結構體
struct thread_tree
{
   short left_thread,right_thread;
   int data;
   thread_pointer left_child,right_child;
};
//尋找該結點的後驅結點
thread_pointer insucc(thread_pointer tree)
{
   thread_pointer temp=tree->right_child;
   if(!tree->right_thread)// 若果不是線索,則沿左兒子查找
      while(!temp->left_thread)
         temp=temp->left_child;
   return temp;
}
//中序線索樹遍歷輸出
void tinorder(thread_pointer tree)
{
   for(;;)
   {
      thread_pointer temp=insucc(tree);
      if(temp==tree) break;
      printf("%d",temp->data);
   }
}

向上面線索二叉樹中插入結點,假設我們只考慮插入一個新結點作爲結點parent的右兒子情況,那麼我們就有以下兩種情況要考慮:
若parent的右兒子爲空,則插入新結點後,線索二叉樹變化如下圖:
這裏寫圖片描述
若parent的右兒子存在右子樹,則插入新結點後,線索二叉樹變化如下圖:
這裏寫圖片描述
代碼實現:

//在線索二叉樹中,向父結點插入新的右兒子
void insert_right(thread_pointer parent,thread_pointer child)
{
   thread_pointer temp;
   child->right_child=parent->right_child;
   child->right_thread=parent->right_thread;
   child->left_child=parent;
   child->left_thread=TRUE;
   parent->right_child=child;
   parent->right_thread=child->right_thread;
   //當時第二種情況時,需查找新插入的結點的後驅結點,
   //並改變其前驅結點爲該新的兒子結點
   if(!child->right_thread)
   {
      temp=insucc(child);
      temp->left_child=child;
   }
}
發佈了119 篇原創文章 · 獲贊 10 · 訪問量 13萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章