数据结构-哈夫曼树-哈夫曼编码的实现

Description
由键盘输入一组整数,作为权值序列,求赫夫曼编码并输出。Input输入为两行数据,第一行是一个整数,作为输入权值的个数( n< =10),第二行为权值序列。Output输出为权值序列对应的赫夫曼编码,每个编码输出一行
Sample Input
4
4 3 2 1
Sample Output 
4:0 
3:10
2:110 
1:111

#include <bits/stdc++.h>
#define Max_size 1005
using namespace std;

typedef struct
{
    int weight;
    int parent, lc, rc;
} HTnode, *HuffTree;
typedef char **Huffcode;
void select(HuffTree HT, int n, int &s1, int &s2)
{
    int m1, m2, cnt = 0;
    for (int i = 1; i <= n; i++)
    {
        if (HT[i].parent == 0)
        {
            if (cnt == 0)
                m1 = i;
            if (cnt == 1)
                m2 = i;
            cnt++;
            if (cnt == 2)
                break;
        }
    }
    // cout << m1 << m2 << "\n";
    for (int i = 1; i <= n; i++)
    {
        if (HT[i].parent == 0 && i != m1 && i != m2)
        {
            if (HT[i].weight < HT[m1].weight && HT[i].weight > HT[m2].weight)
            {
                m1 = m2;
                m2 = i;
            }
            else if (HT[i].weight < HT[m1].weight && HT[i].weight < HT[m2].weight)
            {
                if (HT[m1].weight < HT[m2].weight)
                {
                    m2 = i;
                }
                else
                {
                    m1 = m2;
                    m2 = i;
                }
            }
            else if (HT[i].weight > HT[m1].weight && HT[i].weight < HT[m2].weight)
            {
                m2 = i;
            }
            else if (HT[i].weight == HT[m1].weight)
            {
                if (HT[m1].weight < HT[m2].weight)
                {
                    m2 = i;
                }
            }
            else if (HT[i].weight == HT[m2].weight)
            {
                if (HT[m1].weight > HT[m2].weight)
                {
                    m1 = m2;
                    m2 = i;
                }
            }
        }
    }
    s1 = m1;
    s2 = m2;
}
void selectpro(HuffTree HT, int n, int &s1, int &s2)
{                    // 按左小又大
    int k1 = -1, k2; // 分别记录一趟的最小的两个结点
    for (int j = 1; j <= n; j++)
    { // 更新k1,k2为前两个不为空的结点
        if (HT[j].parent == 0 && k1 == -1)
        {
            k1 = j;
            continue;
        }
        if (HT[j].parent == 0)
        {
            k2 = j;
            break;
        }
    }
    for (int j = k2; j <= n; j++)
    { // 找到前两个最小的结点并记录
        if (HT[j].parent == 0)
        {
            if (HT[j].weight < HT[k1].weight)
            {
                k2 = k1;
                k1 = j;
            }
            else if (HT[j].weight < HT[k2].weight)
            {
                k2 = j;
            }
        }
    }
    s1 = k1;
    s2 = k2;
}
void selectHT(HuffTree HT, int n, int &s1, int &s2)
{ // 按先后顺序
    int i, m1 = 1, m2 = 1;
    for (i = 1; i <= n; i++)
    { // 先找到最小的
        if (HT[i].parent == 0)
        {
            if (HT[m1].weight > HT[i].weight)
                m1 = i;
        }
    }
    for (i = 1; i <= n; i++)
    {
        if (HT[i].parent == 0 && i != m1)
        { // 再找第二小的
            if (HT[m2].weight > HT[i].weight && m2 != m1)
                m2 = i;
            if (m2 == 1) // 如果找完m2没有动,说明只有两个父亲结点为0
                m2 = i;
        }
    }
    // 使s1和s2是先后顺序
    if (m1 > m2)
        swap(m1, m2);
    s1 = m1;
    s2 = m2;
}
void Huffman(HuffTree &HT, Huffcode &HC, int *w, int n)
{
    if (n <= 1)
        return;
    int m = n * 2 - 1, i, start, c, f;
    HT = (HuffTree)malloc((m + 1) * sizeof(HTnode));
    for (i = 1; i <= n; i++)
    { // 初始化哈夫曼树
        HT[i].weight = w[i];
        HT[i].lc = HT[i].parent = HT[i].rc = 0;
    }
    for (; i <= m; i++) // 初始化父亲结点
        HT[i].weight = HT[i].lc = HT[i].parent = HT[i].rc = 0;
    for (i = n + 1; i <= m; i++)
    {
        int s1, s2;
        // 查找该趟父亲结点为0且权值最小的两个点(可以是左小右大也可以按先后顺序)
        selectHT(HT, i - 1, s1, s2);
        HT[s1].parent = i; // 两个孩子的父节点为i
        HT[s2].parent = i;
        HT[i].lc = s1; // 记录左右孩
        HT[i].rc = s2;
        HT[i].weight = HT[s1].weight + HT[s2].weight; // 更新权值
    }
    HC = (Huffcode)malloc((n + 1) * sizeof(char *)); // 给编码分配n+1个空间
    char *cd;                                        // 给辅助分配n个空间
    cd = (char *)malloc(n * sizeof(char));
    cd[n - 1] = '\0'; // 下标从0开始,所以n-1应该为结束符
    for (i = 1; i <= n; i++)
    {
        start = n - 1;
        for (c = i, f = HT[i].parent; f != 0; c = f, f = HT[f].parent)
        { // 根据父亲结点左0右1
            if (HT[f].lc == c)
            {
                start--;
                cd[start] = '0';
            }
            else
            {
                start--;
                cd[start] = '1';
            }
        }
        // 这里必须只分配n-start个空间,这样输出的时候较为方便
        HC[i] = (char *)malloc((n - start) * sizeof(char));
        strcpy(HC[i], &cd[start]);
    }
}

int main()
{
    HuffTree HT;
    Huffcode HC;
    int n, *w;
    w = new int[Max_size];
    cin >> n;
    for (int i = 1; i <= n; i++)
    {
        cin >> w[i];
    }
    Huffman(HT, HC, w, n);
    for (int i = 1; i <= n; i++)
    {
        cout << w[i] << ":";
        cout << HC[i] << "\n";
    }
    return 0;
}

 

  • 10
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值