C语言实现哈夫曼编码_哈夫曼编码压缩文件c语言

C语言实现哈夫曼编码_哈夫曼编码压缩文件c语言////霍夫曼编码//#include<stdio.h>#include<stdlib.h>#include<string.h>/**思路:用一个有序链表(从大到小)来保存节点,然后通过链表来构造霍夫曼树,再由霍夫曼树得到霍夫曼编码**/typedefstructhuffman_tree_node{intwe…………

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全家桶1年46,售后保障稳定

//
// 霍夫曼编码
//
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
/**思路:用一个有序链表(从大到小)来保存节点,然后通过链表来构造霍夫曼树, 再由霍夫曼树得到霍夫曼编码**/
 
typedef struct huffman_tree_node{
    int weight;//权重
    char c;//字符 非叶子节点为0
    struct huffman_tree_node * nextHuffmanTreeNode;//链表下一个节点
    struct huffman_tree_node * leftHuffmanTreeNode;//左节点
    struct huffman_tree_node * rightHuffmanTreeNode;//右节点
}HuffmanTreeNode; //霍夫曼树节点
 
typedef struct huffman_code{
    char *s;//编码 如  010, 00, ....
    int len;//编码长度
    char c;//字符
}HuffmanCode; //霍夫曼编码(可以用来保存结果)
 
/**
 * 创建一个节点
 * @param c  字符
 * @param weight 权重
 * @return
 */
HuffmanTreeNode * createHuffmanTreeNode(char c, int weight){
    HuffmanTreeNode * node = (HuffmanTreeNode *)calloc(1, sizeof(HuffmanTreeNode));
    node->c = c;
    node->weight = weight;
    node->nextHuffmanTreeNode = NULL;
    node->leftHuffmanTreeNode = NULL;
    node->rightHuffmanTreeNode = NULL;
    return node;
}
 
/**
 * [insert 插入节点到有序链表中]
 * @param  h [头节点指针]
 * @param  s [要插入的节点]
 * @return   [头节点]
 */
static HuffmanTreeNode * insert(HuffmanTreeNode * h, HuffmanTreeNode * s){
    if(h == NULL){ //插入第一个节点时 没有头节点
        return s;//s作为头节点
    }
    if(s->weight > h->weight){
        s->nextHuffmanTreeNode = h; //s作为头节点
        return s;
    }
 
    HuffmanTreeNode * tempHuffmanTreeNode = h; //中间变量 用于遍历
    HuffmanTreeNode * preHuffmanTreeNode = tempHuffmanTreeNode;//中间变量的前一个节点
    while(tempHuffmanTreeNode != NULL){
        if(s->weight < tempHuffmanTreeNode->weight){ //要插入的节点的学号比当前节点小
            preHuffmanTreeNode = tempHuffmanTreeNode;
            tempHuffmanTreeNode = tempHuffmanTreeNode->nextHuffmanTreeNode;
            continue;
        }
        //插入到中间
        preHuffmanTreeNode->nextHuffmanTreeNode = s;
        s->nextHuffmanTreeNode = tempHuffmanTreeNode;
        break;
    }
    if(tempHuffmanTreeNode == NULL){ //插入的节点比已有的节点都小
        preHuffmanTreeNode->nextHuffmanTreeNode = s;
    }
    return h;
}
 
/**
 * 移除最后一个节点(最小的那个) 并返回
 * @param node
 * @return
 */
HuffmanTreeNode * removeLastHuffmanTreeNode(HuffmanTreeNode * h){
    HuffmanTreeNode * tempHuffmanTreeNode = h; //中间变量 用于遍历
    HuffmanTreeNode * preHuffmanTreeNode = tempHuffmanTreeNode;//中间变量的前一个节点
    while(tempHuffmanTreeNode->nextHuffmanTreeNode != NULL){
            preHuffmanTreeNode = tempHuffmanTreeNode;
            tempHuffmanTreeNode = tempHuffmanTreeNode->nextHuffmanTreeNode;
        }
        preHuffmanTreeNode->nextHuffmanTreeNode = NULL;
    return tempHuffmanTreeNode;
}
 
/**
 * 链表转霍夫曼树
 * @param head
 * @return
 */
HuffmanTreeNode * createTree(HuffmanTreeNode * head){
    if(head == NULL){
        return NULL;
    }
    while (1){
        //获取最小的两个节点
        HuffmanTreeNode * node1 = removeLastHuffmanTreeNode(head);
        if(node1 == head){ //只有一个节点了 完成
            return node1;
        }
        HuffmanTreeNode * node2 = removeLastHuffmanTreeNode(head);
        if(node2 == head){ //最后一个节点
            head = NULL; //头节点置为NULL
        }
        //创建一个新的节点
        HuffmanTreeNode * newNode = createHuffmanTreeNode(0, node1->weight+node2->weight);
        //设置左节点
        newNode->leftHuffmanTreeNode = node1->weight <= node2->weight ? node1 : node2;
        //设置右节点
        newNode->rightHuffmanTreeNode = node1->weight <= node2->weight ? node2 : node1;
        //新节点插入到链表中,再次循环 直到链表中只有一个节点
        head = insert(head, newNode);
    }
}
 
/**
 * 字符串拷贝
 * @param s
 * @param len
 * @param dest
 */
void str_copy(char *s,int len ,char *dest){
    for(int i = 0; i < len; i++){
        dest[i] = s[i];
    }
}
 
