• 哈夫曼编码-C语言实现


    实验目的:

    (1) 掌握二叉树的定义;

    (2) 掌握哈夫曼树和哈夫曼编码算法的实现。

    实验内容:

    实现一个哈夫曼编码系统,系统包括以下功能:

    (1) 字符信息统计:读取待编码的源文件SourceFile.txt,统计出现的字符及其频率。

    附:SourceFile.txt文件内容为

    U ARE THE BEST IN MY HEART
    

    (2) 建立哈夫曼树:根据统计结果建立哈夫曼树。

    (3) 建立哈夫曼码表:利用得到的哈夫曼树,将各字符对应的编码表保存在文件Code.txt中。

    (4) 对源文件进行编码:根据哈夫曼码表,将SourceFile.txt中的字符转换成相应的编码文件ResultFile.txt。

    实现提示:

    (1) 字符信息统计:假设源文件SourceFile.txt中的字符只有大小写英文字母(同一个字母的大小写看作一个字符),则字符统计算法的实现过程可以归纳为:先定义一个含有26个元素的整形数组,用来存储各个字母出现的次数,最后还要排除其中出现次数为0的数组元素。

    (2) 建立哈夫曼树:参考教材算法5.10,补充函数Select的实现。

    (3) 建立哈夫曼码表:参考教材算法5.11,将编译表HC中的内容写到文件Code.txt中。

    (4) 对源文件进行编码:依次读入文件SourceFile.txt中的字符 c,在编码表 HC 中找到此字符,将字符c转换为编码表中存放的编码串,写入编码文件ResultFile.txt中,直到所有的字符处理完毕为止。

    代码实现

    #define _CRT_SECURE_NO_WARNINGS
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<fstream>
    #include<string>
    using namespace std;
    typedef struct{
    	int weight;
    	int parent, lchild, rchild;
    }HTNode, *HuffmanTree;
    typedef char **HuffmanCode;
    int a[24 + 1], b[24 + 1];
    char c[24 + 1];
    void Select(HuffmanTree &HT, int n, int &s1, int &s2){
    	for (int i = 1; i <= n; i++)
    		if (HT[i].parent == 0 && s1 == 0) { s1 = i; break; }
    	for (int i = 1; i <= n; i++)
    		if (HT[i].parent == 0 && HT[i].weight<HT[s1].weight) s1 = i;
    	for (int i = 1; i <= n; i++)
    		if (HT[i].parent == 0 && s2 == 0 && i != s1) { s2 = i; break; }
    	for (int i = 1; i <= n; i++)
    		if (HT[i].parent == 0 && HT[i].weight<HT[s2].weight&&i != s1) s2 = i;
    }
    void CreateHuffmanTree(HuffmanTree &HT, int n){
    	if (n <= 1) return;
    	int m = 2 * n - 1;//构造一棵哈夫曼树所需要的所有节点数 
    	HT = new HTNode[m + 1];//m+1指从第一个结点开始,第0个结点不用 
    	for (int i = 1; i <= m; i++){
    		HT[i].parent = 0;
    		HT[i].lchild = 0;
    		HT[i].rchild = 0;
    	}
    	for (int i = 1; i <= n; i++) HT[i].weight = b[i];//把字母出现的次数赋值给哈夫曼树的weight 
    	for (int i = n + 1; i <= m; i++){
    		int s1 = 0, s2 = 0;
    		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 CreateHuffmanCode(HuffmanTree &HT, HuffmanCode &HC, int n){
    	HC = new char*[n + 1];
    	char *cd = new char[n];
    	cd[n - 1] = '';
    	for (int i = 1; i <= n; i++){
    		int start = n - 1, c = i, f = HT[i].parent;
    		while (f){
    			--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("SourceFile.txt", "r", stdin);//打开输入文件	
    	memset(a, 0, sizeof(a));
    	string str;
    	getline(cin, str);//接收文件的字符串并保存到str中 
    	for (int i = 0; i<str.length(); i++)//统计每个字母出现的频率即次数 
    		a[str[i] - 64]++;
    	int n = 0;
    	for (int i = 1, j = 1; i <= 24; i++)//统计有多少个不同的字母以及把没出现的字母去除掉 
    		if (a[i] != 0){
    		n++;
    		b[j] = a[i];
    		c[j++] = i + 64;
    		}
    	HuffmanTree HT;
    	HuffmanCode HC;
    	CreateHuffmanTree(HT, n);
    	CreateHuffmanCode(HT, HC, n);
    	freopen("Code.txt", "w", stdout);
    	for (int i = 1; i <= n; i++)
    		cout << c[i] << ':' << HC[i] << endl;
    	freopen("ResultFile.txt", "w", stdout);
    	for (int i = 0; i<str.length(); i++){
    		for (int j = 1; j <= n; j++){
    			if (str[i] == c[j]) cout << HC[j];
    		}
    	}
    	return 0;
    }
    

    Code.txt

    A:000
    B:0110
    E:111
    H:001
    I:0111
    M:1000
    N:1001
    R:010
    S:1010
    T:110
    U:1011
    

    ResultFile.txt

    101100001011111000111101101111010110011110011000001111000010110
    
  • 相关阅读:
    我的算法日志:数据结构之顺序队列与循环队列
    我的算法日志:排序算法之快速排序
    算法:冒泡排序
    算法:桶排序(简易版)
    Android:配置LitePal 3.0
    Android:简单粗暴的二维码生成与扫描
    Linux
    Python
    Linux
    Python
  • 原文地址:https://www.cnblogs.com/zhengyu-ahu/p/12038832.html
Copyright © 2020-2023  润新知