⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 haffman_code.cpp

📁 统计字符出现概率
💻 CPP
字号:
#include "string.h" 
#include "iomanip.h"
#include "math.h"
#include"iostream.h"
#define MAX_NODE 128 
#define MAX_WEIGHT 1000 

typedef struct  
{ 
	char ch; 
	int weight; //出现次数
	float freq;	//频率
	int parent, lchild, rchild; 
}HTNode; //节点类型

typedef struct 
{ 
	HTNode arr[MAX_NODE]; 
	int length; 
} HTree; //存储整个Haffman树

typedef struct  
{
	int codes[20];
	int length;
}Coded;//每个字符的编码存放位置


// 统计字符出现的次数、频率 
void statistic_char(char *text, HTree *t)
{ 
	int i, j; 
	int text_len = strlen(text); 
	t->length = 0; 
	for (i=0; i<text_len; i++)
	{ //对每个元素
		for (j=0; j<t->length; j++) 
			if (t->arr[j].ch == text[i])
			{ 
				t->arr[j].weight ++; 
				break;
			} 
			
			
			if (j==t->length) 
			{ 
				t->arr[t->length].ch = text[i]; 
				t->arr[t->length].weight = 1; 
				t->length++; 
			} 
	} 


	//计算各个字符出现的频率
	for(int k=0;k<t->length;k++)
	{
		t->arr[k].freq=(float)(t->arr[k].weight)/text_len;
	
	}


} //statistic_char



//创建haffman树(数组存储)
void Create_htree(HTree *t) 
{ 
	int i; 
	int length_node = t->length * 2 - 1; 
	int min1, min2; // 权最小的两个结点  
	int min1_i, min2_i; // 权最小结点对应的编号  
	
	for (i=0; i<t->length; i++)
	{ 
		t->arr[i].parent = -1; 
		t->arr[i].rchild = -1; 
		t->arr[i].lchild = -1; 
	} 
	
	while (t->length<length_node) 
	{ 
		min1 = min2 = MAX_WEIGHT; 
		for (i=0; i<t->length; i++) 
		{ // 对每一个结点  
			if (t->arr[i].parent == -1 // 结点没有被合并  
				&& t->arr[i].weight < min2)
			{ // 结点的权比次最小权小  
				if (t->arr[i].weight < min1) 
				{ // 比最小权的结点还小  
					min2_i = min1_i; min2 = min1; 
					min1_i = i; min1 = t->arr[i].weight; 
				} 
				else 
				{ 
					min2_i = i; min2 = t->arr[i].weight; 
				} 
			} 
		}
		
		t->arr[t->length].weight = min1 + min2; 
		t->arr[t->length].parent = -1; 
		t->arr[t->length].lchild = min1_i; 
		t->arr[t->length].rchild = min2_i; 
		t->arr[min1_i].parent = t->length; 
		t->arr[min2_i].parent = t->length; 
		t->arr[t->length].ch = ' '; 
		t->length++; 
	}
} 


// 对哈夫曼树进行编码 (遍历)
void Coding(HTree *t,  Coded *pcode,float *avg_len) 
{ 
	int len=(t->length+1)/2;
	int parent=0;
	for(int i=0;i<len;i++)
	{     
		int parent=t->arr[i].parent;
		int curent=i;
		int code_len=0;
		while(parent!=-1)
		{
			if((t->arr[parent]).lchild==curent)
				pcode[i].codes[code_len++]=0;
			else
				pcode[i].codes[code_len++]=1;
			curent=parent;
			parent=t->arr[parent].parent;
			
		}
		pcode[i].length=code_len;
		cout<<setw(3)<<t->arr[i].ch;
		cout<<setw(5)<<t->arr[i].weight;
		cout<<setw(7)<<setprecision(2)<<t->arr[i].freq;
		cout<<setw(6)<<code_len<<"\t  ";
		for(int j=pcode[i].length-1;j>=0;j--)
		{
			cout<<pcode[i].codes[j];
		}
		cout<<endl;
	}
     
	for(int k=0;k<len;k++)
	{
		*avg_len+=(float)(t->arr[k].freq)*(pcode[k].length);
	}

	cout<<"哈夫曼编码平均长度为:  "<<setprecision(3)<<*avg_len<<endl;
		
} 

void main() 
{ 
	HTree t; 
	Coded code[100];
	char text[200]; 
	float haf_avg_len=0;
	double equal_len=0;
	cout<<"请输入需要编码的字符串:"<<endl; 
	cin>>text; 
	statistic_char(text, &t); 
	Create_htree(&t); 
	cout<<"编码对应关系为:"<<endl;
	cout<<"字符  次数 频率 编码长度  编 码  "<<endl;
	Coding(&t,  code,&haf_avg_len); 
	
	//等长编码平均长度
	equal_len=(double)log10((t.length+1)/2)/log10(2);
    cout<<"等长编码平均长度为: "<<setprecision(3)<<equal_len<<endl;

	if(haf_avg_len<equal_len)
    {
        cout<<("可见HUFFMAN编码的平均长度要比固定等长编码的平均长度短,故HUFFMAN更优越\n");
    }
    else
    {
        cout<<("huffman编码不行,可能出问题了。\n");;
    }
	
}  

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -