树——哈夫曼编译码

题目:

假设某通信报文的字符集由A,B,C,D,E,F这6个字符组成,它们在报文中出现的频度(频度均为整数值)。 (1)构造一棵哈弗曼树,依次给出各字符编码结果。 (2)给字符串进行编码。 (3)给编码串进行译码。 规定: 构建哈弗曼树时:左子树根结点权值小于等于右子树根结点权值。 生成编码时:左分支标0,右分支标1。

输入:

第一行:依次输入6个整数,依次代表A,B,C,D,E,F的频度,用空格隔开。 第二行:待编码的字符串 第三行:待译码的编码串

输出:

前6行依次输出各个字符及其对应编码,格式为【字符:编码】(冒号均为英文符号) 第7行:编码串 第8行:译码串

输入样例:

3 4 10 8 6 5
BEE
0010000100111101

输出样例:

A:000
B:001
C:10
D:01
E:111
F:110
001111111
BADBED

代码如下:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

//定义哈夫曼树的 静态三叉链表结构 
typedef struct
{
    
    
    int Weight;
    int Lchild, Rchild, Parent;
}HFNode;
typedef char * HFCode[7];

//在ht前i-1项中 选取双亲为0且权值最小的两结点s1,s2 
void select(HFNode* hftree, int i, int * s1, int * s2)
{
    
    
    int j, t, flag;
    *s1 = *s2 = 0;
    for(j = 1; j <= i; j++)
    {
    
    
        if(hftree[j].Parent == 0)
        {
    
    
            if(*s1 == 0)
                *s1 = j;
            else if(*s2 == 0)
            {
    
    
                *s2 = j;
                flag = j;
                break;
            }
        }
    }
    if(hftree[*s1].Weight > hftree[*s2].Weight)
    {
    
    
        t = *s1;
        *s1 = *s2;
        *s2 = t;
    } 
    for(j = flag; j <= i; j++)
    {
    
       
        if(hftree[j].Parent == 0 && hftree[j].Weight < hftree[*s1].Weight )
        {
    
    
            *s2 = *s1;
            *s1 = j;
        }
        else if(hftree[j].Parent == 0 && hftree[j].Weight < hftree[*s2].Weight )
        {
    
    
            *s2 = j; 
        }
    }
}

//创建哈夫曼树 
void CreateHuffman_Tree(HFNode* hftree)
{
    
    
    int s1, s2;
    for(int i = 1; i <= 6; i++)
        scanf("%d",&hftree[i].Weight);
    for(int i = 7; i < 12; i++)
    {
    
       
        select(hftree, i-1,&s1, &s2);
        hftree[i].Weight = hftree[s1].Weight + hftree[s2].Weight;
        hftree[i].Lchild = s1;
        hftree[i].Rchild = s2;
        hftree[s1].Parent = hftree[s2].Parent = i;
    }
}
//哈夫曼编码 
void HuffCode(HFNode* hftree, HFCode hfcode)
{
    
    
	//由于题目中要求了 叶子结点个数为6 所以后面用的时候就不设置参数n 直接写成6了 
    int i, start, c, p;
    //申请一块空间 用来临时存放结点的编码 
    char * temp = (char *)malloc(6 * sizeof(char));
    
    temp[5]='\0';
    for(i = 1; i <= 6; i++)
    {
    
    
    	// strat=n-1 是因为 数组的前n个空间存放叶子结点 后面n-1个空间存放不断生成的子树 
        start = 5;
        c = i;
        p = hftree[c].Parent;
        
        //在下面这个循环中 将下标为 i 的结点编码完成 并且存储在temp中 
        while(p != 0)
        {
    
    
            if(hftree[p].Lchild == c)
                temp[--start] = '0';
            else
                temp[--start] = '1';
        	//编码是从最底下的结点开始找到根节点,所以每次循环结束都更新 p = hftree[c].Parent 
            c = p;
            p = hftree[c].Parent;
        }
        //刚开始start=n-1 上面的循环每追溯一层 start--,所以此时 n-start 就是 这个结点的哈夫曼编码所需要的的空间 
        hfcode[i] = (char *)malloc((6-start) * sizeof(char));
        strcpy(hfcode[i], &temp[start]);
    }
    //free掉 用来临时存放编码的temp 
    free(temp);
}
//输出编码 
void PrintCode(HFNode* hftree, HFCode hfcode)
{
    
    
    int i;
    char x = 'A';
    for(i = 1; i <= 6; i++)
        printf("%c:%s\n",x+i-1, hfcode[i]);
}
//输出译码 
void TransCode(HFCode hfcode, char * inputChar)
{
    
    
    int i, index;
    for(i = 0; i < strlen(inputChar); i++) 
    {
    
    
        index = inputChar[i] - 'A' + 1;
        printf("%s",hfcode[index]);
    }
    printf("\n");
}
//进行译码 
void TransChar(HFNode* hftree, HFCode hfcode, char * inputCode)
{
    
    
	//由于题目中要求了 叶子结点个数为6 所以后面用的时候就不设置参数n 直接写成6了 
	//p=11 是因为 一共需要2n-1个空间  并且该数组最后一个空间放的 就是最终哈弗曼树的 根节点! 
    int i = 0, j, p = 11, start;
    //temp临时存储 
    char * temp = (char *)malloc(6 * sizeof(char));
    while(inputCode[i] != '\0')
    {
    
    
    	//初始化p为哈夫曼树根节点 的下标 
        p = 11;
        start = 0; 
        while(1)
        {
    
    
        	//循环对下标 p 的结点进行译码 
            if(hftree[p].Lchild != 0)
            {
    
    
                if(inputCode[i] == '0')
                {
    
    
                    p = hftree[p].Lchild;
                    temp[start++] = '0';
                }
                else
                {
    
    
                    p = hftree[p].Rchild;
                    temp[start++] = '1';    
                }
            }
            else
            {
    
     
                break;
            }
            i++;
        }
        temp[start] = '\0'; 
        
        for(j = 1; j <= 6; j++)
        {
    
    
            if(strcmp(hfcode[j], temp) == 0)
            {
    
    
                printf("%c",'A'+j-1);
                break;
            }
        }
    }
    free(temp);
}
int main()
{
    
    
    char inputChar[100]; 
    char inputCode[100];
    HFNode hftree[12]={
    
    0};
    HFCode hfcode;
    CreateHuffman_Tree(hftree);
    HuffCode(hftree, hfcode);
    scanf("%s",inputChar);
    scanf("%s",inputCode);
    PrintCode(hftree, hfcode);
    TransCode(hfcode, inputChar);
    TransChar(hftree, hfcode, inputCode);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_51368103/article/details/121134824