數據結構實驗報告(三)


實驗報告3 樹
1)順序二叉樹

#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <string>
#include <string.h>
#include <math.h>
#define MAXSIZE 20
//順序二叉樹
using namespace std;
typedef int Elemtype;
typedef struct SqBinode
{
    Elemtype data[MAXSIZE];
} SqBinode,SqBiTree;
typedef struct
{
    int level;//第幾層
    int order;//本層序號,(level,order)類似於(i,j)
} position;
void initBiTree(SqBiTree &bt)
{
    for (int i=0; i<MAXSIZE; i++)
    {
        bt.data[i]=NULL;
    }
}
int createBiTree(SqBiTree &bt)
{
    cout<<"無節點處請輸入0,輸入完畢請輸入-999"<<endl;
    int i=0,n;
    cin>>n;
    while (n!=-999&&i<=MAXSIZE)
    {
        bt.data[i]=n;
        i++;
        if (i!=0&&bt.data[(i+1)/2-1]==NULL&&bt.data[i]!=NULL)
        {
            cout<<"存在雙親為空且自身為空且不為根節點的點!"<<endl;
            return 0;
        }
        cin>>n;

    }

    if (i>MAXSIZE)
        return 0;
    return 1;
}
int BiTreeEmpty(SqBiTree bt)
{
    if (bt.data[0]==NULL)
        return 1;
    else
        return 0;
}
int BiTreeDepth(SqBiTree bt)
{
    int n=0,i=0;//N為節點個數
   for (i=0;i<MAXSIZE-1;i++)
    {
        if (bt.data[i]!=NULL)
            n++;

    }
    int k=0;
    do
    {
        k++;
    }
    while (pow(2,k-1)<=n);
    return k-1;
}

Elemtype Root(SqBiTree bt)
{
    if (bt.data[0])
        return bt.data[0];
    else
        return 0;
}
void initPosition(position &p,int a,int b)
{
    p.level=a;
    p.order=b;
}
void Value(SqBiTree bt,Elemtype &e,position p)
{
    //根據E的位置P找到它
    int n=pow(2,p.level-1)+p.order-2;
    e=bt.data[n];
}

void Assign(SqBiTree &bt,position &p,Elemtype e)
{
    int x=pow(2,p.level-1)+p.order-2;
    bt.data[x]=e;
}

void print(SqBiTree bt)
{
    int i,j,k=0;
    for (i=1;i<=BiTreeDepth(bt); i++)
    {
        cout<<""<<i<<"";
        for (j=1; j<=pow(2,i-1); j++)
        {
            if (bt.data[k]!=NULL)
                cout<<"("<<j<<","<<bt.data[k]<<") ";
            k++;
        }
        cout<<endl;
    }
}
void valueP(int i,int j,position &p)
{
    p.level=i;
    p.order=j;
}

int Parent(SqBiTree &bt,Elemtype e)
{
    if (bt.data[0]==e)
        return NULL;
    int i=1;
    while (bt.data[i]!=e && i<=MAXSIZE-1) i++;
    return bt.data[(i+1)/2-1];
}
int LeftChild(SqBiTree &bt,Elemtype e)
{
//1.葉子結點無左孩子 2.非葉子結點的左孩子是2*i
    int i=0;
    while (bt.data[i]!=e && i<=MAXSIZE-1) i++;
//循環停止時應當是找到了值為E的結點,但不知道是葉子節點還是非葉子
    if (bt.data[2*i+1]!=NULL)
        return bt.data[2*i+1];
    else
        return NULL;
}
int RightChild(SqBiTree &bt,Elemtype e)
{
//1.葉子結點無左孩子 2.非葉子結點的左孩子是2*i
    int i=0;
    while (bt.data[i]!=e && i<=MAXSIZE-1) i++;
//循環停止時應當是找到了值為E的結點,但不知道是葉子節點還是非葉子
    if (bt.data[2*i+2]!=NULL)
        return bt.data[2*i+2];
    else
        return NULL;
}

int LeftSibling(SqBiTree &bt,Elemtype e)
{
    int i=0;
    if (!bt.data[0]) return NULL;//空樹不用查找
    if (bt.data[0]==e) return NULL;//根節點沒有左兄弟
    while (bt.data[i]!=e && i<=MAXSIZE-1) i++;
//1.左兄弟為-1 2. 為最左側的一列,沒有左兄弟
    if (i%2==0) return bt.data[i-1];//序號為偶節點才有左兄弟
    else return NULL;
}
int RightSibling(SqBiTree &bt,Elemtype e)
{
    int i=0;
    if (!bt.data[0]) return NULL;//空樹不用查找
    if (bt.data[0]==e) return NULL;//根節點沒有左兄弟
    while (bt.data[i]!=e && i<=MAXSIZE-1) i++;
//1.左兄弟為-1 2. 為最左側的一列,沒有左兄弟
    if (i%2!=0) return bt.data[i+1];//序號為偶節點才有左兄弟
    else return NULL;
}

