数据结构实验五:哈夫曼树的设计及实现

这篇具有很好参考价值的文章主要介绍了数据结构实验五:哈夫曼树的设计及实现。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

实验五  哈夫曼树的设计及实现

一、实验目的

1. 掌握哈夫曼树的构造算法,理解二叉树的应用;

2. 掌握哈夫曼编码的构造算法。

二、实验内容

输入一串字符串,根据给定的字符串中字符出现的频率建立相应的哈夫曼树,构造哈夫曼编码表,在此基础上可以对压缩文件进行压缩(即编码)。

已知字符串中出现的字符为A、B、C、D、E、F、G、H,其相应的权值为

7、19、2、6、32、3、21、10。

三、实验提示

此实验内容即要求实现主教材的案例5.1,具体实现可参考算法5.10和算法5.11。首先,读入一行字符串,统计每个字符出现的频率;然后,根据字符出现的频率利用算法5.10建立相应的哈夫曼树;最后,根据得到的哈夫曼树利用算法5.11求出每个字符的哈夫曼编码。

源代码:

程序所需头文件及结构体的定义:

#include<iostream>
#include <stdlib.h>
#include<string.h>
#include<fstream>
using namespace std;
typedef struct{
	int weight;
	char ch;
	int parent,lchild,rchild;
}HTNode,*HuffmanTree;
typedef char **HuffmanCode;

输入一串字符串并计算其各字符的权值函数,并用文件打印存储,用于哈夫曼树的构建:

void WeightCulate(string str,int &n){
	int i=0,k=0,flag=0,sum=0;
	n=1;
	char CharOp[26];
	int CharWeight[26];
	for(i=1;i<=26;i++){
		CharWeight[i]=0;
	}
	ofstream outfile("权值打印.txt");
	i=0;
	while(str[i]!='\0'){//输入一串字符串并统计不重复的字符及其出现次数 
		
		if(i==0){
			CharOp[n]=str[i];
			CharWeight[n]+=1;
		}
		else{
			for(k=1;k<=n;k++){
				if(str[i]==CharOp[k]){
					CharWeight[k]+=1;
					flag=1;
					break;
				}
				}
				if(flag==0){
					n+=1;
					CharOp[n]=str[i];
					CharWeight[n]+=1;
				}
			}
			i+=1;
			flag=0;
		}
		for(i=1;i<=n;i++){
			outfile.put(CharOp[i]);
			outfile<<CharWeight[i]<<endl;;
		}	
		outfile.close();
}

选择parent为0且权值最小的两科树,并记作s1,s2:

void Select(HuffmanTree& HT, int n, int& s1, int& s2){//选择权值最小的两棵树进行合并 
	int min,i;
	for(i=1;i<=n;i++){
		if(HT[i].parent == 0){
			min=i;
			break;
		}
	}
	for (i=min+1;i<=n;i++){
		if (HT[i].parent==0&&HT[i].weight<HT[min].weight)
			min = i;
	}
	s1 = min;//左孩子s1 
	for(i=1;i<=n;i++){
		if(HT[i].parent==0&&i!=s1){
			min=i;
			break;
		}
	}
	for(i=min+1;i<=n;i++){
		if(HT[i].parent==0&&HT[i].weight<HT[min].weight&&i!= s1)
			min=i;
	}
	s2=min; //右孩子s2 
}

建立哈夫曼树,并用文件对字符及其权值进行输入:

void CreatHuffmanTree(HuffmanTree &HT,int n,int choose){
	int m,i,s1,s2;
	if(n<=1)	return;
	m=2*n-1;
	HT=new HTNode[m+1];
	for(i=1;i<=m;++i){
		HT[i].parent=0;
		HT[i].lchild=0;
		HT[i].rchild=0;
	}
	i=1;
	fstream file;//文件输入 
	if(choose==1){
		file.open("字符权值.txt");
		if(!file)
			cout<<"[----错误!未找到字符权值文件----]"<<endl; 
	}
	else if(choose==2){
		file.open("权值打印.txt");
		if(!file)
			cout<<"[----错误!未找到字符权值文件----]"<<endl; 
	}
	while(!file.eof()){
		file>>HT[i].ch>>HT[i].weight;
		i++;
	}
	for(i=n+1;i<=m;++i){
		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;
	}
	cout<<"[------哈夫曼树已成功建立!------]"<<endl; 
}

打印哈夫曼树:

void print(HuffmanTree HT,int n){
	int i,m;
	m=2*n-1;
	cout<<"[--------------哈夫曼树为:>--------------]"<<endl;
	cout<<"下标   权值     父结点   左孩子   右孩子"<<endl; 
	for(i=1;i<=m;i++)
	{
		cout<<i<<"	"<<HT[i].weight<<"	"<<HT[i].parent<<"	"<<HT[i].lchild<<"	"<<HT[i].rchild<<endl;
	}
}

