用數組實現順序存儲二叉樹及操作的實現


 

實現了順序存儲結構的二叉樹和隊列的基本操作,以下是相關函數及類型的聲明

 

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h> 
#include <math.h>

#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0

#define MAX_TREE_SIZE 100
#define MAX_QUEUE_SIZE 5
#define Nil ' ' 

typedef char TElemtype;    //將樹的結點類型設置為字符型 
typedef int QElemType;    //將隊列的結點類型設置為整形 


typedef struct{     
    QElemType *base;    //隊列的基地址 
    int front;     
    int rear;     
}SqQueue;

typedef TElemtype SqBiTree[MAX_TREE_SIZE];    //定義順序存儲二叉樹的結構數組 

typedef struct{
    int level;    //樹的層號 
    int order;    //一層中的序號(從左向右) 
}position;

/**-------隊列的函數聲明------*/

int InitQueue(SqQueue *);    //初始化隊列 
int DestroyQueue(SqQueue *);    //銷毀隊列 
int ClearQueue(SqQueue *);    //清空隊列 
int QueueEmpty(SqQueue *);    //隊列是否為空 
int GetQueueLength(SqQueue *);    //獲取隊列的長度 
int GetQueueHead(SqQueue *,QElemType *);    //獲取隊頭元素 
int EnterQueue(SqQueue *,QElemType);    //向隊列中插入元素 
int DeleteQueue(SqQueue *,QElemType *);    //向隊列中刪除元素 
int (*QueueVisit)(QElemType);    //函數變量 
int QueueTraverse(SqQueue *,int (*) (QElemType));    //遍歷隊列 


/*---------二叉樹的函數聲明*/ 

int InitBiTree(SqBiTree);    //初始化二叉樹 
int CreateBiTree(SqBiTree);    //創建二叉樹 
int BiTreeEmpty(SqBiTree);    //判斷二叉樹是否為空 
int BiTreeDepth(SqBiTree);    //計算二叉樹的深度 
int GetRoot(SqBiTree,TElemtype *);    //獲取二叉樹的根結點 
TElemtype GetNodeValue(SqBiTree,position);    //獲取二叉樹結點元素 
int Assign(SqBiTree,position,TElemtype);    //給結點元素賦值 
TElemtype GetParent(SqBiTree,TElemtype);    //獲取結點的雙親結點 
TElemtype GetLeftChild(SqBiTree,TElemtype);    //獲取結點的左孩子 
TElemtype GetRightChild(SqBiTree,TElemtype);    //獲取結點的右孩子 
TElemtype GetLeftSibling(SqBiTree,TElemtype);    //獲取結點的左兄弟 
TElemtype GetRightSibling(SqBiTree,TElemtype);    //獲取結點的右兄弟 
void Move(SqBiTree,int,SqBiTree,int);    //移動結點 
int InsertChild(SqBiTree,TElemtype,int,SqBiTree);    //插入子結點 
int DeleteChild(SqBiTree,position,int);    //刪除子結點 
int (*TreeVisit)(TElemtype);    //函數變量 
int PreOrderTraverse(SqBiTree, int (*Visit)(TElemtype));    //先序遍歷二叉樹 
int InOrderTraverse(SqBiTree,int (*Visit)(TElemtype));    //中序遍歷二叉樹 
int PostOrderTraverse(SqBiTree,int (*Visit)(TElemtype));    //后序遍歷二叉樹 
void LevelOrderTraverse(SqBiTree,int (*Visit)(TElemtype));    //層序遍歷二叉樹 
void PrintTree(SqBiTree);    //打印二叉樹 

 

以下是函數的定義

*-----------隊列的函數定義-----------*/ 
 
 /*初始化隊列*/ 
int InitQueue(SqQueue *Q)
{
    //分配內存區域 
    Q->base=(QElemType *)malloc(MAX_QUEUE_SIZE*sizeof(QElemType)); 
    if(!Q->base)
    {
        printf("存儲分配失敗.\n");
        return ERROR;
    }
    Q->front=Q->rear=0;    //將隊列置空 
    return OK;
}

