1. 程式人生 > >哈夫曼樹——————資料結構作業

哈夫曼樹——————資料結構作業

實現一個哈夫曼編碼系統,系統包括以下功能:

  • 字元資訊統計:讀取待編碼的原始檔SourceFile.txt,統計出現的字元及其頻率。
  • 建立哈夫曼樹:根據統計結果建立哈夫曼樹。
  • 建立哈夫曼碼錶:利用得到的哈夫曼樹,將各字元對應的編碼表儲存在檔案Code.txt中。
  • 對原始檔進行編碼:根據哈夫曼碼錶,將SourceFile.txt中的字元轉換成相應的編碼檔案ResultFile.txt。
SourceFile.txt 的檔案內容為:

要對下邊的字元進行哈夫曼編碼處理

AAAAABBBBBBBBBBBBBBBBBBBBBBBBBCCCCCCCDDDDDDDDEEEEEEEEEEEEEEFFFFFFFFFFFFFFFFFFFFFGGGHHHHHHHHHHH
出現的字元及其頻率
A:5
B:25
C:7
D:8
E:14
F:21
G:3
H:11
哈夫曼樹
 i   weight  parent  lchild  rchild
 1     5       10        0        0
 2    25       14        0        0
 3     7        9        0        0
 4     8       10        0        0
 5    14       13        0        0
 6    21       12        0        0
 7
3 9 0 0 8 11 12 0 0 9 10 11 3 7 10 13 11 4 1 11 23 13 10 9 12 32 14 6 8 13 37 15 11 5 14 57 15 12 2 15 94 0 14
13
各字元對應的編碼表 即檔案Code.txt
 i  Char   Code
 1   A     0110
 2   B     10
 3   C     0101
 4   D     0111
 5   E     00
 6   F     111
 7   G     0100
 8   H     110
得到的檔案ResultFile.txt內容為
01100110011001100110101010101010101010101010101010101010101010101010100101010101010101010101010101011101110111011101110111011101110000000000000000000000000000111111111111111111111111111111111111111111111111111111111111111010001000100110110110110110110110110110110110

程式碼如下:

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

const int MAXN = 1e3+7;

typedef char **HuffmanCode;
typedef struct{
        int weight;
        int parent, lchild, rchild;
}HTNode,*HuffmanTree;
HuffmanTree HT;
HuffmanCode HC;
int m,s1,s2,start,c,f;
char *cd;
int z[30];
void Select(HuffmanTree HT,int n,int &s1,int &s2)//Select函式
{
        int min1 = 0x3f3f3f3f;
        int min2 = 0x3f3f3f3f;
        for(int i=1;i<=n;i++)
        {
                if(HT[i].parent)       continue;//if this node's parent not equal zero,it not root;

                if(HT[i].weight < min1)
                {
                        min1 = HT[i].weight;
                        s1 = i;
                        continue;
                }
                if(HT[i].weight < min2 && HT[i].weight >= min1)
                {
                        min2 = HT[i].weight;
                        s2 = i;
                }
        }
}

void GreatHuffmanTree(HuffmanTree &HT, int n)//建立哈夫曼樹
{
        if(n<=1) return ;
        m = 2*n - 1;
        HT = new HTNode[m+1];
        for(int i=1; i<=m; ++i)
                HT[i].parent = HT[i].lchild = HT[i].rchild = 0;
        for(int i=1; i<=n; ++i)//需要更改
                HT[i].weight=z[i];

        for(int i=n+1; i<=m; ++i)
        {
                Select(HT,i-1,s1,s2);
                HT[s1].parent = i;
                HT[s2].parent = i;
                HT[i].lchild = s1;
                HT[i].rchild = s2;
                HT[i].weight = HT[s1].weight + HT[s2].weight;
        }
}

void CreatHuffmanCode(HuffmanTree HT, HuffmanCode &HC, int n)
{
        HC = new char*[n+1];
        cd = new char[n];
        cd[n-1] = '\0';
        for(int i=1; i<=n; ++i)
        {
                start = n-1;
                c = i;
                f = HT[i].parent;
                while(f!=0)//
                {
                        --start;
                        if(HT[f].lchild == c)   cd[start]='0';
                        else                    cd[start]='1';
                        c = f;
                        f = HT[f].parent;//向上回溯
                }
                HC[i] = new char[n-start];
                strcpy(HC[i],&cd[start]);
        }
        delete cd;
}

int main()
{
//        freopen("in.txt", "r", stdin);//檔案要和程式碼放在同一個資料夾
//        freopen("out.txt", "w", stdout);
        char s[MAXN];
        scanf("%s",s);
        int len = strlen(s);
        memset(z,0,sizeof(z));
        for(int i=0;i<len;i++)//統計字元個數
                z[s[i]-'A'+1]++;
        int cnt=0;
        for(int i=1;i<=26;++i)
                if(z[i])
                        cnt++;
        for(int i=1;i<=26;i++)
                if(z[i])
                printf("%c:%d\n",'A'+i-1,z[i]);

        GreatHuffmanTree(HT,cnt);

        //輸出一下看看是否建立好哈夫曼數
        printf("\n i   weight  parent  lchild  rchild \n");
        for(int i=1; i<=m; ++i)
                printf("%2d %5d %8d %8d %8d\n",i,HT[i].weight,HT[i].parent,HT[i].rchild,HT[i].lchild);


        CreatHuffmanCode(HT,HC,cnt);
        printf("\n\nHuffmanCode:\n");
        printf(" i  Char   Code\n\n");
        for(int i=1; i<=cnt; ++i)
                printf("%2d   %c     %s\n",i,i+'A'-1,HC[i]);

        puts("");
        for(int i=0;i<len;i++)
                printf("%s",HC[s[i]-'A'+1]);
        return 0;
}