数据结构与算法--哈夫曼树应用

第1关:统计报文中各个字符出现的次数

任务描述

本关任务: 给定一串文本,统计其中各个字符出现的次数;

测试说明

平台会对你编写的代码进行测试:

测试输入:` abcdeabcdeabcdabcdabcdabcbccc

预期输出: a 6 b 7 c 9 d 5 e 2

代码:

//第一关
//(2)统计message所指一串报文中的所有不同字符及其出现次数
Precord computeChar(char *message)
{
    //补充代码
    //补充代码
    int i;
    Precord rcd=(Precord)malloc(sizeof(struct record));
    //初始化rcd
    rcd->m=0;
    for (i=0;i<N;i++)
    {
        rcd->data[i].ww=0; //初始化各字符出现的次数为0
    }
   //统计
    for (i=0;i<strlen(message);i++)
    {
        for (int j=0;j<=rcd->m;j++)
        {
            if (rcd->data[j].ww==0)
            {
                rcd->data[j].ww++;
                rcd->data[j].ch=message[i];
                rcd->m++;
                break;
            }
            else if (rcd->data[j].ch==message[i])
            {
                rcd->data[j].ww++;
                break;
            }
        }
    }
    return rcd;
}

第2关:对第一关报文中的各个字符进行哈夫曼编码

任务描述

本关任务:以第一关计算得到的各个字符的出现次数作为权值,构建哈夫曼树,并对各个字符进行哈夫曼编码。输入一串字符,输出各个字符及其出现的次数,该字符在哈夫曼树中是作为左分支还是右分支、该字符的哈夫曼编码。

输入

abcdeabcdeabcdabcdabcdabcbccc

输出

字符: a 出现次数:6 左or右:0 哈夫曼编码:00

字符: b 出现次数:7 左or右:1 哈夫曼编码:01

字符: c 出现次数:9 左or右:1 哈夫曼编码:11

字符: d 出现次数:5 左or右:1 哈夫曼编码:101

字符: e 出现次数:2 左or右:0 哈夫曼编码:100

代码:

//第二关
//(3)初始化哈夫曼树
 PHtTree initHuffman(Precord r)
 {
      //补充代码
    int i;
    int n=2*(r->m)-1;
    PHtTree ht = (PHtTree)malloc(sizeof(struct HtTree));
    ht -> htable = (struct HtNode*)malloc(sizeof(struct HtNode)*n);
	ht -> m = r -> m;
    for(i=0; i<n; i++){
        ht->htable[i].ww = ht->htable[i].parent = ht->htable[i].llink = ht->htable[i].rlink = -1;
    }
    for(i=0; i<r->m; i++){
        ht -> htable[i].ww = r->data[i].ww;
    }
    return ht;

 }

// 第二关
//(4)构造哈夫曼树。 根据报文中出现的各字符及其出现次数,构造哈夫曼树
//约定:构造过程中每次选的根结点值最小的子树作为左子树,根结点值次小的子树作为右子树 
void createHuffman(PHtTree ht,Precord r)
{
	//补充代码
    int min1, min2, s1, s2;
    int i, j;
    int n=r->m;
	for(i=0; i<n; i++){
		min1=min2 = 255;
		s1=s2= -1;
		for(j=0; j<n+i; j++){

			if(ht->htable[j].ww < min1 && ht->htable[j].parent == -1){
				min2 = min1; 
                s2 = s1; 
                min1 = ht->htable[j].ww; 
                s1 = j;
			}
			else if(ht->htable[j].ww < min2 && ht->htable[j].parent == -1){
				min2 = ht->htable[j].ww; 
                s2=j;
			}
		}

		if(n+i != 2*n-1){
		    ht -> htable[s1].parent = n+i;
		    ht -> htable[s2].parent = n+i;
		}

		ht -> htable[n+i].ww = min1+min2;
		ht -> htable[n+i].llink = s1;
		ht -> htable[n+i].rlink = s2;
	}
	ht -> root = 2*n-2;

}

// 第二关
//(5)编码
void coding(PHtTree ht,Precord r)
{
	//补充代码
    int i,j;
    int n=r->m;
    int p, q;
	char str[5];
	for(i=0; i<n; i++){
		p = i;
		q = 0;
		while(ht->htable[p].parent != -1){
			if(ht->htable[ht->htable[p].parent].llink == p){
				str[q] = '0';
				q++;
			}
			else{
				str[q] = '1';
				q++;
			}
			p = ht->htable[p].parent;
		}
		str[q] = '\0';
		if(ht->htable[ht->htable[i].parent].llink == i)
			r->data[i].branch_code = '0';
		else
			r->data[i].branch_code = '1';
		p=q-1;
		for(j=0; j<q; j++){
			r->data[i].codes[j]=str[p];
			p--;
		}
	}


}

第3关:哈夫曼译码

任务描述

本关任务:对第二关的字符串所得到的二进制编码串进行译码,输出译码后的原文。

输入:

00011110110000011110110000011110100011110100011110100011101111111

输出:

abcdeabcdeabcdabcdabcdabcbccc

代码:

// 第三关
//(6)译码
void decoding(char *codes,char *codesToMessage,PHtTree ht,Precord r)
{
	//补充代码
    int i=0,j=0; 
    int p=0;
    int n=r->m;
    while(codes[j] != '\0'){
        p=2*n-2;
        while(ht->htable[p].llink != -1 && ht->htable[p].rlink != -1){
            if(codes[j] == '0')
                p = ht -> htable[p].llink;
            else
                p = ht -> htable[p].rlink;
            j++;
        }
        codesToMessage[i] = r->data[p].ch;
        i++;
    }
    codesToMessage[i] = '\0';

}

 

 

  • 6
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
哈夫曼树是一种最优二叉树,它的构造算法如下:首先将n个结点作为n棵仅含有一个根结点的二叉树,构成一个森林F。然后,生成一个新结点,并从F中找出根结点权值最小的两棵树作为它的左右子树,新结点的权值为两棵子树根结点的权值之和。接着,从F中删除这两个树,并将新生成的树加入到F中。重复以上步骤,直到F中只有一棵树为止。 哈夫曼树具有以下性质: 1)每个初始结点都会成为叶节点,双支结点都为新生成的结点 2)权值越大离根结点越近,反之权值越小离根结点越远 3)哈夫曼树中没有结点的度为1 4)n个叶子结点的哈夫曼树的结点总数为2n-1,其中度为2的结点数为n-1。 哈夫曼树应用之一是解决编码问题。在编码中,我们使用二进制来表示字符,其中固定长度编码和前缀编码是两种常见的编码方式。前缀编码要求没有一个编码是另一个编码的前缀,而哈夫曼树构造的编码正是满足前缀编码的要求。 所以,哈夫曼树数据结构考研中是一个重要的概念,它可以用于构造最优二叉树和解决编码问题。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [数据结构考研笔记(十六) ——哈夫曼树、编码应用](https://blog.csdn.net/sf9090/article/details/109154652)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值