1. 程式人生 > >二叉樹的基本操作及哈夫曼編碼譯碼的實現(實驗二)

二叉樹的基本操作及哈夫曼編碼譯碼的實現(實驗二)

實驗目的:
1.掌握二叉樹的二叉連結串列儲存表示及遍歷操作實現方法。


//完成二叉樹的建立,先序遍歷,中序遍歷,後續遍歷
#include<iostream>
#include<cstring>
using namespace std;
typedef char ElementType;

//二叉樹二叉連結串列結點結構定義:
typedef struct node{
    ElementType Data;
    struct node *Lchild,*Rchild;
}BTnode;

//先前序建立二叉樹
BTnode * PreCreateBt(BTnode* &t){    //指標的引用
char ch; ch=getchar(); if(ch=='#') //輸入#表示這裡建立空的二叉樹,及遍歷演算法的空操作 t=NULL; else{ t=(BTnode *)malloc(sizeof(BTnode)); t->Data=ch; t->Lchild=PreCreateBt(t->Lchild); t->Rchild=PreCreateBt(t->Rchild); } return t; } //先序遍歷 void PreOrderTransverse(BTnode *t){ if
(t==NULL) return ; cout<<t->Data<<" "; //列印根節點,也可以定義其他操作 PreOrderTransverse(t->Lchild); PreOrderTransverse(t->Rchild); } //中序遍歷 void InOrderTransverse(BTnode *t){ if(t==NULL) return ; InOrderTransverse(t->Lchild); cout<<t->Data<<" "
; InOrderTransverse(t->Rchild); } //後序遍歷 void PostOrderTranseverse(BTnode *t){ if(t==NULL) return ; PostOrderTranseverse(t->Lchild); PostOrderTranseverse(t->Rchild); cout<<t->Data<<" "; } int main(){ BTnode *T; PreCreateBt(T); cout<<"建立完成二叉樹!"<<endl<<endl; cout<<"前序遍歷二叉樹"<<endl; PreOrderTransverse(T); cout<<endl; cout<<"中序遍歷二叉樹"<<endl; InOrderTransverse(T); cout<<endl; cout<<"後序遍歷二叉樹"<<endl; PostOrderTranseverse(T); cout<<endl; return 0; }

2.實現二叉樹遍歷運算的應用:求二叉樹葉子結點的個數.結點總數.二叉樹的高度.交換二叉樹的左右子樹。

//求二叉樹總節點的個數和葉子節點的個數
#include<iostream>
using namespace std;
typedef struct node{
    struct node *lchild,*rchild;
    char data;
}BTnode;
BTnode * createBT(BTnode * &T){
    char ch;
    ch=getchar();
    if(ch=='#') T=NULL;
    else{
        T=(BTnode *)malloc(sizeof(BTnode));
        T->data=ch;
        T->lchild=createBT(T->lchild);
        T->rchild=createBT(T->rchild);
    }
    return T;
}

void preTransverse(BTnode* T){
    if(T==NULL) return ;
    cout<<T->data;
    preTransverse(T->lchild);
    preTransverse(T->rchild);
}

//統計總共結點的個數,及為根節點個數加上左子樹結點的個數加上右子樹結點的個數
int countBTnode(BTnode *T){
    if(T==NULL) return 0;
    return 1+countBTnode(T->lchild)+countBTnode(T->rchild);
}

//統計葉子節點的個數
//當樹為空的時候,葉子節點的個數為0;
//當樹的某個節點的左右子樹都為空的時候,表明該節點是葉子節點,返回1
//當樹的某個結點有左子樹或者右子樹的時候,表明這個不是葉子節點,那麼葉子節點的數目等於左子樹葉子節點加上右子樹葉子節點的個數
int countBTleef(BTnode *T){
    int nodes=0;
    if(T==NULL) return 0;
    if(T->lchild==NULL &&T->lchild==NULL) return 1;
    else nodes=countBTleef(T->lchild)+countBTleef(T->rchild);
    return nodes;
}

//得到二叉樹的深度
//二叉樹的深度為左右子樹深度的最大值加一(根節點)
int getDepth(BTnode *T){
    int LD,RD;
    if(T==NULL) return 0;  //如果是空的二叉樹
    else{
        LD=getDepth(T->lchild);
        RD=getDepth(T->rchild);
        return (LD>RD?LD:RD)+1;
    }
}

