哈夫曼树

#include<stdio.h>
#include<stdlib.h>
#define max 100
struct BTreeNode
{
    char data;//字符信息
    int weight;//权重
    struct BTreeNode* left;
    struct BTreeNode* right;
};
struct Code//存储每个字符的编码
{
    int len;//编码长度
    char data;//存储字符
    int *code;//定义一个可变数组,返回头指针,每一位存储一个编码信息
    struct Code *next;
};
struct BTreeNode* CreateHuffman(int a[],char p[] ,int n)//创建huffman树,数组a传入权重,数组p传入待编码字符信息,n待编码字符个数
{
    int i, j;
    struct BTreeNode **b, *q;
    b = malloc(n*sizeof(struct BTreeNode));
    for (i = 0; i < n; i++)
    {
        b[i] = malloc(sizeof(struct BTreeNode));
        b[i]->weight=a[i];
        b[i]->data=p[i];
        b[i]->left = b[i]->right = NULL;
    }
    for (i = 1; i < n; i++)
    {
        //k1表示森林中具有最小权值的树根结点的下标,k2为次最小的下标
        int k1 = -1, k2;
        for (j = 0; j < n; j++)//让k1初始指向森林中第一棵树,k2指向第二棵
        {
            if (b[j] != NULL && k1 == -1)
            {
                k1 = j;
                continue;
            }
            if (b[j] != NULL)
            {
                k2 = j;
                break;
            }
        }
        for (j = k2; j < n; j++)//从当前森林中求出最小权值树和次最小
        {
            if (b[j] != NULL)
            {
                if (b[j]->weight < b[k1]->weight)
                {
                    k2 = k1;
                    k1 = j;
                }
                else if (b[j]->weight < b[k2]->weight)
                    k2 = j;
            }
        }
        //由最小权值树和次最小权值树建立一棵新树,q指向树根结点
        q = malloc(sizeof(struct BTreeNode));
        q->weight = b[k1]->weight + b[k2]->weight;
        q->data='#';
        q->left = b[k1];
        q->right = b[k2];
        b[k1] = q;//将指向新树的指针赋给b指针数组中k1位置
        b[k2] = NULL;//k2位置为空
    }
    free(b);
    return q;
}
struct Code* HuffManCoding(struct BTreeNode* FBT, int len)//编码
{
    static struct Code *head;
    static int a[10];//静态数组,存储编码信息
    if (FBT != NULL)
    {
        if (FBT->left == NULL && FBT->right == NULL)
        {
            int i;
            struct Code *p;
            int *code;
            p=(struct Code*)malloc(sizeof(struct Code));//申请一个节点
            code=(int *)malloc(len*sizeof(int));//申请可变数组,用于存储编码信息
            p->data=FBT->data;
            p->len=len;
            printf("字母:%c,权值:%d,编码:",FBT->data,FBT->weight);
            for (i = 0; i < len; i++)
            {
                printf("%d",a[i]);
                code[i]=a[i];
            }
            p->code=code;
            if (head==NULL)//节点之间的链接
            {
                p->next=NULL;
                head=p;
            }
            else
            {
                p->next=head->next;
                head->next=p;
            }
            printf("\n");
        }
        else
        {
            a[len] = 0;
            HuffManCoding(FBT->left, len + 1);
            a[len] = 1;
            HuffManCoding(FBT->right, len + 1);
        }
    }
    return head;
}
void find(struct Code *head,char x)//查找字符x,输出字符编码。head存储编码信息的头指针,x待查找字符
{
    int i;
    while (head)
    {
        if (head->data==x)
        {
            for (i=0;i<head->len;i++)
                printf("%d",head->code[i]);
            return ;
        }
        else
            head=head->next;
    }
}
int main()
{
    struct Code *head;
    int n=0,k=0,t=1,i,j,weight[max]={0},isread[max]={0};//weight存储权重
    struct BTreeNode* fbt;
    char S[max],ch,data[max];//S存储字符串,data存储带编码字符
    printf("请输入字符串:");
    while ((ch=getchar())!='\n')
        S[n++]=ch;
    for (i=0;i<n;t=1,i++)
    {
        if (isread[i]==1)
            continue;
        ch=S[i];
        isread[i]=1;
        for (j=i+1;j<n;j++)
        {
            if (ch==S[j])
            {
                isread[j]=1;
                t++;
            }
        }
        weight[k]=t;
        data[k++]=ch;
    }
    fbt = CreateHuffman(weight,data,k);
    printf("树中每个叶子结点的哈夫曼编码:\n");
    head=HuffManCoding(fbt,0);
    printf("字符串编码为:");
    for (i=0;i<n;i++)
    {
        find(head,S[i]);
    }
    return 0;
}

 

转载于:https://www.cnblogs.com/sy-me/p/6921722.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值