/*銷毀隊列*/ 
int DestroyQueue(SqQueue *Q)
{
    if(Q->base)
    {
        free(Q->base);
    }
    Q->front=Q->rear=0;
    return OK;
}

/*清空隊列*/ 
int ClearQueue(SqQueue *Q)
{
    Q->front=Q->rear=0;
    return OK;
}

/*判斷隊列是否為空*/ 
int QueueEmpty(SqQueue *Q)
{
    if(Q->front==Q->rear)
    {
        return OK;
    }
    else
    {
        
        return ERROR;
    }
}

/*獲取隊列長度*/
int GetQueueLength(SqQueue *Q)
{
    return (Q->rear-Q->front);
}

/*獲取隊列頭的元素*/ 
int GetQueueHead(SqQueue *Q,QElemType *e)
{
    if(!QueueEmpty(Q))
    {
        *e=*(Q->base+Q->front);    
        return OK;    
    }
    return ERROR;
}

/*使元素進隊*/ 
int EnterQueue(SqQueue *Q,QElemType e)
{
    if(Q->rear == MAX_QUEUE_SIZE)    //隊列滿了,重新分配內存區域,用realloc 
    {
        printf("隊列已滿,嘗試增加存儲單元...\n"); 
        Q->base=(QElemType *)realloc(Q->base,MAX_QUEUE_SIZE+1);
        if(!Q->base)        
        {
            printf("增加隊列存儲單元失敗.\n");
            return ERROR;
        }
    }
    *(Q->base+Q->rear)=e;
    Q->rear++;
    return OK;
}

/*刪除隊頭元素*/ 
int DeleteQueue(SqQueue *Q,QElemType *e)
{
    if(QueueEmpty(Q))
    {
        //printf("隊列為空.\n");
        return ERROR;
    }
    *e=*(Q->base+Q->front);
    Q->front++;
    return OK;
}

/*遍歷隊列*/ 
int QueueTraverse(SqQueue *Q,int (*QV)(QElemType) )
{
    int i=0;
    while(i<Q->rear)
    {
        (*QV)(*(Q->base+i));
        i++;
    }    
}

/*訪問隊列中元素的函數,將元素值打印出來*/ 
int QueueVisitFunc(QElemType e)
{
    printf("%d\n",e);
}

/*-------二叉樹的函數定義-------*/

/*初始化樹*/ 
int InitBiTree(SqBiTree T)
{
    int i;
    for(i=0;i<MAX_TREE_SIZE;i++)
    {
        T[i]=Nil;    //將初值設為空格 
    }
    
    T[MAX_TREE_SIZE]='\0';    //給數組尾部加上結標致 
    return OK;
} 

/*創建樹*/ 
int CreateBiTree(SqBiTree T)
{
    int i=0;
    int l=0;
    char s[MAX_TREE_SIZE];
    printf("請按順序輸入結點的值,空格表示空結點,結點數<=%d\n",MAX_TREE_SIZE);
    gets(s);
    l=strlen(s);
    for(;i<l;i++)
    {
        T[i]=s[i];
        if(i!=0&&T[(i+1)/2-1]==Nil&&T[i]!=Nil)
        {
            printf("出現無雙親且不是根的結點.\n");
            return ERROR;
        }
    }
    for(;i<MAX_TREE_SIZE;i++)
    {
        T[i]=Nil; 
    }
    return OK;
}

#define ClearBiTree InitBiTree    //在順序存儲結構中,ClearBiTree和InitBiTree完全一樣 

/*判斷樹是否為空*/ 
int BiTreeEmpty(SqBiTree T)
{
    if(T[0]==Nil)
    {
        printf("樹為空.\n");
        return TRUE;
    }
    else
    {
        return FALSE;
    }
}

