1. 程式人生 > >二叉樹的遍歷和線索線索二叉樹

二叉樹的遍歷和線索線索二叉樹

一、二叉樹的遍歷

1.先序遍歷
在二叉樹非空的情況下:
(1)訪問根結點
(2)先序遍歷左子樹
(3)先序遍歷右子樹
對應演算法如下:
void PreOrder(BiTree T){
  if(T != NULL){
    visit(T);//訪問根結點
    PreOrder(T->lchild);//遍歷右子樹
    PreOrder(T->rchild);//遍歷左子樹
  } 
}
2.中序遍歷
(1)中序遍歷左子樹
(2)訪問根結點
(3)中序遍歷右子樹
對應演算法如下:
void InOrder(BiTree T){
  if(T != NULL){
    InOrder(T->lchild);
    visit(T);

    PreOrder(T->rchild);
  }

3.後序遍歷過程為:
(1)中序遍歷左子樹
(2)中序遍歷右子樹
(3)訪問根結點
對應演算法如下:
void PostOrder(BiTree T){
  if(T != NULL){
    InOrder(T->lchild);
    PreOrder(T->rchild);
    visit(T);
  }

4.由遍歷序列構造二叉樹
根據先序序列和中序序列可唯一確定一棵二叉樹
根據後序序列和中序序列也可以確定一棵二叉樹
但是後序和先序序列無法唯一確定一棵二叉樹

二、線索二叉樹
1.基本概念
若無左子樹,令lchild指向前驅結點,若無右子樹,令rchild指向後繼結點。前繼和後繼根據遍歷序列方式而不同

線索二叉樹儲存結構描述:
typedef struct _node_{
  int data;//資料
  struct _node_ *lchild, *rchild;//左右孩子指標
  int ltag,rtag;//左右線索標誌
}Node;
2.線索二叉樹構造
通過中序遍歷對二叉樹線索化演算法:
void InThred(ThreadTree &p,ThreadTrdd &pre){
  if(p != NULL){
    InThread(p->lchild, pre);//遞迴,線索化左子樹
    if(p->lchild == NULL){   //左子樹為空,建立前戲線索
      p->lchild = pre;
      p->ltag = 1;
    }
    if(pre != NULL && pre->rchild == NULL){
      pre->rchild = p;  //建立前驅結點的後繼線索
      pre->rtag = 1;
    }
    pre = p;  //標記當前結點成為剛剛訪問過的結點
    InThred(p->rchild, pre); //遞迴線索化右子樹
  }
}
主演算法如下:
void CreateInThread(ThreadTree T){
  ThreadTree pre = NULL;
  if(T != NULL){
    InThread(T, pre);
    pre->rchild = NULL;//處理遍歷的最後一個結點
    pre->rtag = 1;
  }
}
3.線索二叉樹的遍歷
(1)找中序二叉樹中中序序列下的第一個結點
  ThreadNode *Firstnode(ThreadNode *p){
    while(p->ltag == 0) p = p->lchild;
    return p;
  }
(2)找中序序列二叉樹結點p在中序序列下的後繼結點
  ThreadNode *Nextnode(ThreadNode *p){
    if(p->rtag == 0)return Firstnode(p->p->rchild);
    else return p->rchild; 
  }
(3)利用以上兩個演算法,寫出中序線索二叉樹的中序遍歷演算法
  void Inorder(ThreadNode *T){
    for(ThradNode *p=Firstnode(T); p!=NULL; p=Nextnode(p))
      visit(p);
}