1. 程式人生 > 其它 >二叉樹的一些學習

二叉樹的一些學習

轉:https://xiaozhuanlan.com/topic/5036471892

二叉樹性質
1)在二叉樹的第i層上最多有2i-1 個節點 。(i>=1)
2)二叉樹中如果深度為k,那麼最多有2k-1個節點。(k>=1)
3)n0=n2+1 n0表示度數為0的節點數,n2表示度數為2的節點數。
4)在完全二叉樹中,具有n個節點的完全二叉樹的深度為[log2n]+1,其中[log2n]是向下取整。
5)若對含 n 個結點的完全二叉樹從上到下且從左至右進行 1 至 n 的編號,則對完全二叉樹中任意一個編號為 i 的結點有如下特性:
  (1) 若 i=1,則該結點是二叉樹的根,無雙親, 否則,編號為 [i/2] 的結點為其雙親結點;


  (2) 若 2i>n,則該結點無左孩子, 否則,編號為 2i 的結點為其左孩子結點;
  (3) 若 2i+1>n,則該結點無右孩子結點, 否則,編號為2i+1 的結點為其右孩子結點。


二叉樹遍歷
前序遍歷 :通俗的說就是從二叉樹的根結點出發,當第一次到達結點時就輸出結點資料,按照先向左再向右的方向訪問。
中序遍歷 :就是從二叉樹的根結點出發,當第二次到達結點時就輸出結點資料,按照先向左再向右的方向訪問。
後序遍歷 :就是從二叉樹的根結點出發,當第三次到達結點時就輸出結點資料,按照先向左再向右的方向訪問。
層序遍歷 :層次遍歷就是按照樹的層次自上而下的遍歷二叉樹。

*雖然二叉樹的遍歷過程看似繁瑣,但是由於二叉樹是一種遞迴定義的結構,故採用遞迴方式遍歷二叉樹的程式碼十分簡單。

void PreOrderTraverse(BiTree T)
{
    if(T==NULL)
    return;
    printf("%c", T->data);  /*顯示結點資料,可以更改為其他對結點操作*/
    PreOrderTraverse(T->lchild);    /*再先序遍歷左子樹*/
    PreOrderTraverse(T->rchild);    /*最後先序遍歷右子樹*/
}


/*二叉樹的中序遍歷遞迴演算法*/
void InOrderTraverse(BiTree T)
{
    if(T==NULL)
    return;
    InOrderTraverse(T
->lchild); /*中序遍歷左子樹*/ printf("%c", T->data); /*顯示結點資料,可以更改為其他對結點操作*/ InOrderTraverse(T->rchild); /*最後中序遍歷右子樹*/ } /*二叉樹的後序遍歷遞迴演算法*/ void PostOrderTraverse(BiTree T) { if(T==NULL) return; PostOrderTraverse(T->lchild); /*先後序遍歷左子樹*/ PostOrderTraverse(T->rchild); /*再後續遍歷右子樹*/ printf("%c", T->data); /*顯示結點資料,可以更改為其他對結點操作*/ }

將二叉樹按中序遍歷得到一個有序的陣列結果,某個節點元素的前後相鄰的節點即為前驅節點,後區節點

前驅節點
1:如果當前節點的左子樹不為空,那麼該點的前驅節點為該點左子樹中最右的節點。
2:如果當前節點的左子樹為空,那麼該點的前驅節點為從該點往上延伸,如果延伸到的點為其父親節點的右孩子,那麼這個父親節點就是該點的前驅節點。

後驅節點
1:如果當前節點的右子樹不為空,那麼該點的後驅節點為該點右子樹中最左的節點。
2:如果當前節點的右子樹為空,那麼該點的後驅節點為從該點往上延伸,如果延伸到的點為其父親節點的左孩子,那麼這個父親節點就是該點的後驅節點。

struct node
{
  node left;//左孩子
  node right;//右孩子
  node parent;//父親節點
  int value;
};

node getfristornode(node heap)//heap代表當前要找前驅節點的節點
{
  if(heap==null)//如果當前節點為空,返回空
    return heap;
  if(heap.left!=null)//如果當前節點左子樹不為空,那麼該節點的後繼節點為左子樹中最右的節點
    return getrightmost(heap.left);//找到左子數樹中最右的節點,並返回
  else                //如果程式到達這裡,說明當前節點的左子數為空
  {
    node parent=heap.parent;

       //第一個條件就是判斷那種特殊情況的,一直延伸到當前節點沒有父親節點時,那麼parent為空,這個條件不滿足,函式返回空
       //第二個條件是判斷當前節點是否為該父親節點的右孩子,如果不是,繼續執行下面的程式碼,如果是,說明這個父親節點就是heap節點的前驅節點
    while (parent!=null&&heap!=parent.right)
    {                    
      heap=parent;
      parent=heap.parent;
    }
    return parent;
  }
}

//這個函式是求左子樹中最右的節點的函式
getrightmost(node heap)
{
  while (heap!=null)
    heap=heap.right;
  return heap.parent;
 
}

上面是前驅節點的查詢方式,後區節點基本相同,左右換下。