/*計算樹的深度*/ 
int BiTreeDepth(SqBiTree T)
{
    int j=-1;
    int i=0;
    if(BiTreeEmpty(T))
    {
        return ERROR;    
    }
    for(i=MAX_TREE_SIZE-1;i>=0;i--)
    {
        if(T[i]!=Nil)
        {
            break;
        }
    }
    i++;
    //printf("i = %d\n",i);
    do
    {
        j++;
    }while(i>=pow(2,j));
    return j;
}

/*獲取根結點的值*/ 
int GetRoot(SqBiTree T,TElemtype * e)
{
    if(BiTreeEmpty(T))
    {
        return ERROR;
    }
    *e=T[0];
    return OK;
}

/*根據位置獲取某一結點的值*/ 
TElemtype GetNodeValue(SqBiTree T,position p)
{
    return T[(int)pow(2,p.level)-1-(int)pow(2,p.level-1)+p.order-1];
}

/*根據結點的位置給某一結點元素賦值*/ 
int Assign(SqBiTree T,position p,TElemtype e)
{
    int i = (int)pow(2,p.level)-1-(int)pow(2,p.level-1)+p.order-1;
    if(e!=Nil&&T[(i+1)/2-1]==Nil)
    {
        printf("將要賦值的結點雙親為空,不合法.\n");
        return ERROR;
    }
    if(e==Nil&&(T[2*i+1]!=Nil||T[2*i+2]!=Nil))
    {
        printf("將有子結點的結點賦空值,不合法.\n");
        return ERROR;
    }
    T[i]=e;
    //printf("T[%d] 已修改為: %c.\n",i,T[i]);
    return OK;
}

/*獲取結點元素的雙親結點*/ 
TElemtype GetParent(SqBiTree T,TElemtype e)
{
    int i;
    if(BiTreeEmpty(T))
    {
        return Nil;
    }
    for(i=0;i<MAX_TREE_SIZE;i++)
    {
        if(T[i]==e)
        {
            return T[(i+1)/2-1];
        }
    }     
    printf("未找到雙親結點.\n");
    return Nil;
}

/*獲取結點元素的左孩子*/ 
TElemtype GetLeftChild(SqBiTree T,TElemtype e)
{
    int i;
    if(BiTreeEmpty(T))
    {
        return Nil;
    }
    for(i=0;i<MAX_TREE_SIZE;i++)
    {
        if(T[i]==e)
        {
            return T[2*i+1];
        }
    }
    printf("未找到左孩子.\n");
    return Nil;
}

/*獲取結點元素的右孩子*/ 
TElemtype GetRightChild(SqBiTree T,TElemtype e)
{
    int i;
    if(BiTreeEmpty(T))
    {
        return Nil;
    }
    for(i=0;i<MAX_TREE_SIZE;i++)
    {
        if(T[i]==e)
        {
            return T[2*i+2]; 
        }
    }
    printf("未找到右孩子.\n");
    return Nil;
} 

/*獲取結點元素的左兄弟*/ 
TElemtype GetLeftSibling(SqBiTree T,TElemtype e)
{
    int i;
    if(BiTreeEmpty(T))
    {
        return Nil;
    }
    for(i=1;i<MAX_TREE_SIZE;i++)
    {
        if(T[i]==e&&i%2==0)
        {
            return T[i-1];
        }
    }
    printf("未找到左兄弟.\n");
    return Nil;
}

/*獲取結點元素的右兄弟*/ 
TElemtype GetRightSibling(SqBiTree T,TElemtype e)
{
    int i;
    if(BiTreeEmpty(T))
    {
        return Nil;
    }
    for(i=1;i<MAX_TREE_SIZE;i++)
    {
        if(T[i]==e&&i%2!=0)
        {
            return T[i+1];
        }
    }
    printf("未找到右兄弟.\n");
    return Nil;
}

/*把從T1中j結點開始的子樹移到T2中i結點開始的子樹*/ 
void Move(SqBiTree T1,int i1,SqBiTree T2,int i2)
{
    if(T1[2*i1+1] != Nil)
    {/*左子樹不空*/
        Move(T1,2*i1+1,T2,2*i2+1);
    }
    if(T1[2*i1+2] != Nil)
    {/*右子樹不空*/
        Move(T1,2*i1+2,T2,2*i2+2);    
    }
    /*左右子樹都為空,說明該結點為葉子結點,可以移動.*/
    T2[i2]=T1[i1];
    T1[i1]=Nil;
}