void Move(SqBiTree &bt,int k,SqBiTree &q,int g)
{
    if (bt.data[2*k+1]!=NULL) //左孩子不空
        Move(bt,2*k+1,q,2*g+1);
    if (bt.data[2*k+2]!=NULL)//右孩子不空
        Move(bt,2*k+2,q,2*g+2);
    q.data[g]=bt.data[k];
    bt.data[k]=NULL;
}

int InsertChild(SqBiTree &bt,Elemtype e,int LR,SqBiTree &c)
{
//1.找到E所在結點的序號
    int i =0;
    while (bt.data[i]!=e &&i<=MAXSIZE-1 ) i++;
    int k=2*i+LR+1;//得到E結點的LR孩子的序號
    if (bt.data[k])//如果LR結點存在,需要轉移到C的右子樹,也就是K結點的右子樹
        Move(bt,k,bt,2*k+2);
    Move(c,0,bt,k);
    return 1;
}
void del(SqBiTree &bt ,int k)
{
    //刪除bt的k結點作為根結點的非空樹
    if (!bt.data[2*k+1])//左子樹非空
        del(bt,2*k+1);
    if (!bt.data[2*k+2])
        del(bt,2*k+2);
    bt.data[k]=NULL;

}
int DeleteChild(SqBiTree &bt,Elemtype e,int lr)
{
    //刪除e元素對應的左或右子樹
    //1 find the number of e
    int i=0;
    while (bt.data[i]!=e &&i<=MAXSIZE-1) i++;
    //2 找到要刪除的左或右子樹
    int k =2*i+1+lr;
    if (bt.data[k]!=NULL) //非空則刪除
    del(bt,k);
    else
    {
        cout<<"不存在左或右子樹,無法刪除"<<endl;
        return 0;
    }
}
void PreOrder(SqBiTree &bt ,int i)
{
    cout<<bt.data[i]<<" ";
    if (bt.data[2*i+1])//左子樹非空
    PreOrder(bt,2*i+1);
    if (bt.data[2*i+2])//右子樹非空
    PreOrder(bt,2*i+2);

}
int PreOrderTraverse(SqBiTree &bt)
{
    int i=0;
    if (bt.data[i])
    PreOrder(bt,i);//遍歷左子樹
    else
    {
        cout<<"此樹為空,不能遍歷"<<endl;
        return 0;
    }
    return 1;
}
void InOrder(SqBiTree &bt ,int i)
{

    if (bt.data[2*i+1])//左子樹非空
    PreOrder(bt,2*i+1);
    cout<<bt.data[i]<<" ";
    if (bt.data[2*i+2])//右子樹非空
    PreOrder(bt,2*i+2);

}
int InOrderTraverse(SqBiTree &bt)
{
    int i=0;
    if (bt.data[i])
    InOrder(bt,i);//遍歷左子樹
    else
    {
        cout<<"此樹為空,不能遍歷"<<endl;
        return 0;
    }
    return 1;
}
void PostOrder(SqBiTree &bt ,int i)
{

    if (bt.data[2*i+1])//左子樹非空
    PostOrder(bt,2*i+1);
    if (bt.data[2*i+2])//右子樹非空
    PostOrder(bt,2*i+2);
     cout<<bt.data[i]<<" ";

}
int PostOrderTraverse(SqBiTree &bt)
{
    int i=0;
    if (bt.data[i])
    PostOrder(bt,i);//遍歷左子樹
    else
    {
        cout<<"此樹為空,不能遍歷"<<endl;
        return 0;
    }
    return 1;
}
int main()
{
    cout<<"---順序二叉樹的基本操作實現 twomeng---"<<endl;
    cout<<"--------------------------------------"<<endl;
    cout<<"1 InsertChild()"<<endl;
    cout<<"2 DeleteChild()"<<endl;
    cout<<"3 PreOrderTraverse()"<<endl;
    cout<<"4 InOrderTraverse()"<<endl;
    cout<<"5 PostOrderTraverse()"<<endl;
    cout<<"6 Parent()"<<endl;
    cout<<"7 LeftChild()"<<endl;
    cout<<"8 RightChild()"<<endl;
    cout<<"9 leftSibling()"<<endl;
    cout<<"10 RightSibling()"<<endl;
    cout<<"11 Root()"<<endl;
    cout<<"12 Value()"<<endl;
    cout<<"13 Assign()"<<endl;
    cout<<"--------------------------------------"<<endl;
ll1:cout<<"請輸入您選擇的函數序號:)"<<endl;
    int number;
    cin>>number;
    SqBiTree bt;
    initBiTree(bt);
    createBiTree(bt);//創建一個可以公用的二叉樹bt
    Elemtype e;position p;
    switch(number){
case 1:
    SqBiTree c;
    initBiTree(c);
    createBiTree(c);
    InsertChild(bt,3,1,c);
    print(bt);
    break;
case 2:
    DeleteChild(bt,3,1);
    print(bt);
    break;
case 3:
    PreOrderTraverse(bt);
    break;
case 4:
    InOrderTraverse(bt);
    break;
case 5:
    PostOrderTraverse(bt);
    break;
case 6:
    cout<<"輸入E的值"<<endl;
    cin>>e;
    cout<<Parent(bt,e);
    break;
case 7:
    cout<<"輸入E的值"<<endl;
    cin>>e;
    cout<<LeftChild(bt,e);
    break;
case 8:
    cout<<"輸入E的值"<<endl;
    cin>>e;
    cout<<RightChild(bt,e);
    break;
case 9:
    cout<<"輸入E的值"<<endl;
    cin>>e;
    cout<<LeftSibling(bt,e);
    break;
case 10:
    cout<<"輸入E的值"<<endl;
    cin>>e;
    cout<<RightSibling(bt,e);
    break;
case 11:
    cout<<Root(bt);
    break;
case 12:
    cout<<"請輸入P的位置(level,order)"<<endl;
    int a,b;
    cin>>a>>b;
    initPosition(p,a,b);
    Value(bt,e,p);
    cout<<e<<endl;
    break;
case 13:
    cout<<"請輸入P的位置(level,order)和E的值"<<endl;
    cin>>a>>b>>e;
    initPosition(p,a,b);
    Assign(bt,p,e);
    print(bt);
    break;
    }

    cout<<"您是否想要繼續調用函數?yes/no"<<endl;
    string s;cin>>s;
    if (!s.compare("yes"))
    goto ll1;
    else
    return 0;
}

 

