首页 > 其他分享 >数据结构--哈夫曼树

数据结构--哈夫曼树

时间:2024-05-28 11:02:35浏览次数:15  
标签:编码 weight 哈夫曼 -- ++ HT int 数据结构

一、实验目的

1、掌握二叉树的逻辑结构、存储结构及基本操作;

2、熟练掌握哈夫曼树在实际问题中的应用;

3、针对计算机领域复杂工程问题,能够综合运用数据结构的基本理论和设计方法,设计出合理的算法。

二、实验内容

 “烽火连三月,家书抵万金”可见古人传递信息的不容易。古人用烽火台、信鸽、驿站等传送信息。现在我们有电话、互联网等媒介,信息传递非常方便快捷。我们所发送的信息都会先经过编码变成01串,再打包传输出去的。为了提高传输效率,通常利用哈夫曼树来进行编码,使得编码总长度最短且不出现二义性, 

请输入一行字符串,分别统计出各种字符的个数,作为其对应权值,建立哈夫曼树。

实现功能如下:

  1. 统计各种字符出现次数
  2. 以统计的次数作为权值建立哈夫曼树
  3. 对哈弗曼树进行先序、中序、后序、层序等遍历
  4. 求出哈弗曼树的高度
  5. 求出各种字符的哈夫曼编码及总WPL(选做)
  6. 显示编码后的字符串及压缩比(01串,选做)
  7. 用编码表对任意输入的一行01串进行译码(选做)

三、算法描述

(采用自然语言描述)

先构造哈夫曼树,再存储数据,编码,打印哈夫曼树。

四、详细设计

五、程序代码

#include<stdio.h>

#include<string.h>

#define OK 1

#define ERROR 0

#define OVERFLOW -2

#define MAXSIZE 100

typedef int Status;

int num[256]={0},H[256]={0};

//哈夫曼树的存储表示

