哈夫曼编码课设

/*
   因为总计就是255个字符(状态),所以采用深搜是完全没有压力的 
*/ 


#include<iostream>
#include<string>
#include<map>
using namespace std;
#define manx 100
#define inf 9999999;


map<char,int>mp;


struct node{
    int weight;
    int parent;
    int lch;
    int rch;
    string code;  ///  哈夫曼码值 
    string val;  ///  字符 
};


void init(node *hfnode,int n){ /// 初始化 
    for(int i=0;i<(n<<1)-1;i++){
        hfnode[i].weight=0;
        hfnode[i].parent=-1;
        hfnode[i].lch = hfnode[i].rch = -1;
        hfnode[i].code.clear();
        hfnode[i].val.clear();
    }
}


void make_tree(node *hfnode,int n){  /// 建哈夫曼树 
    int m1, m2, x1, x2;
    for(int i=1;i<n;i++){
        m1 = m2 = inf;  ///  记录最小和其次小的值 
        x1 = x2 = 0;  ///   记录最小和其次的值的位置 
        for(int j=1;j<n+i;j++){    ///   查询,找到最小和其次小的位置 
            if(hfnode[j].weight < m1 && hfnode[j].parent < 0){
                m2 = m1;
                x2 = x1;
                m1 = hfnode[j].weight;
                x1 = j;
            }
            else if(hfnode[j].weight < m2 && hfnode[j].parent <0 ){
                m2 = hfnode[j].weight;
                x2 = j;
            }
        }
        hfnode[x1].parent = n+i;  ///  然后父亲节点进行更新 
        hfnode[x2].parent = n+i;
        hfnode[n+i].weight = hfnode[x1].weight + hfnode[x2].weight;  ///  权值更新 
        hfnode[n+i].lch = x1;   ///  左右孩子进行记录 
        hfnode[n+i].rch = x2;
    }
}  


void tree_code(node *hfnode, int m, int n ){  ///  采用递归的形式建立哈夫曼编码值 
    if( m<=n ) return ;
    if(hfnode[m].lch > 0) {
        hfnode[ hfnode[m].lch ].code = "0";
    }
    if(hfnode[m].rch > 0) {
        hfnode[ hfnode[m].rch ].code = "1";
    }
    tree_code( hfnode, hfnode[m].lch, n );  
    tree_code( hfnode, hfnode[m].rch, n ); 
}


string e,hh; ///  hh表示哈夫曼编码,它的长度也算是深度
             ///  e 表示目标值 
int length;  ///  文本的长度 


void tree_dfs( node *hfnode,int m,int n,string s,int &flag ){  /// 深搜 
    if( hfnode[m].val == e ){  /// 当查询到时 
        flag=1, hh=s;
        return ;
    }
    if(flag || m <= n) return ; ///  两个成立的条件 
    if(hfnode[m].lch > 0) {
        tree_dfs(hfnode,hfnode[m].lch, n, s+hfnode[ hfnode[m].lch ].code, flag);
    }
    if(hfnode[m].rch > 0) {
        tree_dfs(hfnode,hfnode[m].rch, n, s+hfnode[ hfnode[m].rch ].code, flag);
    }
}


void scan(string & str , node * hfnode){
	getchar();
	system("cls");
	cout<<"\n\n请输入文本:";
	getline(cin,str);
	init(hfnode,str.size());
	cout<<"\n输入完毕!正在返回...";
	_sleep(500);
	mp.clear();
    init(hfnode,manx);
    int n=0,ans=1;
    for(int i=0;i<str.size();i++) mp[str[i]]++;  /// map 统计单个字符出现的次数 
    for(int i=0;i<str.size();i++){
        if(mp[str[i]]){
            hfnode[++n].weight = mp[str[i]];
            hfnode[n].val = str[i];
            mp[str[i]]=0; 
        }
    }
	make_tree(hfnode,n); 
    tree_code( hfnode,(n<<1)-1 ,n ); 
	length=n; ///   记录不同字符的个数
}


void print1(node * hfnode){
	string hfcode;
    int flag=0;
	int n = length;
	cout<<"字符"<<"\t"<<"哈夫曼Code"<<endl; 
    for(int i=1;i<=n;i++){
        flag = 0;
        hfcode.clear();
        e = hfnode[i].val;
        tree_dfs( hfnode, (n<<1)-1, n, hfcode, flag );
		cout<<""<<hfnode[i].val<<"\t"<<hh<<endl;
    } 
    cout<<"请按任意键进入主菜单.."; 
	system("pause");
}


void menu(node *hfnode){
	int operation;
	string str;
	while(1){
		system("cls");
        cout<<"\n\n\t\t**********************************"<<endl;
	    cout<<"\t\t*      1, 输入文本(换行结束)   *"<<endl;
	    cout<<"\t\t*      2, 输出所有字符哈夫曼编码 *"<<endl;
	    cout<<"\t\t*      3, 退出                   *"<<endl;
	    cout<<"\t\t**********************************"<<endl;
	    cout<<"         请输入您的选择:"; cin>>operation;
	    if(operation==3) break ;
	    if(operation==1) scan(str,hfnode);
	    if(operation==2) print1(hfnode);
	}
} 


int main(){
	system("color 79");
    node hfnode[manx*4];
    string str;
    int n1; 
	menu(hfnode);
}

哈夫曼树构造,基础资料网址链接:http://patapatapon.blog.163.com/blog/static/2040442392012261186656/



  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值