数据结构实验四(哈夫曼编码)

最近拖更了好久,在忙一些琐事,有时间继续加更!
上次实验三二叉树递归与非递归版本已经全部公开,请点击此处
数据结构实验四要求
题目描述:对任意输入的一段英文,为每个字符编制其相应的哈夫曼编码,并利用该编码为任意输入的0、1序列进行解码。
操作提示:一个完整的系统应具有以下功能:
(1)初始化:从终端读入一段英文字符,统计每个字符出现的频率,建立哈夫曼树,并将该树存入某文件;
(2)编码: 利用建好的哈夫曼树对各字符进行编码,用列表的形式显示在屏幕上,并将编码结果存入另一文件中;
(3)解码: 利用保存的哈夫曼编码,对任意输入的0,1序列能正确解码。

话说我用C语言写的,有好多指针还是挺绕的,虽然思路对的但得不出正确答案,索性使用引用,对指针掌握还是有所欠缺,以后还是好好用C++吧(捂脸ing)。

这次方便同学提供部分主要函数代码(后天代码全部公开)见下:
Tree.h

#ifndef _TREE_H_
#define _TREE_H_

#include <iostream>
#include <string>
#include <cstring>
#include <map>
#include <fstream>
using namespace std;

map<char,int> str;//全局变量,键值对,对字符计数
const int INFMAX=0x3f3f3f3f;

typedef struct{
    char c;
    int parent;
    int LChild;
    int RChild;
    int weight;
}HTNode,*huffman;

typedef char ** huffmancode;

#endif

Tree.cpp

#include "Tree.h"

/*从ht树中,范围是1-n,选出最小的2个赋值给s1,s2*/
void Select(huffman ht,int n,int &s1,int &s2){
    int min=INFMAX;
    for(int i=1;i<=n;i++){
        if(ht[i].parent==0&&ht[i].weight<min){
            min=ht[i].weight;
            s1=i;
        }
    }
    min=INFMAX;
    for(int i=1;i<=n;i++){
        if(ht[i].parent==0&&ht[i].weight<min&&i!=s1){
            min=ht[i].weight;
            s2=i;
        }
    }
}

/*创建huffmantree,注意使用&*/
void CreatHuffmanTree(huffman &ht,int n){
    int m=2*n-1;
    ht=new HTNode[m+1];//第0号位置不使用
    map<char,int>::iterator it=str.begin();
    //初始化n个结点的信息
    for(int i=1;i<=n&&it!=str.end();++i,++it){
        ht[i].c=it->first;
        ht[i].parent=0;
        ht[i].LChild=0;
        ht[i].RChild=0;
        ht[i].weight=it->second;
    }
    for(int i=n+1;i<=m;i++){
        ht[i].parent=0;
        ht[i].LChild=0;
        ht[i].RChild=0;
        ht[i].weight=0;
    }
    for(int i=n+1;i<=m;i++){
        int s1,s2;
        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;
    }
}

/*通过huffman树进行解码,左为0,右为1*/
void CreatHuffmanCode(huffman ht,int n,huffmancode &hc){
    int m=2*n-1;
    hc=new char*[n+1];
    char *cd;
    cd=new char[n+1];
    cd[n-1]='\0';
	for(int i=1;i<=n;++i){
		int start=n-1;
		int c=i;
		int 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;
}

void Decode(huffman ht,int n,string str){
    HTNode p=ht[2*n-1];
	for(int i=0;i<str.length();++i){
		if(str[i]=='0'){
			p=ht[p.LChild];
		}else if(str[i]=='1'){
			p=ht[p.RChild];
		}
		if(p.LChild==0&&p.RChild==0){
			cout<<p.c;
			p=ht[2*n-1];
		}
	} 
}

Main.cpp

/*
    Author:Jack Leo
    All Rights Reserved
*/
#include "Tree.h"
#include "Tree.cpp"

int main(){
    /*读取字符并对出现的字符进行计数加权处理*/
    cout<<"请输入一段英文字符(可以输入空格,按Enter结束)"<<endl;
    string s;
    getline(cin,s);
    for(int i=0;i<s.length();i++){
        if(str.find(s[i])==str.end()){
            str.insert(pair<char,int>(s[i],1));
        }
        else{
            ++str[s[i]];
        }
    }
    int n=str.size();

    /*创建huffman树并显示创建树的过程*/
    huffman ht;
    CreatHuffmanTree(ht,n);

    ofstream file;//文件读写操作
    file.open("Tree.txt",ios::out);
    cout<<"哈夫曼树创建过程:"<<endl<<"注意:空格ASCII码值为32"<<endl<<"序号\t字符\tASCII\t权值(次数)\t父亲结点\t左孩结点\t右孩结点"<<endl;
    file<<"哈夫曼树创建过程:"<<endl<<"注意:空格ASCII码值为32"<<endl<<"序号\t字符\tASCII\t权值(次数)\t父亲结点\t左孩结点\t右孩结点"<<endl;
    for(int i=1;i<=n;++i){
		cout<<i<<"\t"<<ht[i].c<<"\t"<<int(ht[i].c)<<"\t\t"<<ht[i].weight<<"\t\t"<<ht[i].parent<<"\t\t"<<ht[i].LChild<<"\t\t"<<ht[i].RChild<<endl;
        file<<i<<"\t"<<ht[i].c<<"\t"<<int(ht[i].c)<<"\t\t"<<ht[i].weight<<"\t\t"<<ht[i].parent<<"\t\t"<<ht[i].LChild<<"\t\t"<<ht[i].RChild<<endl;
	}
    for(int i=n+1;i<=2*n-1;i++){
        cout<<i<<"\t\t\t\t"<<" \t\t"<<ht[i].parent<<"\t\t"<<ht[i].LChild<<"\t\t"<<ht[i].RChild<<endl;
        file<<i<<"\t\t\t\t"<<" \t\t"<<ht[i].parent<<"\t\t"<<ht[i].LChild<<"\t\t"<<ht[i].RChild<<endl;
    }
	cout<<"已将上述过程写入Tree.txt文档"<<endl;
    file.close();
    
    /*
    Author:Jack Leo
    All Rights Reserved
    */

    /*对字符进行解码处理*/
    huffmancode hc;
    ofstream file_code;
    file_code.open("Code.txt",ios::out);
    CreatHuffmanCode(ht,n,hc);
    cout<<"\n字符哈夫曼编码:"<<endl<<"序号\t字符\t权值(次数)\t编码\t"<<endl;
    file_code<<"字符哈夫曼编码:"<<endl<<"序号\t字符\t权值(次数)\t编码\t"<<endl;
    for(int i=1;i<=n;i++){
        cout<<i<<"\t "<<ht[i].c<<"\t "<<ht[i].weight<<"\t        "<<hc[i]<<endl;
        file_code<<i<<"\t "<<ht[i].c<<"\t "<<ht[i].weight<<"\t        "<<hc[i]<<endl;
    }
    file_code.close();
    cout<<"字符编码已写入Code.txt文档"<<endl;

    /*哈夫曼译码处理*/
    cout<<"\n译码:"<<endl;
    cout<<"请输入0,1序列进行译码"<<endl;
    string sm;
    cin>>sm;
    cout<<"上述0,1序列表示的字符串是"<<endl;
    Decode(ht,n,sm);
    return 0;
}
  • 2
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值