鏈式二叉樹
1.實驗內容
1.輸入字符序列,建立二叉鏈表。 1
2.中序遍歷二叉樹:遞歸算法。3
3.中序遍歷二叉樹:非遞歸算法。(最好也能實現先序,后序非遞歸算法)4
4.求二叉樹的高度 。1
5.求二叉樹的葉子個數。1
*6.將二叉鏈表視為森林的孩子兄弟鏈表,計算森林中葉子個數。1
*7.建立中序線索二叉樹,並實現中序遍歷。1
8.借助隊列實現二叉樹的層次遍歷。1
9.在主函數中設計一個簡單的菜單,分別調試上述算法。1
*10.綜合訓練:為N個權值設計哈夫曼編碼。

#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <string>
#include <string.h>
#include <math.h>
#define MAXSIZE 10
//鏈式二叉樹
using namespace std;
typedef char Elemtype;
typedef struct BiTNode{
Elemtype data;
struct BiTNode *left,*right;
}BiTNode,*BiTree;

void InitBiTree(BiTree &bt)
{
    bt=NULL;//構造空的二叉樹
}
void CreateBiTree(BiTree &bt)
{
    Elemtype e;
    scanf("%c",&e);
    if (e==' ')
    {
        bt=NULL;//如果輸入空格則將該結點置空
    }
    else
    {
        bt=(BiTree)malloc(sizeof(BiTNode));
        bt->data=e;
        CreateBiTree(bt->left);
        CreateBiTree(bt->right);
    }
}
void PreOrderTraverse(BiTree &bt)
{
    if (bt!=NULL)
    {
    printf("%c",bt->data);
    PreOrderTraverse(bt->left);
    PreOrderTraverse(bt->right);
    }

}