对各字符进行哈夫曼编码:

typedef char **HuffmanCode;

//生成哈夫曼编码
void HuffCoding(HuffmanTree& HT, HuffmanCode& HC, int n)
{
	HC = (HuffmanCode)malloc(sizeof(char*)*(n + 1)); //开n+1个空间,因为下标为0的空间不用
	char* code = (char*)malloc(sizeof(char)*n); //辅助空间,编码最长为n(最长时,前n-1个用于存储数据,最后1个用于存放'\0')
	code[n - 1] = '\0'; //辅助空间最后一个位置为'\0'
	for (int i = 1; i <= n; i++)
	{
		int start = n - 1; //每次生成数据的哈夫曼编码之前,先将start指针指向'\0'
		int c = i; //正在进行的第i个数据的编码
		int p = HT[c].parent; //找到该数据的父结点
		while (p) //直到父结点为0,即父结点为根结点时,停止
		{
			if (HT[p].lc == c) //如果该结点是其父结点的左孩子,则编码为0,否则为1
				code[--start] = '0';
			else
				code[--start] = '1';
			c = p; //继续往上进行编码
			p = HT[c].parent; //c的父结点
		}
		HC[i] = (char*)malloc(sizeof(char)*(n - start)); //开辟用于存储编码的内存空间
		strcpy(HC[i], &code[start]); //将编码拷贝到字符指针数组中的相应位置
	}
	free(code); //释放辅助空间
    cout<<"[-----已完成对各字符的编码!-----]"<<endl;
}

输出各字符及其编码:

void CodeOutput(HuffmanTree HT,HuffmanCode HC,int n){
	int i;
	for(i=1;i<=n;i++){
		cout<<"字符"<<HT[i].ch<<"的编码为:"<<HC[i]<<endl;
	}
	cout<<"[---已输出所有字符及其编码!---]"<<endl;
}

输入一串字符串并对其进行哈夫曼编码:

void StringCode(HuffmanTree& HT,HuffmanCode& HC,int n,string str){ 
	int i=0,k,flag;
	while(str[i]!='\0'){
		flag=0;
		for(k=1;k<=n;k++){//字符匹配 
			if(HT[k].ch==str[i]){
				if(i==0)	cout<<"字符串"<<str<<"的哈夫曼编码为"; 
				cout<<HC[k];
				flag=1;
			}
		}
		if(flag==0)	cout<<"字符"<<str[i]<<"编码失败!";
		i++;
	}
	cout<<endl; 
}

菜单函数:

void menu1(){
	cout<<"[----------------------------------------请选择操作!----------------------------------------]"<<endl;
	cout<<"[1.以字符为A、B、C、D、E、F、G、H,其相应的权值为7、19、2、6、32、3、21、10,开始创建哈夫曼树!]"<<endl;
	cout<<"[----------------------------2.输入一串字符并计算其权值开始实验!----------------------------]"<<endl;	
}
void menu2(){
	cout<<"[----------请选择操作!----------]"<<endl;
	cout<<"[--------1.打印哈夫曼树!--------]"<<endl;
	cout<<"[-------2.对字符进行编码!-------]"<<endl;
	cout<<"[-----3.输出各字符及其编码!-----]"<<endl;
	cout<<"[4.输入一串字符串并对其进行编码!]"<<endl;
	cout<<"[----------0.退出程序!----------]"<<endl; 
}

主函数:

int main(){
	HTNode *HT;
	HuffmanCode HC;
	int n,i,choose;
	string str;
	menu1();
	cin>>choose;
	if(choose==1)	n=8;
	if(choose==2){
		cout<<"[--------开始创建哈夫曼树!--------]"<<endl;
		cout<<"[请输入一串字符,我们将计算其权值!]"<<endl;
		cin>>str;
		WeightCulate(str,n);
		cout<<"[----------打印字符及其权值文件完成!----------]"<<endl;
	}
	CreatHuffmanTree(HT,n,choose);
	menu2();
	cin>>choose;
	while(choose){
		switch(choose){
			case 1:print(HT,n);break;
			case 2:HuffCoding(HT,HC,n);break;
			case 3:CodeOutput(HT,HC,n);break;
			case 4:cout<<"[-------请输入一串字符串!-------]"<<endl;
			cin>>str;
			cout<<"[------------已输入!------------]"<<endl;
			StringCode(HT,HC,n,str);break; 
		}
		cout<<"[----------请选择操作!----------]"<<endl;
		cin>>choose;
	} 	
	cout<<"[----------感谢您的使用!----------]"<<endl; 
	return 0;
} 

输入文件“字符权值.txt”: 

(注:文件的格式应为ANSI,否则会导致乱码)

数据结构实验五:哈夫曼树的设计及实现

运行结果:

数据结构实验五:哈夫曼树的设计及实现

 运行结果2:

