哈夫曼树和哈夫曼编码

/*
Name:哈夫曼树 
Copyright: 安徽大学计算机科学与技术学院 
Author: 软件工程   杨磊 
Date: 10/05/17 02:04
Description: 给出输入字符串的哈夫曼编码
*/
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
struct htnode{
    int weight;
    int parent;
    int lchild;
    int rchild;
}ht[200];
char hc[100][100];
char C[100];
int w[100];
char s[100];
//选择两个parent为0,且weight最小的结点s1和s2
void select(int n,int &s1,int &s2){
    int i,min;
    for(i=1;i<=n;++i) {
        if(ht[i].parent==0) {
            min=i;
            break;
        }
    }
    for(i=1;i<=n;++i) {
        if(ht[i].parent==0) {
            if(ht[i].weight<ht[min].weight)
                min=i;
        }
    }
    s1=min;
    for(i=1;i<=n;++i){
        if(ht[i].parent==0 && i!=s1) {
            min=i;
            break;
        }
    }
    for(i=1;i<=n;++i){
        if(ht[i].parent==0 && i!=s1) {
            if(ht[i].weight<ht[min].weight)
                min=i;
                      }
    }
    s2=min;
}
//构造哈夫曼树ht,w存放已知的n个权值
void CrtHuffmanTree(int n){
    int m,i,s1,s2;
    m=2*n-1;
    memset(ht,0,sizeof(ht));
    for(i=1;i<=n;++i) {
        ht[i].weight=w[i];
    }
    for(i=n+1;i<=m;++i){
        select(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 CrtHuffmanCode(int n){
    char cd[100];
    int a[100];
    int i,start,p;
    int c;
    cd[n-1]='\0';
    for(i=1;i<=n;++i){
       a[i]=0;
       start=n-1;
       for(c=i,p=ht[i].parent;p!=0;c=p,p=ht[p].parent) {
           if(ht[p].lchild==c){
               cd[--start]='0';
               a[i]++;
           }
           else{
               cd[--start]='1';
               a[i]++;
           }
       }
       strcpy(hc[i],&cd[start]);
   }
    cout<<"哈夫曼编码"<<endl;
    for(i=1;i<=n;++i){
       cout<<C[i]<<' '<<w[i]<<' '<<hc[i]<<endl;
   }
}
int main(){
   	memset(C,'\n',sizeof(C));
       int i,n;
       cout<<"输入待编码字符串长度"<<endl; 
       scanf("%d",&n);
       cout<<"输入字符串"<<endl;
       for(i=1;i<=n;++i){
           cin>>s[i]; //读入字符串 
       }
       sort(s+1,s+n+1); //字典大小排序 
       int temp=1;
       for(int i=1;i<n;i++){
       	 int cnt=1;
       	 C[temp]=s[i];   //取字符 
       	 while(s[i]==s[i+1]){
       	  	cnt++;
       	  	i++;
		}
		w[temp]=cnt;  //得到字符的权值
		temp++;
	   }
	   if(s[n]!=s[n-1]){
		  C[temp]=s[n];
		  w[temp]=1;
		}
	   int k=1;
	   while(C[k]!='\n'){
	   	   k++;    //得到共有多少不同字符 
	   } 
       cout<<k-1<<endl;
       cout<<"不同的字符及其权值"<<endl;
       for(i=1;i<=k-1;i++){
        cout<<C[i]<<' '<<w[i]<<endl;
       }  
       CrtHuffmanTree(k-1);
       CrtHuffmanCode(k-1);
   return 0;
}

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值