树型结构1 堆排序 线索二叉树 huffman

(1).堆排序:

使用了数组结构进行堆排序。输入一组数,输出排序后的数列。

结构如下:

struct node{

    elemtype key;

}A[maxn];

主要函数:void PushDown(int first,int last); //整理堆,维护堆的性质

  void Sort(int n); //排序总函数

思路及原理:首先把数组建立为初始堆,然后把堆顶元素与末元素交换,再用Pushdown函数维护堆(原理是向下交换,直至找到正确的位置),最后整理的堆即所求。

 

(2).哈夫曼编码与译码

使用了三态静态链表实现。输入频数,进行建立huffman树,实现编码01序列,和01序列的译码。

结构如下:

typedef struct{

    double weight;

    int lchild;

    int rchild;

    int parent;

    char data;

}HTNODE;

typedef HTNODE HuffmanT[node];

HuffmanT T;

主要函数:void SelectMin(int N,int &p1,int &p2){ //选最小的两个数,记录下标p1,p2

  void CreatHT(); //建树

  void Bianyi(); //译码函数

思路及原理:原理是使频数大的接近根。首先是huffman树的建立。每次找到最小的两个数,求和,删去这两个数,一直重复直至只剩下一个元素,即树的根。Haffman树是二叉树,令左儿子为0,右儿子为1,按照路线查找即可实现01译码。

 

(3).线索树三种遍历:

使用了线索链表存储结构实现前序中序后序遍历算法。应用功能包括建立二叉树,实现树的前序/中序/后序线索化,然后对应线索化的三种遍历输出。共九种遍历结果。

结构如下:

struct node{

    Elemtype data;

    struct node *lson,*rson;

    bool ltag,rtag; //判断是否为空

};

typedef struct node * BTREE;

主要函数:BTREE Innext(BTREE p); //二叉树查找的线索

思路及原理:线索树即使用二叉树的空指针,节约空间,提高遍历的时间。有三种线索树,包括前序、中序、后序。每种线索树又包含各自的遍历查找算法,主要就是查找线索的过程。需要理解其中的内涵。



数组存储结构实现堆排序(完全二叉树)
/*
    author:yjc
    time:2014/3/15
    title:二叉树数组存储结构堆排序
*/

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>

using namespace std;

const int maxn=2000;

typedef int elemtype;

struct node{
    elemtype key;
}A[maxn];

void Swap(node &a,node &b){
    node c=a;
    a.key=b.key,b.key=c.key;
}

void PushDown(int first,int last){
    int r=first;
    while(r<=last/2){
        if((r==last/2) && (last%2)==0){//r有一个儿子,在2*r
            if(A[r].key>A[2*r].key)
                Swap(A[r],A[2*r]);
            r=last;
        }
        else if((A[r].key>A[2*r].key) && (A[2*r].key<=A[2*r+1].key)){ //与左儿子交换
            Swap(A[r],A[2*r]);
            r=2*r;
        }
        else if((A[r].key>A[2*r].key) && (A[2*r].key>A[2*r+1].key)){ //与右儿子交换
            Swap(A[r],A[2*r+1]);
            r=2*r+1;
        }
        else r=last;
    }
}

void Sort(int n){
    for(int i=n/2;i>=1;i--)  //建立初始堆(堆逐渐扩大)
        PushDown(i,n);
    for(int i=n;i>=2;i--){
        Swap(A[1],A[i]); //根置于末尾
        PushDown(1,i-1);
    }
}

int main(){
    int n;
    printf("输入数组的元素个数:");
    scanf("%d",&n);
    printf("输入元素:");
    for(int i=1;i<=n;i++){
        scanf("%d",&A[i].key);
    }
    Sort(n);
    printf("输出排列后的元素:\n");
    for(int i=1;i<=n;i++)
        printf("%d ",A[i].key);
    printf("\n");
    return 0;
}

/*
10
1 1 2 3 3 9 4 6 5 5
*/




三叉树Huffman的编码及译码:
/*
    author:yjc
    time:2014/3/20
    title:三叉静态链表表示Huffman树的编码与译码
*/
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#define leaf 100
#define node 2*(leaf)-1

using namespace std;

int n,m;//m=2*n-1

typedef struct{
    double weight;
    int lchild;
    int rchild;
    int parent;
    char data;
}HTNODE;

typedef HTNODE HuffmanT[node];

HuffmanT T;

void InitHT(){
    for(int i=0;i<=leaf;i++){
        T[i].parent=T[i].lchild=T[i].rchild=-1;
        T[i].weight=10000;
    }
    printf("输入叶节点个数:");
    scanf("%d",&n);
    m=2*n-1;
    printf("输入叶节点的权值:\n");
    for(int i=0;i<n;i++){
        scanf("%lf",&T[i].weight);
        T[i].data='A'+i;
    }
}

void SelectMin(int N,int &p1,int &p2){ //选最小的两个数,记录下标p1,p2
    int i,j;
    for(i=0;i<=N;i++)
        if(T[i].parent==-1){
            p1=i;
            break;
        }
    for(j=i+1;j<=N;j++)
        if(T[j].parent==-1){
            p2=j;
            break;
        }
    for(i=0;i<=N;i++)
        if(T[p1].weight>T[i].weight && T[i].parent==-1 && p2!=i)
            p1=i;
    for(j=0;j<=N;j++)
        if(T[p2].weight>T[j].weight && T[j].parent==-1 && p1!=j)
            p2=j;
}


void CreatHT(){
    int i,p1,p2;
    InitHT();
    for(i=n;i<m;i++){
        SelectMin(i-1,p1,p2);
        T[p1].parent=T[p2].parent=i;
        if(T[p1].weight<=T[p2].weight){
            T[i].lchild=p1;
            T[i].rchild=p2;
        }
        else{
            T[i].lchild=p2;
            T[i].rchild=p1;
        }
        T[i].weight=T[p1].weight+T[p2].weight;
    }
}

void Print(){
    for(int i=0;i<m;i++)
        printf("i=%d weight=%lf lchild=%d  rchild=%d\n",i,T[i].weight,T[i].lchild,T[i].rchild);
}

char str[100000];

void Bianyi(){
    printf("输入01字符串,中间不可以有空格:\n");
    scanf("%s",str);
    HTNODE p=T[m-1];
    for(int i=0;i<=strlen(str);i++){
        if(p.lchild==-1 && p.rchild==-1){
            cout << p.data << " ";
            p=T[m-1];
            i--;
            continue;
        }
        else if(str[i]=='0') p=T[p.lchild];
        else if(str[i]=='1') p=T[p.rchild];
    }
    return;
}

int main(){
    CreatHT();
    Print();
    Bianyi();
    return 0;
}

/*
5
0.12 0.40 0.15 0.08 0.25
01011011101111
*/





线索二叉树的三种遍历算法:
/*
    author:yjc
    time:2014/3/21
    title:线索链表存储结构实现三种遍历算法
*/

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <queue>
#include <stack>
#define ll long long
#define CLR(x,a) memset(x,a,sizeof(x))

using namespace std;

const int maxn=100010;

typedef char Elemtype;

struct node{
    Elemtype data;
    struct node *lson,*rson;
    bool ltag,rtag;
};

typedef struct node * BTREE;

void menu(){
    printf("Everyone loves menu!\n");
    printf("1/Creat a binary tree.\n");
    printf("2/Print the tree using list.\n");
    printf("3/Search by preorder/inorder/postorder/levelorder.\n");
    printf("4/Make full the Clue binary tree.\n");
    printf("5/Search the clue binary tree.\n");
    printf("0/Exit.\n");
}

//Second tree storing method.
struct node *s[maxn];//辅助指针二叉树,存放二叉树结点指针

BTREE CreatBT_other(){
    int i,j;
    Elemtype c;
    printf("Input the node's id and data.(end with i==0 or data=='#'\n");
    printf("例: A\n");
    printf("    / \\ \n");
    printf("   B   C\n");
    printf("        \\ \n");
    printf("         D\n");
    printf("对应输入应该为:1 A(回车) 2 B(回车) 3 C(回车) 7 D(回车) 0 #(回车)\n");
    scanf("%d %c",&i,&c);
    struct node *bt,*p;
    while(i!=0 && c!='#'){
        p=new node;
        p->data=c;
        p->lson=NULL;
        p->rson=NULL;
        s[i]=p;
        if(i==1) bt=p;
        else{
            j=i/2;
            if(i%2==0) s[j]->lson=p;
            else s[j]->rson=p;
        }
        scanf("%d %c",&i,&c);
    }
    return bt;
}

BTREE copy(BTREE p){
    BTREE t;
    if(p==NULL)t=NULL;
    else
    {
        t=new node;
        t->data=p->data;
        t->lson=copy(p->lson);
        t->rson=copy(p->rson);
    }
    return t;
}
//using list to express the tree.
void Print(BTREE T)
{
    if(T!=NULL){
        printf("%c",T->data);
        if(T->lson!=NULL||T->rson!=NULL){
            printf("(");
            Print(T->lson);
            printf(",");
            Print(T->rson);
            printf(")");
        }
    }
}
//广义表2,用于线索二叉树的输出
void Print2(BTREE T)
{
    printf("%c",T->data);
    if(T->ltag!=0||T->rtag!=0){
        printf("(");
        if(T->ltag!=0)
            Print2(T->lson);
        printf(",");
        if(T->rtag!=0)
            Print2(T->rson);
        printf(")");
    }
}

//Search using dfs
void Preorder(BTREE BT){
    if(BT!=NULL){
        printf("%c",BT->data);
        Preorder(BT->lson);
        Preorder(BT->rson);
    }
}

void Inorder(BTREE BT){
    if(BT!=NULL){
        Inorder(BT->lson);
        printf("%c",BT->data);
        Inorder(BT->rson);
    }
}

void Postorder(BTREE BT){
    if(BT!=NULL){
        Postorder(BT->lson);
        Postorder(BT->rson);
        printf("%c",BT->data);
    }
}

//Search using stack.
struct node *Stack[maxn];
int top;

void Preorder_other(BTREE BT){
    top=-1;
    while(BT!=NULL || top!=-1){
        while(BT!=NULL){
            printf("%c",BT->data);
            Stack[++top]=BT;
            BT=BT->lson;
        }
        if(top!=-1){
            BT=Stack[top--];
            BT=BT->rson;
        }
    }
}

void Inorder_other(BTREE BT){
    top=-1;
    while(BT!=NULL || top!=-1){
        while(BT!=NULL){
            Stack[++top]=BT;
            BT=BT->lson;
        }
        if(top!=-1){
            BT=Stack[top--];
            printf("%c",BT->data);
            BT=BT->rson;
        }
    }
}

void Postorder_other2(BTREE T)//非递归后序遍历,用一个标记标记右子树是否访问过
{
    struct node *p;
    int flag[maxn];
    top=0;
    p=T;
    while(p!=NULL || top!=0){
        while(p){
            Stack[++top]=p;
            flag[top]=0;
            p=p->lson;
        }
        if(top>0){
            if(flag[top]==1){
                p=Stack[top--];
                printf("%c",p->data);
                p=NULL;
            }
            else{
                p=Stack[top];
                if(top>0){
                    p=p->rson;
                    flag[top]=1;
                }
            }
        }
    }
}

struct node *Queue[maxn],*p;

void Levelorder(BTREE BT){
    int pre,rear;
    pre=rear=0;
    if(BT==NULL) return;
    Queue[++rear]=BT;
    while(pre!=rear){
        p=Queue[++pre];
        printf("%c",p->data);
        if(p->lson!=NULL) Queue[++rear]=p->lson;
        if(p->rson!=NULL) Queue[++rear]=p->rson;
    }
}

/*线索化二叉树*/
BTREE pre=NULL;
BTREE head;

/* 二叉数的中序线索化 */
void Make(BTREE p)
{   if(p==NULL)return ;
    Make(p->lson);
    p->ltag=(p->lson)?1:0;
    p->rtag=(p->rson)?1:0;
    if(pre)
    {
        if(pre->rtag==0)pre->rson=p;
        if(p->ltag==0)p->lson=pre;
    }
    pre=p;
    Make(p->rson);
}
BTREE Make2(BTREE p)
{    head=new node;
    head->ltag=1;
    head->rtag=0;head->rson=head;

      if(!p)head->lson=head;/*若二叉树为空,则左指针回指*/
      else{head->lson=p;pre=head;
          Make(p);/*中序遍历进行中序线索化*/
           pre->rson=head;
           pre->rtag=0;/*最后一个结点线索化*/
    }
    return head;
}
/* 二叉树的先序线索化 */
void ProMake(BTREE p)
{
    if(p==NULL)return ;
    p->ltag=(p->lson)?1:0;
    p->rtag=(p->rson)?1:0;
    if(pre)
    {
        if(pre->rtag==0)pre->rson=p;
        if(p->ltag==0)p->lson=pre;
    }
    pre=p;
    if(p->ltag)
    ProMake(p->lson);
    if(p->rtag)
    ProMake(p->rson);
}
BTREE ProMake2(BTREE p)
{
    head=new node;
    head->rtag=0;head->rson=head;
      if(!p){head->ltag=0;head->lson=head;}/*若二叉树为空,则左指针回指*/
       else{
            head->ltag=1;
            head->lson=p;pre=head;
            ProMake(p);/*先序遍历进行先序线索化*/
            pre->rson=head;
            pre->rtag=0;
            /*最后一个结点线索化*/
           }
    return head;
}
/* 二叉树的后序线索化 */
void LastMake(BTREE p)
{    if(p==NULL)return ;
     LastMake(p->lson);
     LastMake(p->rson);
     p->ltag=(p->lson)?1:0;
     p->rtag=(p->rson)?1:0;
     if(pre)
    {
        if(pre->rtag==0)pre->rson=p;
        if(p->ltag==0)p->lson=pre;
    }
      pre=p;
}
BTREE LastMake2(BTREE p)
{
    head=new node;
    head->rtag=0;head->rson=head;
      if(!p){head->ltag=0;head->lson=head;}/*若二叉树为空,则左指针回指*/
       else{ head->ltag=1;
             head->lson=p;
             pre=head;
             LastMake(p);/*后序遍历进行后序线索化*/
             head->rson=pre;
                         /*最后一个结点线索化*/
    }
    return head;
}

/*线索二叉树查找的线索*/
//Get the inorder clue binary tree's preorder's postorder node.
BTREE Innext(BTREE p){
    BTREE q;
    q=p->rson;
    if(p->rtag==true)
        while(q->ltag==true)
            q=q->lson;
    return q;
}

BTREE PreNext(BTREE p)
{
    if(p->ltag==1)return p->lson;
    return p->rson;
}

//后序LastNext
BTREE Parent(BTREE p)  //取得节点的父节点
{
    BTREE temp=head;
    if(temp->lson==p)
        return temp;
    else{
        temp=temp->lson;
        while(temp->lson!=p&&temp->rson!=p)
        {
            if(temp->rtag==1)
                temp=temp->rson;
            else
                temp=temp->lson;  //有左孩子去左孩子,没有左孩子,去前驱;
        }
    }
    return temp;
}

BTREE LastNext(BTREE p)
{
    BTREE tmp=p,par;
    if(tmp==head){
        tmp=tmp->lson;
        if(tmp==head)return tmp;
        for(;;){
            while(tmp->ltag!=0)
            tmp=tmp->lson;
            if(tmp->rtag!=0)
            tmp=tmp->rson;
            else return tmp;
        }
    }
    else{
        if(tmp->rtag==0)return tmp->rson;
        else{
            par=Parent(tmp);
            if(par->rtag==0||par->rson==tmp)
            tmp=par;
            else{
                while(par->rtag==1){
                    par=par->rson;
                    while(par->ltag==1)
                        par=par->lson;
                }
                tmp=par;
            }
            return tmp;
        }
    }
}

/*线索二叉树的查找与打印*/
void Thinorder(BTREE head){
    BTREE temp;
    temp=head;
    do{
        temp=Innext(temp);
        if(temp==NULL) break;
        if(temp!=head)
            printf("%c",temp->data);
    }while(temp!=head);
    printf("\n");
}

void Thpreorder(BTREE head)
{
     BTREE tmp;
     tmp=head;
     do{
         tmp=PreNext(tmp);
         if(tmp!=head)
         printf("%c",tmp->data);
     }while(tmp!=head);
}

void Thlastorder(BTREE head)
{
     BTREE tmp;
     tmp=head;
     do{
         tmp=LastNext(tmp);
         if(tmp!=head)
         printf("%c",tmp->data);
     }while(tmp!=head);
}

int main(){
    menu();
    int choice,tmp;
    BTREE T;
    BTREE t1,t2,t3;
    printf("Input your choice.\n");
    while(scanf("%d",&choice)!=EOF){
        switch(choice){
            case 1:
                T=CreatBT_other();
                break;
            case 2:
                Print(T);
                printf("\n");
                break;
            case 3:
                printf("There are three searching methods,you wanted?pre/in/post/level,input 1/2/3/4.input 0 to exit this choice.\n");
                while(scanf("%d",&tmp)){
                    if(tmp==1) Preorder(T);
                    else if(tmp==2) Inorder(T);
                    else if(tmp==3) Postorder_other2(T);
                    else if(tmp==4) Levelorder(T);
                    else break;
                    printf("\n");
                }
                break;
            case 4:
                t1=copy(T);t2=copy(t1);t3=copy(t2);
              //  printf("先序线索化:");t1=PreorderTh_Make(t1);Print2(t1);printf("\n");
                printf("先序线索化:");t1=ProMake2(t1);Print2(t1);printf("\n");
                printf("中序线索化:");t2=Make2(t2);Print2(t2);printf("\n");
                printf("后序线索化:");t3=LastMake2(t3);Print2(t3);printf("\n");
                break;
            case 5:
                printf("对先序二叉树的非递归遍历:");Thpreorder(t1);printf("\n");
                printf("对中序二叉树的非递归遍历:");Thinorder(t2);printf("\n");
                printf("对后序二叉树的非递归遍历:");Thlastorder(t3);printf("\n");
                break;
            case 0:
                return 0;
        }
        printf("Input your choice.\n");
    }
    return 0;
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值