首页 > 代码库 > 哈夫曼树(数组表示)仅代码

哈夫曼树(数组表示)仅代码

关于哈夫曼树的介绍,网上的资料很多,这里就不多介绍了。下面是C语言的代码实现。GCC5.3.0编译通过。

// Created by Jacky on 2017-5-18
// main.c -- 哈夫曼树(数组表示)

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

/**
 * 哈夫曼树的结点定义
 */
typedef struct HuffmanNode
{
    char data;  // 字符
    int weight; // 权值,字符出现次数
    int parent; // 父结点的数组下标
    int left;   // 左孩子的数组下标
    int right;  // 右孩子的数组下标
} HuffmanNode;

/**
 * 哈夫曼树定义
 */
typedef struct HuffmanTree
{
    int count;          // 结点数,也就是数组长度 = 2 * 叶子结点 - 1
    HuffmanNode *nodes; // 结点数组
} HuffmanTree;

#define HUFFMANTREE_INIT {0, NULL}

void InitHuffmanTree(HuffmanTree *T, const char *str);
void CreateHuffmanTree(HuffmanTree *T);
void PrintHuffmanTree(HuffmanTree T);
void Visit(HuffmanNode *node);
void PreOrderTraversal(HuffmanTree T, void (*visit)(HuffmanNode *));
void InOrderTraversal(HuffmanTree T, void (*visit)(HuffmanNode *));
void PostOrderTraversal(HuffmanTree T, void (*visit)(HuffmanNode *));

int main(int argc, char const *argv[])
{
    HuffmanTree T = HUFFMANTREE_INIT;
    InitHuffmanTree(&T, "aaaabbc");
    CreateHuffmanTree(&T);
    PrintHuffmanTree(T);
    // PostOrderTraversal(T, Visit);

    free(T.nodes);// 释放结点申请的内存
    T.nodes = NULL;
    return 0;
}

/**
 * 初始化哈夫曼树。
 * 根据给定的字符串,统计每个字符出现的次数。
 * 并用统计的信息来构造哈夫曼树的叶子结点。
 * @param T   哈夫曼树对象指针
 * @param str 需要统计的字符串
 */
void InitHuffmanTree(HuffmanTree *T, const char *str)
{
    // 统计每个字符出现的次数。
    int arr[256] = {0};
    while (*str)
    {
        arr[*str]++;
        str++;
    }

    int leafCount = 0;

    // 统计叶子结点的个数。
    for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); ++i)
    {
        if (arr[i])
        {
            leafCount++;
            // printf("%c %d\n", i, arr[i]);
        }
    }

    // printf("leafCount = %d.\n", leafCount);

    HuffmanNode *nodes = (HuffmanNode *)malloc((2 * leafCount - 1) * sizeof(HuffmanNode));
    T->count = 2 * leafCount - 1;

    leafCount = 0;
    for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); ++i)
    {
        if (arr[i])
        {
            nodes[leafCount].data = http://www.mamicode.com/i;"min1 = %d, min2 = %d.\n", min1, min2);
        T->nodes[i].data = http://www.mamicode.com/0;"%c %2d\n", node->data, node->weight);
}

void PreOrder(HuffmanTree T, void (*visit)(HuffmanNode *), int index)
{
    if (index != -1)
    {
        visit(&T.nodes[index]);
        PreOrder(T, visit, T.nodes[index].left);
        PreOrder(T, visit, T.nodes[index].right);
    }
}

void InOrder(HuffmanTree T, void (*visit)(HuffmanNode *), int index)
{
    if (index != -1)
    {
        InOrder(T, visit, T.nodes[index].left);
        visit(&T.nodes[index]);
        InOrder(T, visit, T.nodes[index].right);
    }
}

void PostOrder(HuffmanTree T, void (*visit)(HuffmanNode *), int index)
{
    if (index != -1)
    {
        PostOrder(T, visit, T.nodes[index].left);
        visit(&T.nodes[index]);
        PostOrder(T, visit, T.nodes[index].right);
    }
}

/**
 * 前序遍历
 */
void PreOrderTraversal(HuffmanTree T, void (*visit)(HuffmanNode *))
{
    PreOrder(T, visit, T.count - 1);
}

/**
 * 中序遍历
 */
void InOrderTraversal(HuffmanTree T, void (*visit)(HuffmanNode *))
{
    InOrder(T, visit, T.count - 1);
}

/**
 * 后续遍历
 */
void PostOrderTraversal(HuffmanTree T, void (*visit)(HuffmanNode *))
{
    PostOrder(T, visit, T.count - 1);
}

/**
 * 打印哈夫曼树信息,方便调试
 * @param T         哈夫曼树对象
 */
void PrintHuffmanTree(HuffmanTree T)
{
    printf("\ncount = %d.\n", T.count);
    char *rows[] = {"index", "data", "weight", "parent", "left", "right"};
    int count = T.count;

    for (int i = 0; i < sizeof(rows) / sizeof(rows[0]); ++i)
    {
        if (i == 0)
        {
            printf("+--------+");
            for (int i = 0; i < count; ++i)
            {
                printf("----+");
            }
        }
        printf("\n|%-8s|", rows[i]);
        for (int j = 0; j < count; ++j)
        {
            switch (i)
            {
            case 0:// index
                printf(" %-3d|", j);
                break;
            case 1:// data
                if (T.nodes[j].data =http://www.mamicode.com/= 10)// 回车" %-3d|", T.nodes[j].data);
                }
                else
                {
                    printf(" %-3c|", T.nodes[j].data);
                }
                break;
            case 2:// weight
                printf(" %-3d|", T.nodes[j].weight);
                break;
            case 3:// parent
                printf(" %-3d|", T.nodes[j].parent);
                break;
            case 4:// left
                printf(" %-3d|", T.nodes[j].left);
                break;
            case 5:// right
                printf(" %-3d|", T.nodes[j].right);
                break;
            }
        }
        printf("\n+--------+");
        for (int j = 0; j < count; ++j)
        {
            printf("----+");
        }
    }

    printf("\n");
}

  

哈夫曼树(数组表示)仅代码