1. 程式人生 > 其它 >非線性表-BiTree(二叉樹)

非線性表-BiTree(二叉樹)

1.Status InitBiTree(BiTree *T) 構造空二叉樹

2.Status DestroyBiTree(BiTree *T) 銷燬二叉樹,前提T存在

3.Status CreateBiTree(BiTree *T) 用先序遍歷建立二叉樹

4.Status ClearBiTree(BiTree *T) 清空二叉樹,前提T存在5.int BiTreeDepth(BiTree T) 返回二叉樹的深度,前提T存在

6.BiTree Root(BiTree T) 返回二叉樹的根,前提T存在

7.ElemType Value(BiTree T,BiTree e) 返回e的值,前提T存在

8.Status Assign(BiTree T,BiTree *e,ElemType value) 結點e賦值為value,前提T存在 9.BiTree Parent(BiTree T,BiTree e) 若e是T中某個非根結點,則返回它的雙親,否則返回NULL,前提T存在 10.BiTree LeftChild(BiTree T,BiTree e) 返回e的左孩子。若e無左孩子,則返回NULL,前提T存在 11.BiTree RightChild(BiTree T,BiTree e) 返回e的右孩子。若e無右孩子,則返回NULL,前提T存在 12.BiTree LeftSibling(BiTree T,BiTree e) 返回e的左兄弟。若e是其雙親的左孩子或無左兄弟,則返回NULL,前提T存在
13.BiTree RightSibling(BiTree T,BiTree e) 返回e的右兄弟。若e是其雙親的右孩子或無右兄弟,則返回NULL,前提T存在 14.Status InsertChild(BiTree T,BiTree p,int LR,BiTree c) 初始條件:T存在,p指向T中某個結點,LR為0或1,非空二叉樹c與T不相交且右子樹為空。 操作結果:根據LR為0或1,插入c為T中p所指結點的左或右子樹。p所指結點的原有左或右子樹則成為c的右子樹。
15.Status DeleteChild(BiTree T,BiTree p,int LR) 初始條件:T存在,p指向T中某個結點,LR為0或1
操作結果:根據LR為0或1,刪除T中p所指結點的左或右子樹
16.Status PreOrderTraverse(BiTree T) 先序遍歷二叉樹,前提T存在 17.Status InOrderTraverse(BiTree T) 中序遍歷二叉樹,前提T存在 18.Status PostOrderTraverse(BiTree T) 後序遍歷二叉樹,前提T存在 19.Status LevelOrderTraverse(BiTree T) 層序遍歷二叉樹,前提T存在
#include <stdio.h>
#include <stdlib.h>
//函式結果狀態程式碼
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define OVERFLOW -1

typedef int elemType;
typedef int status;
typedef struct bitNode
{
    elemType data;
    struct bitNode *lchild;
    struct bitNode *rchild;
}bitNode,*bitTree,*BiTree;

1.Status InitBiTree(BiTree *T) 構造空二叉樹

status initBitTree(bitTree *t)
{
    (*t)=(bitTree)malloc(sizeof(bitNode));
    if(!(*t))exit(OVERFLOW);
    (*t)->lchild=NULL;
    (*t)->rchild=NULL;
    return OK;
}

2.Status DestroyBiTree(BiTree *T) 銷燬二叉樹,前提T存在

status DestroyBiTree(bitTree *T)
{
    if(!(*T))
        return OK;
    DestroyBiTree(&((*T)->lchild));
    DestroyBiTree(&((*T)->rchild));
    free(*T);
    return OK;
}

3.Status CreateBiTree(BiTree *T) 用先序遍歷建立二叉樹

status CreateBiTree(bitTree *T)
{
    char ch=getchar();//讀入一個字元
    if(ch=='.') //個人認為用.表示空樹比較好(這樣輸入多個空樹的時候方便檢驗有沒有輸入錯誤,但是如果用空格的話,嗯......實在是無法檢驗)
        *T=NULL;
    else
    {
        *T=(bitTree)malloc(sizeof(bitNode));
        if(!(*T)) exit(OVERFLOW);
        (*T)->data=ch;
        CreateBiTree(&((*T)->lchild));
        CreateBiTree(&((*T)->rchild));
    }
    return OK;
}