typedef struct\n{

  int weight;                //结点权值 

  int perent,lchild,rchild;   //结点的双亲,左孩子,右孩子的下标  } HTNode,*HuffmanTree;        //动态分配数组存储哈夫曼树 

 //构造哈夫曼树中的Select函数 

void Select(HuffmanTree HT,int n,int &s1,int &s2)  //s1,s2取地址 

 { float min1=99999,min2=99999;

   int i;

 for(i=1;i\u003C=n;i++)

  if(min1>HT[i].weight&&HT[i].perent==0)

  {min1=HT[i].weight;s1=i;}

  for(i=1;i\u003C=n;i++)

 if(min2>HT[i].weight&&HT[i].perent==0&&HT[i].weight!=min1)

 {min2=HT[i].weight;s2=i;}

 }

 //构造哈夫曼树

void CreateHuffmanTree(HuffmanTree &HT,int n)

 {    int i,m,s1,s2;      //初始化

   if(n\u003C=1)

 return;  

m=2*n-1;

  HT=new HTNode[m+1];

  for(i=1;i\u003C=m;++i)

   {

      HT[i].perent=0;

   HT[i].lchild=0;

   HT[i].rchild=0;

  }

  for(i=1;i\u003C=n;++i) 

  //    scanf(\"%d\",HT[i].weight);

  HT[i].weight=H[i];

   //开始构造哈夫曼树

  for(i=n+1;i\u003C=m;++i)

   {

     Select(HT,i-1,s1,s2);

    HT[s1].perent=i;

   HT[s2].perent=i;

     HT[i].lchild=s1;

      HT[i].rchild=s2;

     HT[i].weight=HT[s1].weight+HT[s2].weight;

    }

}

   //哈夫曼编码表的存储表示

 typedef char **HuffmanCode;     //动态分配数组存储哈夫曼编码表

 //根据哈夫曼树求哈夫曼编码,存储在编码表HC中 

  void CreateHuffmanCode(HuffmanTree HT,HuffmanCode &HC,int n)

  {   int c,f,start,i;char *cd;    

    HC=new char*[n+1];    //分配存储n个字符编码的编码表空间 

  cd=new char[n];       //分配临时存放每个字符编码的动态数组空间 

    cd[n-1]='\\0';         //编码结束符 

  for(i=1;i\u003C=n;++i)     //逐个字符求哈夫曼编码 

    {

     start=n-1;

      c=i;f=HT[i].perent;

     while(f!=0)

      {

   --start;

 if(HT[f].lchild==c)  cd[start]='0';

            else cd[start]='1';

       c=f;f=HT[f].perent;

    }

   HC[i]=new char[n-start];

      strcpy(HC[i],&cd[start]);

 }

  //delete cd;

   for(i=1;i\u003C=n;i++)

     printf(\"%s \",HC[i]);  }

///哈夫曼树的先序遍历

void PreHufOrder(TreeNode*p)   //先序遍历

{  

if(p!=NULL)

{

printf("%d ",p->data) ;

PreHufOrder(p->lChild) ;

PreHufOrder(p->rChild) ;

}

}

 

//中序遍历  

void InHufOrder(TreeNode*p)

{

   if(p!=NULL)

   {

   InHufOrder(p->lChild) ;

   printf("%d ",p->data) ;

   InHufOrder(p->rChild) ;

   }

}

//后续遍历

void PostHufOrder(TreeNode*p)

{

if(p!=NULL)

{

InHufOrder(p->lChild) ;

InHufOrder(p->rChild) ;

printf("%d ",p->data) ;

}

}

//清空树  

void ClearHufTree(TreeNode*p)

{

if(p!=NULL)

{

ClearHufTree(p->lChild) ;

ClearHufTree(p->rChild) ;

delete p ;

}

}

//打印哈夫曼树

 int main(){    //  统计字符串各字符的频率 

  char str;

  char str[20];

   int i,num[256]={0};

  printf(\"please input string:\");

  scanf(\"%s\",str);

PreHufOrder(TreeNode*p);

InHufOrder(TreeNode*p);

PostHufOrder(TreeNode*p);

  for(i=0;i\u003Cstrlen(str);i++)

  {

     num[(int)str[i]]++;    }

  for(i=0;i\u003C256;i++)  {

   if(num[i]!=0)     {

       printf(\"字符%c出现%d次\\n\",(char)i,num[i]);     }   }

//统计字符串各字符的频率 

   HuffmanCode HC; 

  HuffmanTree HT;  

  CreateHuffmanTree(HT,j);

     CreateHuffmanCode(HT,HC,j);

ClearHufTree(TreeNode*p);

  return 0;

}

  • 测试和结果

测试用例:abcba

测试结果:2 2 1

3

七、用户手册

依次输入数据,运行程序,给出各种字符出现的次数及哈夫曼树的高度

标签:编码,weight,哈夫曼,--,++,HT,int,数据结构
From: https://blog.csdn.net/qq_73188794/article/details/139244714

相关文章

  • 排序(冒泡、选择、插入、希尔、归并、快速)
    冒泡排序基本原理冒泡排序(英语:BubbleSort)是一种简单的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序(如从大到小、首字母从A到Z)错误就把他们交换过来。voidBubble_Sort(int*num,intnumesize){for(inti=0;i<numesize;++i){......
  • 前端小白必知必会:JavaScript的作用域
    文章导读:AI辅助学习前端,包含入门、进阶、高级部分前端系列内容,当前是JavaScript的部分,瑶琴会持续更新,适合零基础的朋友,已有前端工作经验的可以不看,也可以当作基础知识回顾。这篇文章瑶琴带大家学习 javascript中关于变量作用域的相关知识点。在JavaScript中,变量的作用......
  • AI绘画整合包最新Stable Diffusion安装包+教程+模型+插件+动作来了(纯教学)
    首先了解一下AI绘画工具,介绍一下什么是StableDiffusion,模型的主要功能和作用StableDiffusion(简称SD),是一种先进的人工智能技术。这项技术的核心能力在于,它能够根据用户提供的文字描述,生成丰富且细致的图像内容。不仅如此,SD还能够处理图像修补、扩展以及基于文本指导的图像转......
  • docker containerd runc containerd-shim等组件的关系
    早期kubelet创建容器工作原理因为docker出生的比k8s早,所以k8s早期的容器运行时都是基于docker的,kubelet通过docker的api创建容器。后来,k8s官方不想绑死在docker这架马车上,就把容器运行时抽象出来,定义了一个接口,叫CRI(containerruntimeinterface),容器......
  • 容器基础-- namespace,Cgroup 和 UnionFS
    Namespace什么是Namespace?这里的“namespace”指的是Linuxnamespace技术,它是Linux内核实现的一种隔离方案。简而言之,Linux操作系统能够为不同的进程分配不同的namespace,每个namespace都具有独立的资源分配,从而实现了进程间的隔离。如果你的Linux安装了GCC......
  • 容器启动流程(containerd 和 runc)
    启动流程containerd作为一个api服务,提供了一系列的接口供外部调用,比如创建容器、删除容器、创建镜像、删除镜像等等。使用docker和ctr等工具,都是通过调用containerd的api来实现的。kubelet通过cri调用containerd和这些不一样,后续我会介绍到。containerd......
  • CDC 数据实时同步入湖的技术、架构和方案(截至2024年5月的现状调研)
    博主历时三年精心创作的《大数据平台架构与原型实现:数据中台建设实战》一书现已由知名IT图书品牌电子工业出版社博文视点出版发行,点击《重磅推荐:建大数据平台太难了!给我发个工程原型吧!》了解图书详情,京东购书链接:https://item.jd.com/12677623.html,扫描左侧二维码进入京东手......
  • 推荐丨网站https访问也能免费实现了
    2022年Verizon数据泄露调查报告指出,当年75%的社会工程攻击涉及网络钓鱼,仅2022年一年就有超过33万个账户被网络钓鱼,网络钓鱼占整体社会工程攻击的41%。但是也不能将所有责任归咎于运维人员,因为薄弱的安全意识建设及宣教是大部分漏洞利用的原因。在进行网络信息交互的......
  • 西门子学习笔记3 - 工业物联网(MQTT协议服务器的搭建)
    这里使用的是公开测试的一个服务器(EMQX)的服务器EMQX是一款全球下载量超千万的开源物联网MQTT服务器,单集群支持1亿物联网设备连接,消息分发时延低于1毫秒,助力企业构建关键业务的IoT平台与应用。1、服务器文件的下载1、官方下载地址:免费下载、试用EMQ产品(emqx.com......
  • APIO 2024
    A-September模拟题。取出\(m\)个人里包含相同元素的段,再判断删掉的是不是都是叶子就好,时间复杂度\(O(nm)\)#include<bits/stdc++.h>usingnamespacestd;intsolve(intn,intm,vector<int>fa,vector<vector<int>>s){ intans=0,cnt=0; vector<int>d(......