/**
 * 霍夫曼编码
 * @param node 节点
 * @param s 编码的字符串 如 001,00,01...
 * @param len 编码字符串的长度
 */
void showCode(HuffmanTreeNode * node, char *s, int len){
    if(node->c != 0){ //到叶子节点了
        //打印编码结果(或保存到结构体中):
        printf("%c->%s\n", node->c, s);
        free(s);
        return;
    }
    //遍历左节点 编码增加一个0
    char * leftS = (char *)calloc(len+1, sizeof(char));
    str_copy(s, len, leftS);
    leftS[len] = '0';
    showCode(node->leftHuffmanTreeNode, leftS, len+1);
 
    //遍历右节点 编码增加一个1
    char * rightS = (char *)calloc(len+1, sizeof(char));
    str_copy(s, len, rightS);
    rightS[len] = '1';
    showCode(node->rightHuffmanTreeNode, rightS, len+1);
	
    free(s);
 
}
int main(){
    //创建节点
    HuffmanTreeNode * head = NULL;
    HuffmanTreeNode * node_a = createHuffmanTreeNode('A', 5);
    HuffmanTreeNode * node_b = createHuffmanTreeNode('B', 4);
    HuffmanTreeNode * node_c = createHuffmanTreeNode('C', 3);
    HuffmanTreeNode * node_d = createHuffmanTreeNode('D', 2);
    HuffmanTreeNode * node_e = createHuffmanTreeNode('E', 1);
    //插入到有序链表中
    head = insert(head,node_a);
    head = insert(head,node_b);
    head = insert(head,node_c);
    head = insert(head,node_d);
    head = insert(head,node_e);
    //转霍夫曼树
    HuffmanTreeNode *tree =  createTree(head);
    printf("huffman encode:\n");
    //获取编码
	char * s  = (char*)malloc(0);
    showCode(tree, s, 0);
 
}

Jetbrains全家桶1年46,售后保障稳定

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/209949.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • SqlBulkCopy – The given value of type String from the data source cannot be converted to type

    SqlBulkCopy – The given value of type String from the data source cannot be converted to typeSqlBulkCopy-ThegivenvalueoftypeStringfromthedatasourcecannotbeconvertedtotypeofthespecifiedtargetcolumn针对使用C#SqlBulkCopy对象遇到的问题总结1.批量插入excel数据遇到的类型转换问题2.去除非数据行以下是对应的解决办法及代码1….

    2022年7月20日
    17
  • RAID技术全解图解-RAID0、RAID1、RAID5、RAID100

    图文并茂RAID技术全解–RAID0、RAID1、RAID5、RAID100……  RAID技术相信大家都有接触过,尤其是服务器运维人员,RAID概念很多,有时候会概念混淆。这篇文章为网络转载,写得相当不错,它对RAID技术的概念特征、基本原理、关键技术、各种等级和发展现状进行了全面的阐述,并为用户如何进行应用选择提供了基本原则,对于初学者应该有很大的帮助。一、RAID概…

    2022年4月7日
    148
  • Redis主从复制实现

    Redis中的主从复制,也就是Master-Slave模型,其实现相对比较简单,一般使用在多个Redis实例间的数据同步以及Redis集群中用的比较多。• 工作原理• 特征说明• 如何配置• 验证使用

    2022年4月8日
    45
  • 菜鸟实战UML——状态图

    菜鸟实战UML——状态图状态图状态图 StatechartDi 是描述一个实体基于事件反应的动态行为 显示了该实体如何根据当前所处的状态对不同的事件做出反应 通常我们创建一个 UML 状态图是为了以下的研究目的 研究类 角色 子系统 或组件的复杂行为 理解 状态图其实就是用来描述一个特定对象的所有可能状态以及由于各种事件的发生而引起的状态间的转移 状态图的图符 状态 转移 起点 终点状态状态

    2025年11月7日
    6
  • 基岩版服务器开启坐标显示,mc基岩版怎么看坐标 mc基岩版如何看坐标[通俗易懂]

    基岩版服务器开启坐标显示,mc基岩版怎么看坐标 mc基岩版如何看坐标[通俗易懂]mc基岩版如何看坐标我的世界地图有XYZ3个坐标,通过XYZ来显示你所处地图的区域。X-显示你在地图上的东/西位置,正数表示东,负数表示西。Y-显示你在地图上的海拔高度,整数表示位于地面上,负数表示位于地面下。Z-显示你在地图上的南/北位置,正数表示南,负数表示北。坐标可以显示为*位置和相对位置。02当坐标用数字显示时,则是*坐标,显示为地图上的特定地点。比如,1256163是一…

    2025年11月23日
    3
  • 俞敏洪与新东方_新东方俞敏洪现状

    俞敏洪与新东方_新东方俞敏洪现状俞敏洪与新东方“江阴模式”助俞敏洪考上北大  俞敏洪,1962年出生于江苏省江阴。  俞敏洪出生在一个普通的农村家庭里,父亲是一名木匠,母亲则是当地生产队的妇女队长,她有与这一职位对应果敢的作风。俞敏洪还有一个姐姐,是一名赤脚医生。作为一个农家孩子,俞敏洪回忆:我从小就在农田里干活,插秧、割稻、撒猪粪,样样都干……  母亲希望他的人生能有某种意义上的改变,希望…

    2025年11月6日
    4

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号