4.Status ClearBiTree(BiTree *T) 清空二叉樹,前提T存在

status ClearBiTree(bitTree *T)//清空之後,根結點是改變了的
{
    if(!(*T))
        return ERROR;
    DestroyBiTree(&((*T)->lchild));
    DestroyBiTree(&((*T)->rchild));//這裡的確是銷燬,你沒看錯
    free(*T);
    (*T)=(bitTree)malloc(sizeof(bitNode));//重新分配空間
    if(!(*T)) exit(OVERFLOW);
    (*T)->lchild=NULL;
    (*T)->rchild=NULL;
    return OK;
}

5.int BiTreeDepth(BiTree T) 返回二叉樹的深度,前提T存在

int max(int a,int b)
{
    return (a>=b)?a:b;
}
int BiTreeDepth(bitTree T)
{
    if(!T)
        return 0;
    else
        return max(BiTreeDepth(T->lchild),BiTreeDepth(T->rchild))+1;
        //這有個缺點,空樹會返回深度1
}

6.BiTree Root(BiTree T) 返回二叉樹的根,前提T存在

bitTree Root(bitTree T)
{
    return T;
}

7.ElemType Value(BiTree T,BiTree e) 返回e的值,前提T存在

//輔助函式 T若為空返回,否則若等於要找得數返回真,或者有孩子節點等於要找得數返回真,且t為e
status Search(bitTree T,bitTree e)
{
    if(!T)
        return FALSE;
    if(T==e||Search(T->lchild,e)==TRUE||Search(T->rchild,e)==TRUE)
        return TRUE;
    else
        return FALSE;
}
elemType Value(bitTree T,bitTree e)
{
    if(Search(T,e)==TRUE)
        return e->data;
    else
        return 0;
}

8.Status Assign(BiTree T,BiTree *e,ElemType value) 結點e賦值為value,前提T存在

status Assign(bitTree T,bitTree *e,elemType value)
{
    if(Search(T,*e)==TRUE)
    {
        (*e)->data=value;
        return OK;
    }
    return ERROR;
}

9.BiTree Parent(BiTree T,BiTree e) 若e是T中某個非根結點,則返回它的父節點,否則返回NULL,前提T存在

bitTree Parent(bitTree T,bitTree e)
{
    if(T==e)//沒有雙親
        return NULL;
    if(T->lchild==e||T->rchild==e)//根節點是雙親
         return T;
    else if(Search(T->lchild,e)==TRUE)//根節點的左子樹有要找得數 執行完search t指向e這個值的雙親,t->lchild指向e
         return Parent(T->lchild,e);//返回父母節點
    else if(Search(T->rchild,e)==TRUE)//根節點的右子樹有要找得數t指向e這個值的雙親,t->lchild指向e
         return Parent(T->rchild,e);//返回父母節點
    else return NULL;
}
//root指向根節點,p,q指向二叉樹任意兩個節點的指標,找到p,q公共祖先節點r;
//向前追溯p的根節點pp,從pp出發尋找q節點,若找到則pp=r
//向前追溯pp的根節點ppp,從ppp出發尋找q節點,若找到則pp=r
void searchParent(bitTree root,bitTree p,bitTree q,bitTree r)
{
    if(!root||!p||!q)return 0;
    bitTree pp;
    pp=p;
    while(pp!=NULL)
    {
        //以pp為根節點,第一次以p為根節點,在子樹找q,找到說明pp是公共祖先節點
        if(Search(pp,q)==TRUE){
            r=pp;
            break;
        }
        pp=Parent(root,pp);//在樹中找到pp的雙親,返回雙親節點
    }
}

10.BiTree LeftChild(BiTree T,BiTree e) 返回e的左孩子。若e無左孩子,則返回NULL,前提T存在