(注:权值打印文件为这次运行中出现的各字符及其出现次数!)

数据结构实验五:哈夫曼树的设计及实现

给出该实验内容实现的分析研究过程的描述:

 (1)数据结构和其存储结构的选择理由和类型描述;

 (2)  哈夫曼树的构造、设计过程和结果:

 (3)哈夫曼编码的构造、设计过程和结果:

 (4)效率分析:文章来源地址https://www.toymoban.com/news/detail-485100.html

到了这里,关于数据结构实验五:哈夫曼树的设计及实现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • C语言---数据结构实验---哈夫曼树及哈夫曼编码的算法实现---图的基本操作

    本篇实验代码非本人写,代码源自外部,经调试解决了部分warning和error后在本地vs上可以正常运行,如有运行失败可换至vs 未来会重构实现该两个实验 内容要求: 1、初始化(Init):能够对输入的任意长度的字符串s进行统计,统计每个字符的频度,并建立哈夫曼树 2、建立编码

    2024年02月13日
    浏览(52)
  • 数据结构 实验17:Huffman树和Huffman编码——学习理解哈夫曼树

    目录 前言 实验要求 算法描述 个人想法 代码实现和思路、知识点讲解 知识点讲解 文件传输 Huffman树的存储 Huffman的构造  Huffman编码 编码和译码 代码实现 文件写入和输出 Huffman树初始化 构造Huffman树 求带权路径长度 Huffman编码 Huffman译码 结束 代码测试 测试结果 利用Huffman编

    2024年02月03日
    浏览(58)
  • 数据结构——哈夫曼树与哈夫曼编码

    1.1 基本概念 路径 :指从根结点到该结点的分支序列。 路径长度 :指根结点到该结点所经过的分支数目。 结点的带权路径长度 :从树根到某一结点的路径长度与该结点的权的乘积。 树的带权路径长度(WPL) :树中从根到所有叶子结点的各个带权路径长度之和。 哈夫曼树 是由

    2024年02月05日
    浏览(42)
  • 数据结构之哈夫曼树和哈夫曼编码

    切入正题之前,我们先了解几个概念: 路径:从树的一个结点到另一个结点分支所构成的路线 路径长度:路径上的分支数目 树的路径长度:从根结点出发到每个结点的路径长度之和 带权路径长度:该结点到根结点的路径长度乘以该结点的权值 树的带权路径长度:树中所有

    2024年02月11日
    浏览(43)
  • 数据结构之哈夫曼树与哈夫曼编码

    编码是信息处理的基础(重新表示信息)。 普通的编码是等长编码,例如7位的ASCIL编码,对出现频率不同的字符都使用相同的编码长度。 但其在传输和存储等情况下编码效率不高 。 可使用不等长编码,来压缩编码:高频字符编码长度更短,低频字符编码长度更长。   [例

    2023年04月15日
    浏览(60)
  • 【数据结构与算法】-哈夫曼树(Huffman Tree)与哈夫曼编码

    超详细讲解哈夫曼树(Huffman Tree)以及哈夫曼编码的构造原理、方法,并用代码实现。 路径 :从树中一个结点到另一个结点之间的 分支 构成这两个结点间的路径。 结点的路径长度 :两结点间路径上的 分支数 。 树的路径长度: 从树根到每一个结点的路径长度之和。记作: TL  权

    2024年02月06日
    浏览(51)
  • 数据结构【哈夫曼树】

    最优二叉树也称哈夫曼 (Huffman) 树 ,是指对于一组带有确定权值的叶子结点,构造的具有最小带权路径长度的二叉树。权值是指一个与特定结点相关的数值。哈夫曼树是带权路径长度最短的树,权值较大的结点离根较近。 涉及到的几个概念: 路径: 从树中一个结点到另一个结

    2024年02月14日
    浏览(36)
  • 数据结构----哈夫曼树

    哈夫曼树就是寻找构造最优二叉树,用于提高效率 各种路径长度 各种带权路径长度 结点的带权路径长度 树的带权路径长度 哈夫曼树 带权路径长度最短的树或者二叉树 也就是树的叶子结点带权路径长度之和 :也就是叶子结点的结点路径长度(根结点到叶子结点的路径数)

    2024年01月21日
    浏览(47)
  • 数据结构-哈夫曼树

    介绍 哈夫曼树,指 带权路径长度最短的二叉树 ,通常用于数据压缩中 什么是带权路径长度? 假设有一个结点,我们为它赋值,这个值我们称为权值,那么从根结点到它所在位置,所经历的路径,与这个权值的积,就是它的带权路径长度。 比如有这样一棵树,D权值为2  从

    2024年02月20日
    浏览(41)
  • 【数据结构-树】哈夫曼树

    💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kuan 的首页,持续学习,不断总结,共同进步,活到老学到老 导航 檀越剑指大厂系列:全面总

    2024年02月08日
    浏览(45)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包