栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

C语言数据结构学习笔记(15)-哈夫曼树的创建及哈夫曼编码

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

C语言数据结构学习笔记(15)-哈夫曼树的创建及哈夫曼编码


# include
# include
# include
typedef struct HuffmanTreeNode{
    int weight;//权值
    int parent;//父结点下标
    int lchild, rchild;//左右孩子结点下标
}HFNode, *HFTree;
HFTree CreateHuffmanTree(HFTree HF, int n);//创建哈夫曼树
void SeleteMin(HFTree HF, int i, int * min1, int * min2);//寻找无父结点元素合集中的最小和次小元素及其对应下标
void PrintHuffmanTree(HFTree HF, int n);//打印哈夫曼树数组
void InOrderHuffmanTree(HFTree HF, int index);//中序遍历哈夫曼树
int HuffmanWPL(HFTree HF, int n);//哈夫曼树的带权路径长度
void HuffmanCoding(HFTree HF, char ** coding, int n);//哈夫曼编码
int main(void)
{    
    int n;
    HFTree HF = NULL;
    printf("请输入初始结点个数:");
    scanf("%d", &n);
    HF = CreateHuffmanTree(HF, n);
    PrintHuffmanTree(HF, 2*n-1);
    printf("中序遍历:");
    InOrderHuffmanTree(HF, 2*n-2);
    printf("n");
    printf("树的带权路径长度WPL = %dn", HuffmanWPL(HF, n));
    printf("哈夫曼编码:n");
    char ** coding = (char**)malloc(n * sizeof(char*));
    if(!coding)
        exit(-1);
    HuffmanCoding(HF, coding, n);
    for(int i = 0; i < n; i++)
        printf("%sn", coding[i]);
    for(int i = 0; i < n; i++)
    {
        free(coding[i]);
        coding[i] = NULL;
    }
    free(coding);
    coding = NULL;
    free(HF);
    HF = NULL;
    system("pause");
    return 0;
}
//创建哈夫曼树
HFTree CreateHuffmanTree(HFTree HF, int n)
{    
    int total = 2*n - 1;
    HF = (HFTree)malloc(total*sizeof(HFNode));
    if(!HF)
        exit(-1);
    for(int i = 0; i < total; i++)
    {    
        HF[i].parent = -1;
        HF[i].lchild = -1;
        HF[i].rchild = -1;
    }
    printf("请输入%d个权值:", n);
    for(int i = 0; i < n; i++)
    {
        scanf("%d", &HF[i].weight);
    }
    int min1, min2;
    for(int i = n; i < total; i++)
    {
        SeleteMin(HF, i, &min1, &min2);
        HF[i].weight = HF[min1].weight + HF[min2].weight; 
        HF[i].lchild = min1;
        HF[i].rchild = min2;
        HF[min1].parent = i;
        HF[min2].parent = i;
    }
    return HF;
}
//寻找无父结点元素合集中的最小和次小元素及其对应下标
void SeleteMin(HFTree HF, int i, int * min1, int * min2)
{    
    int Min1, Min2;//定义最小值和次小值
    Min1 = Min2 = INT_MAX;//明示常量INT_MAX:int类型的最大值
    for(int j = 0; j < i; j++)
    {
        if(HF[j].weight < Min1 && -1 == HF[j].parent)
        {
            Min2 = Min1;
            *min2 = *min1;
            Min1 = HF[j].weight;
            *min1 = j;
        }
        else if(HF[j].weight < Min2 && -1 == HF[j].parent)
        {
            Min2 = HF[j].weight;
            *min2 = j;
        }
    }
    printf("最小元素为%d下标为%d, 次小元素为%d下标为%dn", HF[*min1].weight, *min1, HF[*min2].weight, *min2);
}
//打印哈夫曼树数组
void PrintHuffmanTree(HFTree HF, int num)
{
    printf("下标tweighttparenttlchildtrchildn");
    for(int i = 0; i < num; i++)
    {
        printf("%dt%dt%dt%dt%dn", i, HF[i].weight, HF[i].parent, HF[i].lchild, HF[i].rchild);
    }
}
//中序遍历哈夫曼树
void InOrderHuffmanTree(HFTree HF, int index)
{
    if(index != -1)
    {
        InOrderHuffmanTree(HF, HF[index].lchild);
        printf("%d ", HF[index].weight);
        InOrderHuffmanTree(HF, HF[index].rchild);
    }
}
//哈夫曼树的带权路径长度
int HuffmanWPL(HFTree HF, int n)
{    
    int sum = 0;
    for(int i = 0; i < n; i++)
    {    
        int wpl = 0;
        int pos = i;
        int p_index = HF[i].parent;
        while(p_index != -1)
        {    
            pos = p_index;
            p_index = HF[p_index].parent;
            wpl++;
        }
        sum += HF[i].weight * wpl;
    }
    return sum;
}
void HuffmanCoding(HFTree HF, char ** coding, int n)
{    
    char * code = (char*)malloc(n *sizeof(char));//临时存放编码
    if(!code)
        exit(-1);
    code[n-1] = '';
    for(int i = 0; i < n; i++)
    {    
        int start = n-1;
        int pos = i;//当前处理结点下标
        int p_index = HF[i].parent;
        while(p_index != -1)
        {    
            if(pos == HF[p_index].lchild)
                code[--start] = '0';
            else
                code[--start] = '1';
            pos = p_index;//当前位置向上移动
            p_index = HF[p_index].parent;//当前位置的父节点向上移动
        }
        coding[i] = (char*)malloc((n-start) *sizeof(char));//创建实际编码空间
        if(!coding[i])
            exit(-1);
        strcpy(coding[i], &code[start]);
    }
    free(code);
    code = NULL;
}
 

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/458274.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号