1. 程式人生 > >二叉樹的順序儲存和基本操作

二叉樹的順序儲存和基本操作

一、二叉樹的定義:

二叉樹是n個結點的有限集合,當n=0時稱為空樹,否則:(1)有且只有一個特殊的被稱為樹的根結點;(2)若n>1時,其餘的結點被分為兩個互不相交的子集,稱為左右子樹,並且左右子樹都是二叉樹;可以看出二叉樹的定義是遞迴的。

二、二叉樹的性質:

(1)在非空二叉樹上,第i層至多有2^(i-1)個結點;

(2)深度為k的二叉樹至多有2^k-1個結點;

(3)對任何一個二叉樹,若其葉子結點數為n0,度為2的節點數為n2,則n0=n2+1;

滿二叉樹:一課深度為k且有2^k-1個結點的二叉樹。

完全二叉樹:如果深度為k,有n個結點的二叉樹,當且僅當其每一個結點都與深度為k的滿二叉樹中編號從1到n的結點一一對應,該二叉樹稱為完全二叉樹。2^(k-1)<=n<=2^k-1

(4)n個結點的完全二叉樹的深度k=[log2 n]+1,這裡這個符號[x]表示小於等於x的整數;(證明過程,對上述n的不等式取對數)

(5)若對一棵有n個結點的完全二叉樹(深度為└㏒2n┘+1)的結點按層(從第1層到第㏒2n +1層)序自左至右進行編號,則對於編號為i(1≦i≦n)的結點:

1、若i=1:則結點i是二叉樹的根,無雙親結點;否則,若i>1,則其雙親結點編號是 [i/2]
2、 如果2i>n:則結點i為葉子結點,無左孩子;否則,其左孩子結點編號是2i。
3、 如果2i+1>n:則結點i無右孩子;否則,其右孩子結點編號是2i+1。 

三、二叉樹的儲存結構

1、順序儲存結構:

typedef char ElemType;
typedef struct stree
{
    ElemType bitTree[MAX_SIZE];
    int pointer;   //number of points
}STree;
//init
void STree_Init(STree &T)
{
    for(int i=0;i<MAX_SIZE;++i)
        T.bitTree[i]='0';
    T.pointer=0;
}
//insert root
int STree_insert_Root(STree &T,ElemType e)
{
    T.bitTree[1]=e;
    T.pointer++;
    return 1;
}
//insert left
int STree_insert_Left(STree &T,int i,ElemType e)
{
    if(i>=MAX_SIZE || i<0)
    {
        cout<<"argument is false!"<<endl;
        return -1;
    }
    T.bitTree[2*(i+1)]=e;
    T.pointer++;
    return 1;
}
//insert right
int STree_insert_Right(STree &T,int i,ElemType e)
{
    if(i>=MAX_SIZE || i<0)
    {
        cout<<"argument is false!"<<endl;
        return -1;
    }
    T.bitTree[2*(i+1)+1]=e;
    T.pointer++;
    return 1;
}
//
int STree_delete_Left(STree &T,int i,ElemType *x_left)
{
    if(i>=MAX_SIZE || i<0)
    {
        cout<<"argument is false!"<<endl;
        return -1;
    }
    *x_left=T.bitTree[2*(i+1)];
    T.pointer--;
    return 1;
}
//
int STree_delete_Right(STree &T,int i,ElemType *x_right)
{
    if(i>=MAX_SIZE || i<0)
    {
        cout<<"argument is false!"<<endl;
        return -1;
    }
    *x_right=T.bitTree[2*(i+1)+1];
    T.pointer--;
    return 1;
}
int STree_delete_Root(STree &T,ElemType *x_root)
{
    *x_root=T.bitTree[1];
    T.pointer--;
    return 1;
}
//
bool STree_empty(STree &T)
{
    return T.pointer==0;
}

2、三種遍歷方式:前序、中序、後序

遞迴形式的遍歷方式

//前序遍歷
void STree_Traver_1(STree &T,int i)
{
        cout<<T.bitTree[i]<<" ";
        if(T.bitTree[2*i]!='0')
            STree_Traver_1(T,2*i);
        if(T.bitTree[2*i+1]!='0')
            STree_Traver_1(T,2*i+1);
}
//中序遍歷
void STree_Traver_2(STree &T,int i)
{
    if(T.bitTree[2*i]!='0')
        STree_Traver_2(T,2*i);
    cout<<T.bitTree[i]<<" ";
    if(T.bitTree[2*i+1]!='0')
        STree_Traver_2(T,2*i+1);
}
//後序遍歷
void STree_Traver_3(STree &T,int i)
{
    if(T.bitTree[2*i]!='0')
        STree_Traver_3(T,2*i);
    if(T.bitTree[2*i+1]!='0')
        STree_Traver_3(T,2*i+1);
    cout<<T.bitTree[i]<<" ";
}
非遞迴形式的遍歷方式
//前序遍歷
int STree_Traver_1_no(STree &T)
{
    stack<int> s({'0'});
    int p=1,q;
    if(STree_empty(T))
    {
        cout<<"tree is empty!"<<endl;
        return -1;
    }
do{
    cout<<T.bitTree[p]<<" ";
    q=p*2+1;
    if(T.bitTree[q]!='0')
        s.push(q);
    p=p*2;
    if(T.bitTree[p]=='0') //到樹的底部了,回退
    {
        p=s.top();
        s.pop();
    }
 }while(T.bitTree[p]!='0');

    return 1;
}
//中序遍歷
int STree_Traver_2_no(STree &T)
{
    stack<int> s;
    int p=1;
    int b=1;
    /*
    if(STree_empty(T))
    {
        cout<<"tree is empty!"<<endl;
        return -1;
    }
    */
    do
    {
        while(T.bitTree[p]!='0')
        {
            s.push(p);
            p=p*2;
        }
        if(s.empty()) b=0;
        else {
        p=s.top();
        s.pop();
        cout<<T.bitTree[p]<<" ";
        p=p*2+1;
        }
    }while(b!=0);
    return 1;
}
//後序遍歷
int STree_Traver_3_no(STree &T)
{
    int p=1;
    int b=1,top=0;
    int s1[20],s2[20];
    do
    {
        while(T.bitTree[p]!='0')
        {
            s1[++top]=p;
            s2[top]=0;
            p=p*2;
        }
        if(top==0) b=0;
        else if(s2[top]==0)
        {
            p=s1[top]*2+1;
            s2[top]=1;
        }
        else
        {
            p=s1[top];
            top--;
            cout<<T.bitTree[p]<<" ";
            T.bitTree[p]='0';
        }
    }while(b!=0);
    return 1;
}
關於二叉樹的順序儲存結構和遞迴遍歷方式以及非遞迴遍歷方式,上邊全部給出了實現程式碼,下一篇給出鏈式儲存結構及其遍歷方式的程式碼。