void InOrderTraverse(BiTree &bt)
{
    if (bt)//如果是空則不用遍歷左右子樹,如果不空則遍歷
    {
        InOrderTraverse(bt->left);
        printf("%c",bt->data);
        InOrderTraverse(bt->right);
    }
}
void PostOrderTraverse(BiTree &bt )
{
    if (bt)
    {
        PostOrderTraverse(bt->left);
        PostOrderTraverse(bt->right);
        printf("%c",bt->data);
    }
}
void LevelOrderTraverse(BiTree &bt)
{
    BiTree q[MAXSIZE];//指針數組
    int front,rear;
    //初始化隊列
    front=rear=-1;
    if (bt)
    {
        rear=(rear+1)%MAXSIZE;
        q[rear]=bt;//安置根節點
        //不斷循環,直到隊空為止
        while (front!=rear)
        {
            //如果隊不空,隊頭出隊
            front=(front+1)%MAXSIZE;
            printf("%c",q[front]->data);
            //左右孩子不空則入隊
            if (q[front]->left)
            {
                rear=(rear+1)%MAXSIZE;
                q[rear]=q[front]->left;//安置根節點
            }
             if (q[front]->right)
            {
                rear=(rear+1)%MAXSIZE;
                q[rear]=q[front]->right;//安置根節點
            }
        }


    }
}
int BiTreeEmpty(BiTree &bt)
{
    if (!bt)
    return 1;
}

int BiTreeDepth(BiTree &bt)
{
    int depth=0;
    int depthL,depthR;
    if (!bt)
    depth=0;
    else
    {
        depthL=BiTreeDepth(bt->left);
        depthR=BiTreeDepth(bt->right);
        depth=1+(depthL>depthR?depthL:depthR);

    }
    return depth;
}
Elemtype Root (BiTree &bt)
{
    if (bt)
    {
        return bt->data;
    }
    else
    return 0;
}
Elemtype Value(BiTree &p)
{
    //P是二叉樹中某個節點
    return p->data;
}
void Assign(BiTree &bt,Elemtype e)
{
    bt->data=e;
}
Elemtype Parent(BiTree &bt,Elemtype e)
{
    //e為二叉樹bt中的某個節點,輸出他的雙親
    BiTree q[MAXSIZE],p;
    int rear,front;
    rear=front =-1 ;

    if (bt)
    {
        rear=(rear+1)%MAXSIZE;
        q[rear]=bt;//根節點入隊

        while (rear!=front)
        {
            //如果隊不空則隊頭出隊
            front=(front+1)%MAXSIZE;
            p=q[front];
            if (p && p->left->data ==e || p && p->right->data == e )
            {
                //如果P本身不空並且有一個孩子等於E,則返回該雙親節點的值
                return p->data;
            }
            //說明這次沒有找到和E相等的節點,則把左孩子和右孩子送入隊列
            if (p->left)
            {
              rear=(rear+1)%MAXSIZE;
              q[rear]=p->left;
            }
            if (p->right)
            {
              rear=(rear+1)%MAXSIZE;
              q[rear]=p->right;
            }
        }
    }
}
BiTree findE(BiTree &bt,Elemtype e)
{
    BiTree q[MAXSIZE],p;
    int rear,front;
    rear=front=-1;
    if (bt)
    {
        rear=(rear+1)%MAXSIZE;
        q[rear]=bt;//根入隊

        while (front!=rear)
        {
            front=(front+1)%MAXSIZE;
            p=q[front];//取出隊頭元素
            if (p->data == e)
            {
                return p;
            }
            if (p->left)
            {
               rear=(rear+1)%MAXSIZE;
               q[rear]=p->left;//left child enqueue
            }
            if (p->right)
            {
               rear=(rear+1)%MAXSIZE;
               q[rear]=p->right;//left child enqueue
            }
        }
    }
}
Elemtype LeftChild( BiTree &bt,Elemtype e)
{
    //找到指向E的指針
    BiTree p=findE(bt,e);
    if (p &&p->left )
    {//P不為空並且左孩子不為空
        return p->left->data;
    }
    else
    return 0;

}
Elemtype RightChild( BiTree &bt,Elemtype e)
{
    //找到指向E的指針
    BiTree p=findE(bt,e);
    if (p &&p->right )
    {//P不為空並且左孩子不為空
        return p->right->data;
    }
    else
    return 0;

}
BiTree findP(BiTree &bt,Elemtype e)
{
    //e為二叉樹bt中的某個節點,輸出他的雙親
    BiTree q[MAXSIZE],p;
    int rear,front;
    rear=front =-1 ;

    if (bt)
    {
        rear=(rear+1)%MAXSIZE;
        q[rear]=bt;//根節點入隊

        while (rear!=front)
        {
            //如果隊不空則隊頭出隊
            front=(front+1)%MAXSIZE;
            p=q[front];
            if (p && p->left->data ==e || p && p->right->data == e )
            {
                //如果P本身不空並且有一個孩子等於E,則返回該雙親節點的值
                return p;
            }
            //說明這次沒有找到和E相等的節點,則把左孩子和右孩子送入隊列
            if (p->left)
            {
              rear=(rear+1)%MAXSIZE;
              q[rear]=p->left;
            }
            if (p->right)
            {
              rear=(rear+1)%MAXSIZE;
              q[rear]=p->right;
            }
        }
    }
}
Elemtype LeftSibling(BiTree &bt,Elemtype e)
{
    BiTree parent = findP(bt,e);//找到E元素的雙親指針

    if (parent->left)
    {
        return parent->left->data;
    }
}