bitTree leftChild(bitTree T,bitTree e)
{
    if(search(T,e)==TRUE)
    {
        return e->lchild;
    }else return NULL;
}

11.BiTree RightChild(BiTree T,BiTree e) 返回e的右孩子。若e無右孩子,則返回NULL,前提T存在

bitTree rightChild(bitTree T,bitTree e)
{
    if(search(T,e)==TRUE)
    {
        return e->rchild;
    }else return NULL;
}

12.BiTree LeftSibling(BiTree T,BiTree e) 返回e的左兄弟。若e是其雙親的左孩子或無左兄弟,則返回NULL,前提T存在

bitTree leftSibling(bitTree t,bitTree e)
{
    /**
    先找到這個e的位置t
    */
    if(Search(t,e)==TRUE&&Parent(t,e)->lchild!=e)
        return Parent(t,e)->lchild;
    else return NULL;
}

13.BiTree RightSibling(BiTree T,BiTree e) 返回e的右兄弟。若e是其雙親的右孩子或無右兄弟,則返回NULL,前提T存在

bitTree rightSibling(bitTree t,bitTree e)
{
    if(search(t,e)==TRUE&&Parent(t,e)->rchild!=e)
        return Parent(t,e)->rchild;
    else return NULL;
}

14.Status InsertChild(BiTree T,BiTree p,int LR,BiTree c)

初始條件:T存在,p指向T中某個結點,LR為0或1,非空二叉樹c與T不相交且右子樹為空。

操作結果:根據LR為0或1,插入c為T中p所指結點的左或右子樹。p所指結點的原有左或右子樹則成為c的右子樹。

status insertChild(bitTree t,bitTree p,int lr,bitTree c)
{
    if(!t||Search(t,p)==FALSE)
    {
        return ERROR;
    }
    bitTree q;
    if(lr==0)//插入到p左邊
    {
        q=p->lchild;
        p->lchild=c;
        c->rchild=q;
    }
    /**
     o p
    o c
      o q
    */
    else if(lr==1)//插入到p右邊
    {
        q=p->rchild;
        p->rchild=c;
        c->rchild=1;
    }
    else return ERROR;
    return OK;
}

15.Status DeleteChild(BiTree T,BiTree p,int LR)

初始條件:T存在,p指向T中某個結點,LR為0或1

操作結果:根據LR為0或1,刪除T中p所指結點的左或右子樹

status deleteChile(bitTree t,bitTree p,int lr)
{
    if(t&&Search(t,p)==FALSE)
    {
        return ERROR;
    }
    if(lr==0)
    {
        DestroyBiTree(&p->lchild);
        p->lchild=NULL;
    }
    else if(lr==1)
    {
        DestroyBiTree(&p->rchild);
        p->rchild=NULL;
    }
    else return ERROR;
    return OK;
}

16.Status PreOrderTraverse(BiTree T) 先序遍歷二叉樹,前提T存在

1:遞迴

status PreOrderTraverse(bitTree T)
{
    if(!T)
        return ERROR;
    printf("%c ",T->data);
    PreOrderTraverse(T->lchild);
    PreOrderTraverse(T->rchild);
    return OK;
}

2:非遞迴

     1
   2   3
 4  5 6  7
