赫夫曼树思路,代码(C语言)

通过根据数据出现的次数计算权值来规划树结构,提高树的查找性能。这样设计出来的树最常用的数据放到离根节点近的地方,从而提高查找速度。带权路径长度最短的树叫做最优二叉树也叫做哈夫曼树。

一些术语:

        结点路径长度:从根节点到当前节点的边数。

        数的路径长度:所有叶子结点的结点路径长度之和

        结点带权路径长度:结点权值*结点路径

        树的带权路径长度:所有叶子结点的结点带权路径长度之和

        实现思路:

                1 首先需要一个结点数组来按照优先级对数据元素进行排序。

                2 编码通过数据出现的次数对数据进行编码。

                3 解码通过编码推出数据。

结点结构体内容:

        左节点位置,右结点位置,双亲位置,结点名称,权值.

哈夫曼树结构构造:

        1 对传入的数据进行统计,使用ASSIC码来进行数据出现次数统计。得到权值

        2 结点构造初始化:左右和双亲节点值均设置为0。

        3 遍历结点数组找到权值最小的两个结点,称为最小结点和次结点,将两节点权值相加构造一个新的结点作为parent结点。最小结点作为左孩子,次小结点作为右孩子。依次寻找,直到数组中所有结点均有parent结点结束。结束条件是所有结点parent!=0。

        4 赫夫曼编码:

                1 前提需要一个char类型的数组来对每个结点的编码值进行存储,char类型的数组设计,数组长度设置为n,最大索引值使用temp变量存储为n-1,假设char数组为hc,设置hc[n] = '\0',初始化数组所有值为0。

                2 从叶子结点开始对树进行构造。从数组结点开始根据索引取出结点判断结点为parent结点的左/右孩子,左节点编码设置为0右节点编码设置为1。并设置hc[temp--]=1/0;同时设置新的结点为当前结点的父节点,parent结点为当前结点的父节点的parent结点,循环直到该树的根节点结束。此时得到的数组为数组结点中结点的赫夫曼编码。

                3 输出赫夫曼编码,遍历数组即可。结点数组中的结点索引和存放赫夫曼编码的数组中的索引是相同的。找特定节点的赫夫曼编码只需要找到结点数组中该节点的索引即可。

下面代码展示

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

#define MAX_TREE_SIZE 1000

typedef struct {
    int weight;
    int parent;
    int left_child;
    int right_child;
} HuffmanNode, *HuffmanTree;

typedef struct {
    char ch;
    char code[MAX_TREE_SIZE];
} HuffmanCode, *HuffmanTable;

void createHuffmanTree(HuffmanTree tree, int n) {
    int i, j, k;
    int min1, min2;
    for (i = 0; i < 2 * n - 1; i++) {
        tree[i].weight = 0;
        tree[i].parent = -1;
        tree[i].left_child = -1;
        tree[i].right_child = -1;
    }
    for (i = 0; i < n; i++) {
        printf("请输入第%d个节点的权重:", i + 1);
        scanf("%d", &tree[i].weight);
    }
    for (i = 0; i < n - 1; i++) {
        min1 = min2 = MAX_TREE_SIZE;
        k = 0;
        for (j = 0; j < n + i; j++) {
            if (tree[j].parent == -1 && tree[j].weight < min1) {
                min2 = min1;
                min1 = tree[j].weight;
                k = j;
            } else if (tree[j].parent == -1 && tree[j].weight < min2) {
                min2 = tree[j].weight;
            }
        }
        tree[k].parent = n + i;
        tree[n + i].weight = min1 + min2;
        tree[n + i].left_child = k;
        k = 0;
        for (j = 0; j < n + i; j++) {
            if (tree[j].parent == -1 && tree[j].weight < min1) {
                min2 = min1;
                min1 = tree[j].weight;
                k = j;
            } else if (tree[j].parent == -1 && tree[j].weight < min2) {
                min2 = tree[j].weight;
            }
        }
        tree[k].parent = n + i;
        tree[n + i].right_child = k;
    }
}

void printHuffmanTree(HuffmanTree tree, int n) {
    int i;
    printf("节点\t权重\t父节点\t左孩子\t右孩子\n");
    for (i = 0; i < 2 * n - 1; i++) {
        printf("%d\t%d\t%d\t%d\t%d\n", i + 1, tree[i].weight, tree[i].parent + 1, tree[i].left_child + 1, tree[i].right_child + 1);
    }
}

void createHuffmanTable(HuffmanTree tree, HuffmanTable table, int n) {
    int i, j, k;
    char code[MAX_TREE_SIZE];
    int parent, child;
    for (i = 0; i < n; i++) {
        table[i].ch = i + 'a';
        code[0] = '\0';
        parent = tree[i].parent;
        child = i;
        while (parent != -1) {
            if (tree[parent].left_child == child) {
                strcat(code, "0");
            } else {
                strcat(code, "1");
            }
            child = parent;
            parent = tree[parent].parent;
        }
        strrev(code);
        strcpy(table[i].code, code);
    }
}

void printHuffmanTable(HuffmanTable table, int n) {
    int i;
    printf("字符\t编码\n");
    for (i = 0; i < n; i++) {
        printf("%c\t%s\n", table[i].ch, table[i].code);
    }
}

int main() {
    int n;
    printf("请输入节点数:");
    scanf("%d", &n);
    HuffmanTree tree = (HuffmanTree)malloc(sizeof(HuffmanNode) * (2 * n - 1));
    createHuffmanTree(tree, n);
    printHuffmanTree(tree, n);
    HuffmanTable table = (HuffmanTable)malloc(sizeof(HuffmanCode) * n);
    createHuffmanTable(tree, table, n);
    printHuffmanTable(table, n);
    free(tree);
    free(table);
    return 0;
}

 代码中求权值我做的操作时直接让用户输入权值,这个可以该成上面我说的使用ASSIC码来计算权重。代码:

int * arr = (int8)malloc(sizeof(int)*256);

for(int i; i < 256; i++){
   
    arr[i] = 0;

}
for(int i; inputstring[j] != '\0'; j++){
    arr[(unsigned char) inputstring[j]]++;
}

                    

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值