Elemtype RightSibling(BiTree &bt,Elemtype e)
{
    BiTree parent = findP(bt,e);//找到E元素的雙親指針
    if (parent->right)
    {
        return parent->right->data;
    }
}
int  InsertChild(BiTree &p ,int lr,BiTree &c)
{//插入更簡單了!!
    if (p)
    {
        if (lr==0)//把C移到P的左子樹上
        {
            c->right=p->left;
            p->left=c;
        }else
        {
          c->right=p->right;
          p->right=c;
        }
        return 1;
    }
    else
    return 0;//P為空
}
void clearBiTree(BiTree &bt)
{
    //同樣用遞歸!
    if (bt)
    {
        if (bt->left)
            clearBiTree(bt->left);
        if (bt->right)
            clearBiTree(bt->right);
        free(bt);
        bt=NULL;
    }
}
void  DeleteChild(BiTree &p,int LR)
{
    // 初始條件: 二叉樹T存在,p指向T中某個結點,LR為0或1
   // 操作結果: 根據LR為0或1,刪除T中p所指結點的左或右子樹
   if (p)
   {
     if (LR == 1)
   {
       clearBiTree(p->left);
   }else
   {
       clearBiTree(p->right);
   }
   }

}

//非遞歸實現pre/in/post 遍歷二叉樹
//使用棧實現中序遍歷


typedef BiTree Elemtype1;
typedef struct {
Elemtype1 elem[MAXSIZE];
int top;
}SeqStack;
void initSeqStack(SeqStack &s){
s.top=-1;
}
int stackEmpty(SeqStack &s){
if (s.top==-1)
return 1;
return 0;//或者返回 表達式的真值return s.top==-1;
}
int push(SeqStack &s,Elemtype1 e){
if (s.top>=MAXSIZE-1)
return 0;
else {
s.top++;
s.elem[s.top]=e;
return 1;
}
}
int pop(SeqStack &s,Elemtype1 &e){
if (s.top==-1)
return 0;
else {
e=s.elem[s.top];
s.top--;
return 1;
}
}
int gettop(SeqStack &s,Elemtype1 &e){
if (s.top==-1)
return 0;
else {
e=s.elem[s.top];
return 1;
}
}
//中序遍歷非遞歸算法
void InOrderTraverse2(BiTree &bt)
{
    //精髓是把每個結點的地址存入棧中,通過push & pop實現過程
    SeqStack s;
    initSeqStack(s);
    BiTree p=bt;
    while (p!=NULL || !stackEmpty(s))
    {
        //當且僅當兩者都空時結束循環
        if (p)
        {
            push(s,p);
            p=p->left;
        }
        else
        {
            pop(s,p);//彈回根節點
            printf("%c ",p->data);//第二次回到根節點時才打印輸出
            p=p->right;

        }
    }

}

//先序遍歷非遞歸算法
void PreOrderTraverse2(BiTree p)
{
    //這里不加&即為形參,便不用定義新的變量作為移動的指針了
    SeqStack s;
    initSeqStack(s);
    do
    {
        if (p)
        {
          printf("%c ",p->data);
          push(s,p);
          p=p->left;
        }
        else
        {
        pop(s,p);
        p=p->right;
        }

    }while (p || !stackEmpty(s));

}