遍歷順序:1 2 4 5 3 6 7
步驟:
1:初始化棧 2:如果根節點不為空,入棧 3; 定義二叉樹空節點topNode,存放彈出的棧頂元素 4:彈出的棧頂元素1,存topNode,訪問該元素,若存在右節點先將右節點入棧3,然後左節點入棧2 5:彈出的棧頂元素2,存topNode,訪問該元素,若存在右節點先將右節點入棧5,然後左節點入棧4 5:彈出的棧頂元素4,存topNode,訪問該元素,沒有左右節點 6:彈出的棧頂元素5,存topNode,訪問該元素,沒有左右節點 7:彈出的棧頂元素3,存topNode,訪問該元素,若存在右節點先將右節點入棧7,然後左節點入棧6 5:彈出的棧頂元素6,存topNode,訪問該元素,沒有左右節點 5:彈出的棧頂元素7,存topNode,訪問該元素,沒有左右節點:
//資料元素為二叉樹的棧,用於非遞迴二叉樹樹的遍歷
typedef struct stackNode
{
    bitTree bnode;
    struct stackNode *next;
}Stack;
int initStack(Stack &stack) {
    stack= (Stack *) malloc(sizeof(Stack));
    if (!stack)return 0; //記憶體分配失敗,儲存空間不夠
    return 1;
}
//入棧 stack指向棧頂
Stack *push(Stack *top,bitTree t)
{
    Stack *p=(Stack *)malloc(sizeof(Stack));
    p->bnode=t;
    p->next=top;
    top=p;
    return top;
}
//出棧 stack指向棧頂
Stack *pop(Stack *top,bitTree *t)
{
    if(top)
    {
        Stack *s=top;
        top=top->next;
        printf("彈棧元素:%d ",s->bnode->data);

        if (top) {
            printf("棧頂元素:%d\n",s->bnode->data);
        }else{
            printf("棧已空\n");
        }
         t=s->bnode;
        free(s);
    }
    else
    {
        printf("棧內沒有元素");
        return top;
    }
    return top;
}
void PreNormal(BitTree *parent)
{
    Stack stack;
    if(initStack(stack)==0)
    {
        return ;
    }
    if(parent==NUll)
    {
        return ;
    }
    push(stack,*parent);
    BitTree topNode;
    while(pop(stack,topNode))//取棧頂元素,訪問並出棧

    {
        visit(topNode);//訪問棧頂元素
        if(topNode.right!=NULL)//存在右結點,則先將右結點入棧。因為左結點先遍歷
        {
            push(stack,*(topNode.right));
        }
        if(topNode.left!=NULL) //存在左結點,左結點入棧
        {
            push(stack,*(topNode.right));
        }
    }
}

17.Status InOrderTraverse(BiTree T) 中序遍歷二叉樹,前提T存在

1:遞迴

status InOrderTraverse(bitTree T)
{
    if(!T)
        return ERROR;
    InOrderTraverse(T->lchild);
    printf("%c ",T->data);
    InOrderTraverse(T->rchild);
    return OK;
}

2:非遞迴