//交換二叉樹的左右子樹
void changeBT(BTnode * &T){
    BTnode *temp;
    if(T==NULL) return ;
    else{
        temp=T->lchild;
        T->lchild=T->rchild;
        T->rchild=temp;
        changeBT(T->lchild);
        changeBT(T->rchild);
    }
}

int main(){
    BTnode *T;  //指向結點的指標
    createBT(T);
    //先序遍歷
    cout<<"先序遍歷: "<<endl;
    preTransverse(T);
    cout<<endl;
    //統計總結點的個數
    cout<<"總結點的個數:"<<endl;
    cout<<countBTnode(T)<<endl;

    //統計葉子結點的個數
    cout<<"葉子結點的個數 "<<endl;
    cout<<countBTleef(T)<<endl;

    //求解二叉樹的高度
    cout<<"二叉樹的高度: "<<endl;
    cout<<getDepth(T)<<endl;

    //交換二叉樹的左右子樹
    cout<<"交換二叉樹的子樹: "<<endl;
    changeBT(T);
    preTransverse(T);
    cout<<endl;

    return 0;
}

3.查詢data是key的結點,並返回結點的值。並且輸出先序遍歷的第k個結點

#include<iostream>
using namespace std;
typedef struct node{
    char data;
    struct node *lchild,*rchild;
}BTnode;

BTnode * createBT(BTnode * &T){
    char ch;
    ch=getchar();
    if(ch=='#') T=NULL;
    else{
        T=(BTnode *)malloc(sizeof(BTnode));
        T->data=ch;
        T->lchild=createBT(T->lchild);
        T->rchild=createBT(T->rchild);
    }
    return T;
}

//查詢data域等於key的結點是否存在
//查詢到的結果通過q返回
void search(BTnode *p,BTnode * &q,char key){
    if(p!=NULL){
        if(p->data==key)
            q=p;
        else{
            search(p->lchild,q,key);    //左子樹查詢
            if(q==NULL) //剪枝操作,如果左子樹找不到再找右子樹
                search(p->rchild,q,key);    //右子樹查詢
        }
    }
}

//輸出先序遍歷第k個結點的值
int n=0;
void searchpre(BTnode *p,int k){
    if(p!=NULL){
        n++;
        if(n==k){
            cout<<p->data;
        }
        else{
            searchpre(p->lchild,k);
            searchpre(p->rchild,k);
        }
    }
}
int main(){
    BTnode *p,*q;
    char key;
    int k;
    createBT(p);
    cout<<"輸入查詢的字元: "<<endl;
    cin>>key;
    search(p,q,key);
    cout<<q->data<<endl;
    cout<<"請輸入先序遍歷的第k個結點的k的值: "<<endl;
    cin>>k;
    searchpre(p,k);
    return 0;
}

4.掌握二叉樹的應用,哈夫曼編碼的實現。

程式碼不對。。。。

//哈夫曼樹的建立,哈夫曼編碼以及解碼的實現
#include<iostream>
#include<cstring>
#define maxn 100000
using namespace std;
typedef int ElemType;
typedef struct{
    ElemType data;  //資料域
    int w;          //結點的權值
    int parent,lchild,rchild; 
}HFMTNode;

//建樹,N是葉子結點的個數 
void createHFMTNode(HFMTNode H[],int N){
    int i,j,k,lmin,rmin;    //lmin和rmin為最小權值兩個結點位置
    int min1,min2;          //min1,min2為最小權值的兩個結點
    for(int i=1;i<=2*N;i++)
        H[i].parent=H[i].lchild=H[i].rchild=-1; 
    for(int i=N+1;i<2*N;i++){
        min1=min2=maxn;
        lmin=rmin=-1;
        for(int k=1;k<=i-1;k++)
            if(H[k].parent==-1)     //只在未構造的二叉樹結點進行
            {
                if(H[k].w<min1){
                    min2=min1; rmin=lmin;
                    min1=H[k].w;lmin=k;
                }   
            } 
            else if(H[k].w<min2){
                min2=H[k].w; rmin=k;
            }

            H[lmin].parent=i;
            H[rmin].parent=i;
            H[i].w=H[lmin].w+H[rmin].w;
            H[i].lchild=lmin; H[i].rchild=rmin;
    }
} 

void print(HFMTNode T[],int N){
    for(int i=0;i<2*N;i++)
        cout<<T[i].data<<endl;
}

int main(){
    HFMTNode *T;
    createHFMTNode(T,10);
    print(T,10); 
    return 0;
}