//后序遍歷非遞歸算法
void PostOrderTraverse2(BiTree p)
{
    struct
    {
        BiTree pp;//pointer
        int tag;//標記位
    }s[MAXSIZE];//定義一個結構體數組,即為一個棧s
//這里struct之前不能加typedef ,因為s[]是結構體數組而不是別名

    int top=0;//棧頂指針

    while ( p || top>0)
    {
        while (p)//一直走到最左邊
        {
            top++;
            s[top].pp=p;
            s[top].tag=0;
            p=p->left;
        }
        if (top>0)
        {
            if (s[top].tag == 0)
            {
                //如果棧頂元素標志位為0,即為第二次遇到該結點元素
                s[top].tag=1;
                p=s[top].pp;
                p=p->right;//繼續向右孩子深入
            }
            else
            {
                p=s[top].pp;
                printf("%c ",p->data);//如果是第二次遇到該節點則輸出
                top--;
                p=NULL;//不用往深處走了,直接退棧繼續循環
            }
        }
    }
}
//找到葉子結點個數,左右孩子都空
int findleaf(BiTree p,int &count1)
{

    if (p)
    {
        if ( !p->left &&!p->right)
            count1++;
        findleaf(p->left,count1);
        findleaf(p->right,count1);
    }
}
int findrightleaf(BiTree p,int &count1)
{

    if (p)
    {
        if (!p->right)
            count1++;
        findleaf(p->left,count1);
        findleaf(p->right,count1);
    }
}
void PreOrderfindall(BiTree &bt,int &count2)
{
    if (bt!=NULL)
    {
    count2++;
    PreOrderfindall(bt->left,count2);
    PreOrderfindall(bt->right,count2);
    }

}

int findleafinforest(BiTree &bt)
{
    //假設bt代表一個森林,求森林中葉子的個數
    //利用理論:假設森林中有N個非終端結點,則二叉樹中右指針域為空的結點個數為N+1
    if (bt)
    {
        int count1 = 0;
        findrightleaf(bt,count1);
        //count即為二叉樹中右指針域為空的結點的個數
        int count2=0;
        PreOrderfindall(bt,count2);
        //count2即為二叉樹中所有節點的個數,也就是森林總結點個數
        return (count2-count1+1);
    }
    else
        return 0;
}
//建立中序線索二叉樹並遍歷
typedef enum PointerTag {link=0,thread=1};//link=0 指針,thread=1 線索
typedef struct BithrNode{
Elemtype data;
struct BithrNode *left,*right;
PointerTag ltag,rtag;
}BithrNode,*BithrTree;