概述:先將根結點入棧,然後根據根結點一直尋找到該左子樹的最左邊結點,訪問該結點。如果該結點不存在右子樹,直接將該結點出棧,
並一直出棧到棧頂的結點存在右子樹。此時將棧頂結點出棧,並將該結點的右孩子結點入棧,並尋找到該結點右子樹的最左邊結點。
1 2 3 4 5 6 7 步驟: 1: 初始化棧 2:如果根節點不為空,入棧 3; 定義二叉樹空節點topNode,存放彈出的棧頂元素 4: 取棧頂元素 存topNode 若該元素存在左節點,左節點入棧,topNode指向該元素,直到左節點元素為空1 2 4 5:取棧頂元素4 不存在右節點,直接出棧 出棧元素存入topNode,輸出topNode ,繼續取棧頂元素重複操作,直到存在右節點; 6:取棧頂元素2 存在右節點 ,直接出棧 出棧元素存入topNode,輸出topNode ,存入右節點5 4: 取棧頂元素5 存topNode 若該元素存在左節點,左節點入棧,topNode指向該元素,直到左節點元素為空 5:取棧頂元素5 不存在右節點,直接出棧 出棧元素存入topNode,輸出topNode ,繼續取棧頂元素重複操作,直到存在右節點; 6:取棧頂元素1 存在右節點 ,直接出棧 出棧元素存入topNode,輸出topNode ,存入右節點3 4: 取棧頂元素3 存topNode 若該元素存在左節點,左節點入棧,topNode指向該元素,直到左節點元素為空3 6 5:取棧頂元素6 不存在右節點,直接出棧 出棧元素存入topNode,輸出topNode ,繼續取棧頂元素重複操作,直到存在右節點; 6:取棧頂元素3 存在右節點 ,直接出棧 出棧元素存入topNode,輸出topNode ,存入右節點7 4: 取棧頂元素7 存topNode 若該元素存在左節點,左節點入棧,topNode指向該元素,直到左節點元素為空 5:取棧頂元素7 不存在右節點,直接出棧 出棧元素存入topNode,輸出topNode ,繼續取棧頂元素重複操作,直到存在右節點;
void MidNormal(BitTree *parent)
{
    Stack stack;
    if(initStack(stack)==0)
    {
        return ;
    }
    if(parent==NUll)
    {
        return ;
    }
    push(stack,*parent);
    BitTree topNode;
    while(top(stack,topNode))//取棧頂節點
    {
        /*
         * 首先,一直遍歷到最左邊的結點
         */
        while (topNode.left != NULL) { //左孩子結點不為空,入棧
            push(stack, *(topNode.left));//左孩子結點入棧
            topNode = *(topNode.left);//看下一個左孩子結點
        }
        /*
         * 其次,判斷其是否存在右孩子結點。
         * 不存在右孩子結點,直接將該結點出棧
         */
        int flag = 1;
        while (flag && topNode.right == NULL) {
            pop(stack, topNode);//出棧
            visit(topNode);
            flag = top(stack, topNode);//取棧頂結點,繼續判斷
        }

        /*
         * 存在右孩子結點,當前結點出棧,並將右孩子結點入棧
         */
        if (pop(stack, topNode)) {
            visit(topNode);
            push(stack, *(topNode.right));
        }
    }
}

18.Status PostOrderTraverse(BiTree T) 後序遍歷二叉樹,前提T存在

1:遞迴

status PostOrderTraverse(bitTree T)
{
    if(!T)
        return ERROR;
    PostOrderTraverse(T->lchild);
    PostOrderTraverse(T->rchild);
    printf("%c ",T->data);
    return OK;
}

2:非遞迴

/*         1
 *       2   3
 *     4  5 6  7
 *逆後續:1 3 7 6 2 5 4  
 *遍歷存入棧中 入棧順序 1 2 3 6 7 4 5 出棧 1 3 7 6 2 5 4
 *後續:  4 5 2 6 7 3 1 彈出的順序為後序遍歷
 */
void PostNormal(BitTree *parent)
{
    /*
     * 宣告兩個棧,遍歷樹的管理棧和備用棧
     */
        Stack stack,newstack;
        if(initStack(stack)==0)
        {
            return;
        }
       if(initStack(newstack)==0)
        {
            return;
        }
        if(parent==NULL)
        {
            return;
        }
        push(stack,*parent);
        bitTree topNode;//記錄當前棧頂結點
        while(pop(stack,topNode))
        {
            push(newstack,*topNode);//入棧
            if(topNode.lchild!=NULL)
            {
                push(stack,*(topNode.lchild));
            }
            if(topNode.rchild!=NULL)
            {
                push(stack,*(topNode.lchild));
            }

        }
        while(pop(newstack,topNode))
        {
            printf("%d",*(topNode));
        }


}

19.Status LevelOrderTraverse(BiTree T) 層序遍歷二叉樹,前提T存在