/*插入結點或子樹*/ 
int InsertChild(SqBiTree T,TElemtype e,int LR,SqBiTree S)
{
    int j,k,i=0;
    if(BiTreeEmpty(T))
    {
        return ERROR;
    }
    for(j=0;j<(int)pow(2,BiTreeDepth(T))-1;j++)
    {
        if(T[j]==e)
        {
            break;
        }
    }
    k=2*j+LR;    //k為e結點的左或右孩子的序號
     if(T[k]!=Nil)
     {/*e結點的左右孩子不空,即e結點不是葉子結點*/
        Move(T,k,T,2*k+2);     
    }
    Move(S,i,T,k); 
} 

/*刪除結點或子樹*/ 
int DeleteChild(SqBiTree T,position p,int LR)
{
    int i;
    int k=OK;
    SqQueue Q;
    InitQueue(&Q);
    i=(int)pow(2,p.level)-1-(int)pow(2,p.level-1)+p.order-1;
    if(BiTreeEmpty(T))
    {
        return ERROR;
    }
    i=2*i+1+LR;
    while(k)
    {
        if(T[2*i+1]!=Nil)
        {
            EnterQueue(&Q,2*i+1);
        }
        if(T[2*i+2]!=Nil)
        {
            EnterQueue(&Q,2*i+2);
        }
        T[i]=Nil;
        k=DeleteQueue(&Q,&i);
    }
    return OK;
}

/*訪問結點元素的函數*/ 
int TreeVisitFunc(TElemtype e)
{
    printf(" %c -",e);
}

/*先序遍歷二叉樹的遞歸函數*/ 
int PreTraverse(SqBiTree T,int i)
{
    TreeVisit(T[i]);
    if(T[2*i+1]!=Nil)
    {
        PreTraverse(T,2*i+1);
    }
    if(T[2*i+2]!=Nil)
    {
        PreTraverse(T,2*i+2);
    }
}

/*先序遍歷二叉樹*/ 
int PreOrderTraverse(SqBiTree T,int (*TV) (TElemtype e))
{
    TreeVisit=TV;
    if(BiTreeEmpty(T))
    {
        return ERROR;
    }
    PreTraverse(T,0);
}

/*中序遍歷二叉樹的遞歸函數*/ 
int InTraverse(SqBiTree T,int i)
{
    if(T[2*i+1]!=Nil)
    {
        InTraverse(T,2*i+1);
    }
    TreeVisit(T[i]);
    if(T[2*i+2]!=Nil)
    {
        InTraverse(T,2*i+2);
    }
}

/*中序遍歷二叉樹*/
int InOrderTraverse(SqBiTree T,int (*TV)(TElemtype))
{
    TreeVisit=TV;
    if(BiTreeEmpty(T))
    {
        return ERROR;
    }
    InTraverse(T,0);
}

/*后序遍歷二叉樹的遞歸函數*/
int PostTraverse(SqBiTree T,int i)
{
    if(T[2*i+1]!=Nil)
    {
        PostTraverse(T,2*i+1);
    }
    if(T[2*i+2]!=Nil)
    {
        PostTraverse(T,2*i+2);
    }
    TreeVisit(T[i]);
}

/*后序遍歷二叉樹*/
int PostOrderTraverse(SqBiTree T,int (*TV)(TElemtype))
{
    TreeVisit=TV;
    if(BiTreeEmpty(T))
    {
        return ERROR;
    }
    PostTraverse(T,0);
}

/*打印樹*/ 
void PrintTree(SqBiTree T)
{
    int j,k;
    position p;
    TElemtype e;
    for(j=0;j<BiTreeDepth(T);j++)
    {
        p.level=j+1;
        printf("第%d層:\n",p.level);
        for(k=0;k<pow(2,p.level-1);k++)
        {
            p.order=k+1;
            e=T[(int)pow(2,p.level)-1-(int)pow(2,p.level-1)+p.order-1];
            printf(" %d : %c ",p.order,e);
        }
        printf("\n");
    }
    printf("\n");
}