int InOrderThreading(BithrTree &thrt,BithrTree bt)
{
    void Inthreading(BithrTree &p,BithrTree &pre);
    //將普通二叉樹線索化成thrt
    //1.建立頭結點
    thrt = (BithrTree)malloc(sizeof(BithrNode));
    BithrTree pre;
    thrt->right=thrt;
    thrt->ltag=link;
    thrt->rtag=thread;
    if (!bt)
        thrt->left=thrt;
    else
    {
        thrt->left = bt;
        pre=thrt;//前驅指針指向頭結點
        Inthreading(bt,pre);
        //線索化二叉樹
        pre->right=thrt;
        pre->rtag=thread;
        thrt->right=pre;
        //線索化最后pre指向樹中最后一個結點,進行最后的處理:連接樹中最后一個結點與頭結點,形成循環的線索樹

    }
}
void Inthreading(BithrTree &p,BithrTree &pre)
{
    if (p)
    {
        Inthreading(p->left,pre);
        if (!p->left)//P的左孩子為空
        {
            p->ltag=thread;
            p->left=pre;
        }
        if (!pre->right)//Pre的右孩子為空
        {
           pre->rtag=thread;
           pre->right=p;
        }
        pre=p;
        Inthreading(p->right,pre);
    }
}
//遍歷線索二叉樹
int InOrderTraverseThrtree(BithrTree &thrt)
{
    BithrTree p=thrt->left;
    while (p != thrt)
    {
        //線索樹不為空時
        while(p && p->ltag !=thread)
        {
            p=p->left;
        }
        printf("%c",p->data);
        while(p->rtag == thread && p->right != thrt)
        {
            //如果p->right==T,則不用繼續往右走
            p=p->right;
            printf("%c",p->data);
        }
        p=p->right;//沒有右線索,只有右孩子

    }
}
void CreateBithrTree(BithrTree &bt)
{
    Elemtype e;
    scanf("%c",&e);
    if (e==' ')
    {
        bt=NULL;//如果輸入空格則將該結點置空
    }
    else
    {
        bt=(BithrTree)malloc(sizeof(BithrNode));
        bt->data=e;
        CreateBithrTree(bt->left);
        CreateBithrTree(bt->right);
    }
}
int main()
{

    cout<<"---二叉樹的基本操作實現 twomeng---"<<endl;
    cout<<"--------------------------------------"<<endl;
    cout<<"1 InsertChild()"<<endl;
    cout<<"2 DeleteChild()"<<endl;
    cout<<"3 PreOrderTraverse()"<<endl;
    cout<<"4 InOrderTraverse()"<<endl;
    cout<<"5 PostOrderTraverse()"<<endl;
    cout<<"6 Parent()"<<endl;
    cout<<"7 LeftChild()"<<endl;
    cout<<"8 RightChild()"<<endl;
    cout<<"9 leftSibling()"<<endl;
    cout<<"10 RightSibling()"<<endl;
    cout<<"11 Root()"<<endl;
    cout<<"12 Value()"<<endl;
    cout<<"13 Assign()"<<endl;
    cout<<"14 LevelOrderTraverse()"<<endl;
    cout<<"15 BiTreeDepth()"<<endl;
    cout<<"16 findleaf()"<<endl;
    cout<<"17 PreOrderTraverse2()"<<endl;
    cout<<"18 InOrderTraverse2()"<<endl;
    cout<<"19 PostOrderTraverse2()"<<endl;
    cout<<"20 findleafinforest()"<<endl;
    cout<<"21 線索化二叉樹並中序遍歷輸出"<<endl;
    cout<<"--------------------------------------"<<endl;

ll1:cout<<"請輸入您選擇的函數序號:)"<<endl;
    int number;
    cin>>number;


    BiTree bt,p;
    InitBiTree(bt);
    Elemtype e;int count3 = 0;
    cout<<"請按照先序順序輸入一棵樹!沒有結點的地方請輸入空格"<<endl;
    fflush(stdin);
    CreateBiTree(bt);//創建一個可以公用的二叉樹bt;
    switch(number)
{
case 1:
    PreOrderTraverse(bt);
    BiTree c;
    InitBiTree(c);
    cout<<"請按照先序順序輸入一棵Insert樹!沒有結點的地方請輸入空格"<<endl;
    fflush(stdin);
    CreateBiTree(c);
    LevelOrderTraverse(c);
    cout<<"輸入完畢!"<<endl;
    cout<<"如果您想插入到左子樹,輸入0;如果您想插入到右子樹,輸入1 "<<endl;
    int x;cin>>x;
    InsertChild(bt,x,c);
    PreOrderTraverse(bt);
    break;
case 2:
    PreOrderTraverse(bt);
    cout<<endl;
    cout<<"刪除左子樹,請輸入1;刪除右子樹,請輸入0"<<endl;
    cin>>x;
    DeleteChild(bt,x);
    PreOrderTraverse(bt);
    break;
case 3:
    PreOrderTraverse(bt);
    break;
case 4:
    InOrderTraverse(bt);
    break;
case 5:
    PostOrderTraverse(bt);
    break;
case 6:
    char ch;
    cout<<"請輸入您要尋找的節點數值"<<endl;
    cin>>ch;
    cout<<Parent(bt,ch);
    break;
case 7:
    cout<<"輸入E的值"<<endl;
    cin>>e;
    cout<<LeftChild(bt,e);
    break;
case 8:
    cout<<"輸入E的值"<<endl;
    cin>>e;
    cout<<RightChild(bt,e);
    break;
case 9:
    cout<<"輸入E的值"<<endl;
    cin>>e;
    cout<<LeftSibling(bt,e);
    break;
case 10:
    cout<<"輸入E的值"<<endl;
    cin>>e;
    cout<<RightSibling(bt,e);
    break;
case 11:
    cout<<Root(bt);
    break;
case 12:
    p=bt->left;
    cout<<Value(p)<<endl;
    break;
case 13:
    p=bt->left;
    cout<<"請輸入您要賦的值"<<endl;
    cin>>e;
    Assign(p,e);
    cout<<"assign函數調用成功!其中的值現在為:"<<endl;
    cout<<p->data<<endl;
    break;

case 14:
    LevelOrderTraverse(bt);
    break;
case 15:
    cout<<BiTreeDepth(bt)<<endl;
    break;
case 16:

    findleaf(bt,count3);
    cout<<count3<<endl;
    break;
case 17:
    PreOrderTraverse2(bt);
    break;
case 18:
    InOrderTraverse2(bt);
    break;
case 19:
    PostOrderTraverse2(bt);
    break;
case 20:
    cout<<findleafinforest(bt)<<endl;
    break;
case 21:
    BithrTree bt;
    CreateBithrTree(bt);
    BithrTree thrt;
    cout<<"線索化二叉樹成功!"<<endl;
    InOrderThreading(thrt,bt);
    InOrderTraverseThrtree(thrt);
    cout<<"遍歷線索二叉樹成功!"<<endl;
   break;
}


   cout<<"您是否想要繼續調用函數?yes/no"<<endl;
    string s;cin>>s;
    if (!s.compare("yes"))
    goto ll1;
    else



    return 0;
}

 