//資料元素為二叉樹的佇列,用於層次遍歷
typedef struct QueNode
{
    bitTree Quedata;
    struct QueNode *next;
}QueNode,*QueuePtr;
typedef struct
{
    QueuePtr front;
    QueuePtr rear;
}LinkQueue;
//構造空佇列
status InitQue(LinkQueue *q)
{
    (*q).front=(QueuePtr)malloc((sizeof(QueNode)));
    if(!(*q).front) exit(-1);
    (*q).front->next=NULL;
    (*q).rear=(*q).front;
    return OK;
}
//判佇列空
status QueEmpty(LinkQueue q)
{
    if(q.front==q.rear)return TRUE;
    else return FALSE;
}
//插入元素e作為新的佇列元素,前提是q存在
status EnQue(LinkQueue *q,bitTree e)
{
    QueuePtr p=(QueuePtr)malloc((sizeof(QueNode)));
    if(!p)exit(OVERFLOW);
    p->Quedata=e;
    p->next=NULL;
    (*q).rear->next=p;
    (*q).rear=p;
    return OK;
}
//若佇列不空,刪除隊頭元素,用e返回其值
status DeQue(LinkQueue *q,bitTree *e)
{
    if((*q).front==(*q).rear)return ERROR;
    QueuePtr p=(*q).front->next;
    *e=p->Quedata;
    (*q).front->next=p->next;
    if((*q).rear==p)
    {
        (*q).rear=(*q).front;
    }
    free(p);
    return OK;
}
status levelTraverse(bitTree t)
{
    if(!t)
    {
        return ERROR;
    }
    LinkQueue q;
    InitQue(&q);
    bitTree p;
    EnQue(&q,t);//頭結點入隊
    while(QueEmpty(q)==FALSE)
    {
        DeQue(&q,&p);
        printf("%c",p->data);
        if(p->lchild)
        {
            EnQue(&q,p->lchild);
        }
        if(p->rchild)
        {
            EnQue(&q,p->rchild);
        }
    }
    return OK;
}

結束:

int main()
{
    bitTree T,c;
    char ch;
    printf("測試第一個基本操作\n");
    if(InitBiTree(&T)==OK&&InitBiTree(&c)==OK)printf("二叉樹初始化成功!\n");

    printf("第三個基本操作\n");
    printf("先序遍歷構造二叉樹T\n");
    CreateBiTree(&T);
    ch=getchar();//吸收換行符
    printf("先序遍歷:\n");
    PreOrderTraverse(T);
    printf("中序遍歷:\n");
    InOrderTraverse(T);
    printf("後序遍歷:\n");
    PostOrderTraverse(T);
    printf("層序遍歷:\n");
    LevelOrderTraverse(T);

    printf("構造二叉樹c\n");
    CreateBiTree(&c);
    printf("層序遍歷:");
    LevelOrderTraverse(c);
    printf("第七個基本操作\n");
    printf("T的深度為:%d\n",BiTreeDepth(T));
printf(
"測試第八、九個操作\n"); printf("根為:%c\n",Value(T,Root(T)));
printf(
"第十至第十四個基本操作\n"); bitTree m=T->lchild->lchild,n=T->rchild;//這裡我是在知道二叉樹結構的情況下進行賦值的 printf("m為:%c,n為:%c\n",Value(T,m),Value(T,n)); printf("m的雙親為:%c,n的雙親為:%c\n",Value(T,Parent(T,m)),Value(T,Parent(T,n))); printf("m的左孩子為:%c,n的左孩子為:%c\n",Value(T,leftChild(T,m)),Value(T,leftChild(T,n))); printf("m的右孩子為:%c,n的右孩子為:%c\n",Value(T,rightChild(T,m)),Value(T,rightChild(T,n))); printf("m的左兄弟為:%c,n的左兄弟為:%c\n",Value(T,leftSibling(T,m)),Value(T,leftSibling(T,n))); printf("m的右兄弟為:%c,n的右兄弟為:%c\n",Value(T,rightSibling(T,m)),Value(T,rightSibling(T,n)));
printf(
"第十個基本操作\n"); printf("將n的值改為G\n"); Assign(T,&n,'G'); printf("層序遍歷:"); LevelOrderTraverse(T);
printf(
"第十四個基本操作\n"); InsertChild(T,n,0,c); printf("層序遍歷T:"); LevelOrderTraverse(T);
printf(
"第十五個基本操作\n"); DeleteChild(T,n,0); printf("層序遍歷T:"); LevelOrderTraverse(T);
printf(
"第二個基本操作\n"); if(DestroyBiTree(&T)==OK) printf("銷燬二叉樹T成功!\n"); return 0; }