1. 程式人生 > >樹與二叉樹(C語言)

樹與二叉樹(C語言)

1. 儲存結構

1.1 順序儲存結構

1.2 鏈式儲存結構

typedef strcture BTNode
{
  char data;
  struct BTNode *lchild;
  struct BTNode *rchild;
}BTNode;

1.2.1 孩子儲存結構

1.2.2 樹的孩子兄弟儲存結構

把樹轉換成二叉樹的樣子,進行儲存

typedef struct BTNode
{
  int data;
  BTNode* child;
  BTNode* sibling;
} BTNode;
// 連結:
A1->child=A2;
A1->sibling=NULL;
A2->sibling= A3;
A3->sibling=A4;
A4->sibling=NULL;
// 取A1孩子結點A3:
A1->child->sibling

2. 遍歷

2.1 二叉樹的遍歷 - 遞迴演算法

void preorder(BTNode *p)
{
  if(p!=NULL)
  {
    //(1)Visit(p)
    preorder(p->lchild);
    //(2)Visit(p)
    preorder(p->rchild);
    //(3)Visit(p)
  }
}
// 假設訪問函式visit()已經定義過
// Visit(p)則在(1)、(2)、(3)處
// 分別是先序、中序和後序遍歷。

2.2 層次遍歷

需要建立一個迴圈佇列

void level(BTNode *p)
{
  int
front, rear; BTNode *que[maxSize]; // 定義一個迴圈佇列,用來記錄將要訪問 // 的層次上的結點 front = rear=0; BTNode *q; if(p!=NULL) { rear=(rear+1)%maxSize; que[rear]=p; // 根節點入隊 while(front!=rear) //當佇列不空的時候進行迴圈 { front=(front+1)%maxSize; q = que[front]; // 隊頭結點出隊 Visit(q); //放問隊頭結點 if
(q->lchild!=NULL) //如果左子樹不空,則左子樹的根結點入隊 { rear=(rear+1)%maxSize; que[rear]=q->lchild; } if(q->rchild!=NULL) // 如果右子樹不空,則右子樹的根節點入隊 { rear=(rear+1)%maxSize; que[rear]=q->rchild } } } }

2.3 線索二叉樹

2.3.1 線索化

通過中序遍歷對二叉樹線索化的遞迴演算法

void InThread(TBTNode *p, TBTNode *&pre)
{
    if(p!=NULL)
    {
        InThread(p->lchild,pre);
        if(p->lchile==NULL)
        /* 建立當前結點的前驅線索 */
        {
            p->lchild=pre;
            p->ltag=1;
        }
        if(pre!=NULL&&pre->rchild==NULL)
        /* 建立前驅結點的後繼線索 */
        {
            pre->rchild=p;
            pre->rtag=1;
        }
        pre=p; 
        //pre指向當前的p,作為p將要指向的下一個結點的前驅結點指示指標
        p=p->rchild; 
        //p指向一個新結點,此時pre 和p分別指向的結點形成了一個前驅後繼對
        InThread(p,pre)
    }
}

2.3.2 建立中序線索二叉樹

通過中序遍歷建立中序線索二叉樹

void createInThread(TBTNode *root)
{
    TBTNode *pre=NULL; //前驅結點指標
    if(root!=NULL)
    {
        InThread(root,pre);
        pre->rchild=NULL; //非空二叉樹,線索化
        pre->rtag=1 //後處理中序最後一個結點
    }
}

2.3.3 遍歷中序線索二叉樹

求以p為根的中序線索二叉樹中,中序序列下的第一個結點
TBTNode *First(TBTNode *p)
{
    while(p->ltag==0)
        p=p->lchild;  // 最左下結點(不一定是葉結點)
    return p;
}
求在中序線索二叉樹中,結點p在中序下的後繼結點
TBTNode *Next(TBTNode *p)
{
    if(p->rtag==0)
        return First(p->rchild);
    else
        return p->rchild; //rtag==1,直接返回後繼線索
}
遍歷中序線索二叉樹
void Inorder(TBTNode *root)
{
    for(TBTNode *p=First(root);p!=NULL;p=Next(p))
        Visit(p)
}