我這個哈夫曼樹貌似有點問題,結果不太對啊。。有空再調一調

哈夫曼測試數據:
8 5 29 7 8 14 23 3 11 未調試出來的哈夫曼: 
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <string>
#include <string.h>
#include <math.h>
#define MAXSIZE 20

using namespace std;
//哈夫曼編碼
typedef struct {
unsigned int weight;
unsigned int parent,lchild,rchild;
}HTNode,*HuffmanTree;

typedef char* *Huffmancode;//定義一個指針數組存放編碼

int min(HuffmanTree t,int i)
 { // 函數void select()調用
   int j,flag;
   unsigned int k=UINT_MAX; // 取k為不小於可能的值
   for(j=1;j<=i;j++)
     if(t[j].weight<k&&t[j].parent==0)
       k=t[j].weight,flag=j;
   t[flag].parent=1;
   return flag;
 }

 void select(HuffmanTree t,int i,int &s1,int &s2)
 { // s1為最小的兩個值中序號小的那個
   int j;
   s1=min(t,i);
   s2=min(t,i);
   if(s1>s2)
   {
     j=s1;
     s1=s2;
     s2=j;
   }
 }

void HuffmanCoding(HuffmanTree &ht,Huffmancode &hc,int *w,int n)
{
    int i;
    if (n<=1)
        return;//判斷N(字符個數)的輸入是否合法
    int m;//哈夫曼樹結點個數
    m = 2*n-1;
    //哈夫曼樹是一個數組,我們要先定義出來, 再初始化數組
    ht = (HuffmanTree )malloc((m+1)*sizeof(HTNode));//0 單元未用
    //給初始字符賦權值
    HuffmanTree p;
    p=ht;
    p++;
    int *t;t=w;

    for (i=1,t++;i<=n;i++,p++,t++)
    {
        (*p).weight=*t;
        (*p).lchild=0;
        (*p).rchild=0;
        (*p).parent=0;
    }
    //給還沒計算的結點賦值0
    for (p=&ht[n+1],i=n+1;i<=m;i++,p++)
    {
        (*p).weight=0;
        (*p).lchild=0;
        (*p).rchild=0;
        (*p).parent=0;
    }

    //建立哈夫曼樹
    for(int i=n+1;i<=m;i++)
    {
        int s1,s2;
        select(ht,i-1,s1,s2);//最小的兩個結點序號為s1,s2

        ht[s1].parent=i;
        ht[s2].parent=i;
        ht[i].lchild=s1;
        ht[i].rchild=s2;
        ht[i].weight=ht[s1].weight+ht[s2].weight;
    }
    //show()
//    for (i=1 ; i<=m ; i++)
//    {
//        cout<< ht[i].weight <<" " <<ht[i].parent <<" "<<ht[i].lchild <<" "<<ht[i].rchild<<endl;
//    }
    //進行哈夫曼編碼
    int c,f;
    hc=(Huffmancode)malloc(sizeof(char *)*(n+1));//頭指針向量
    char *cd = (char *)malloc(sizeof(char)*n);//一個字符編碼的數組指針
    cd[n-1]='\0';
    for (int i=1;i<=n;i++)//循環N個字符
    {
        int start = n-1;//從葉節點開始往上編
        for (c=i,f=ht[i].parent;f!=0;c=f,f=ht[f].parent)
        {
            //定義C是為了不動I,順次往上找雙親,判斷自己是雙親的左子樹還是右子樹
            if (ht[f].lchild == c)
                cd[--start]='0';
            else
                cd[--start]='1';

        }

        for (int x = n-start;x<n;x++)
            cout<<cd[x];
        hc[i]=(char *)malloc((n-start)*sizeof(char));
        strcpy(hc[i],cd);
        //cout<<hc[i]<<endl;
    }

}

int main()
{
  int *w,*ww;

  int n;
  cout<<"請輸入字符數N"<<endl;
  cin>>n;
  w=(int *)malloc(sizeof(int)*(n+1));//0號單元未用
  ww=w;
  int i;
  cout<<"請依次輸入字符的權值"<<endl;
  for (ww++,i=1;i<=n;i++,ww++)
  {
     cin>> *ww;
  }

    HuffmanTree ht;
    Huffmancode hc;
    HuffmanCoding(ht,hc,w,n);
    Huffmancode q=hc;

    for (int k=1;k<=n;k++)
    puts(hc[k]);





    return 0;
}

 


免責聲明!

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



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