,最后是主函數,對以上操作的函數調用

/*程序入口函數,對二叉樹及隊列的操作的調用*/ 
int main()
{
    /*
    SqQueue queue;
    InitQueue(&queue);
    QueueEmpty(&queue);
    ClearQueue(&queue);
    QueueEmpty(&queue);
    int length;
    length = GetQueueLength(&queue);
    printf("隊列長度為: %d\n",length);
    if(1==OK)
    {
        printf("-----------------------------\n\n");
    }
    EnterQueue(&queue,1);
    EnterQueue(&queue,2);
    EnterQueue(&queue,3);
    EnterQueue(&queue,4);
    EnterQueue(&queue,5);
    QueueEmpty(&queue);
    length=GetQueueLength(&queue);
    printf("The Length of the Queue is : %d.\n",length);
    QElemType headElem;
    if(GetQueueHead(&queue,&headElem))
    {
        printf("The Head of the Queue is : %d.\n",headElem);
    }
    QueueVisit=QueueVisitFunc;
    QueueTraverse(&queue,QueueVisit);
    printf("銷毀隊列.\n");
    DestroyQueue(&queue);
    */
    
    position p;
    SqBiTree T;
    SqBiTree S;
    int depth;
    int i;
    TElemtype elem;
    InitBiTree(T);
    BiTreeEmpty(T);
    CreateBiTree(T);
    puts(T);
    depth=BiTreeDepth(T);
    printf("The Depth of the tree is %d.\n",depth);
    
    
    GetRoot(T,&elem);
    printf("The Root of the tree is %c.\n",elem);/*

    printf("Please Enter the Level and Order of the Tree:\n");
    scanf("%d",&p.level);
    scanf("%d",&p.order);
    fflush(stdin);
    elem=GetNodeValue(T,p);
    printf("The Node of level %d order %d is : %c \n",p.level,p.order,elem);
    Assign(T,p,'C');*/
    printf("--------------------------------\n\n");
/*
    printf("輸入一個結點的值,我們可以找到其雙親,孩子和兄弟.\n");
    scanf("%c",&elem);
    fflush(stdin);
    printf("%c 's parent is : %c.\n",elem,GetParent(T,elem));
    printf("%c 's left child is : %c.\n",elem,GetLeftChild(T,elem));
    printf("%c 's right child is : %c.\n",elem,GetRightChild(T,elem));
    printf("%c 's left sibling is : %c.\n",elem,GetLeftSibling(T,elem));
    printf("%c 's right sibling is : %c.\n",elem,GetRightSibling(T,elem));*/
    
    printf("----------------------------------\n\n");
    /*
    InitBiTree(S);
    CreateBiTree(S);
    printf("Please enter the node value where you want to insert a child.\n");
    scanf("%c",&elem);
    InsertChild(T,elem,1,S);
    puts(T);
    printf("Please enter the node position you want to delete.\n");
    scanf("%d%d",&p.level,&p.order);
    printf("p.level=%d,p.order=%d\n",p.level,p.order);
    DeleteChild(T,p,0);
    puts(T);
    */
    printf("--------------遍歷二叉樹--------------------\n\n");
    printf("先序遍歷:\n");
    PreOrderTraverse(T,TreeVisitFunc);
    printf("\n中序遍歷:\n");
    InOrderTraverse(T,TreeVisitFunc);
    printf("\n后序遍歷:\n");
    PostOrderTraverse(T,TreeVisitFunc);
    printf("\n");
    printf("--------------打印二叉樹--------------------\n\n");
    PrintTree(T); 
} 

,通過這一次的代碼實踐,更深切的體會到了二叉樹和存儲結構和邏輯結構,以后如何操作一個樹,講數據結構的書,大部分都是理論知識,只要自己實踐了,才能更好的理解.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM