Visual Studio 2010+C#实现信源编码

1. 要求

本文设计了一套界面系统,该系统能够实现以下功能:

  1. 克劳夫特不等式的计算,并且能够根据计算结果给出相应的信息。
  2. 可通过用户输入的初始条件然后给出哈夫曼编码以及LZ编码,结果均通过对话框来显示
  3. 哈夫曼编码结果包含相应的码字,信源熵,平均码长以及编码效率
  4. LZ编码结果的形式如下图所示,包括每一个短语,段号,码字以及二进制码

2.过程

1.界面总体设计:

初始界面包含用户登录,克劳夫特不等式,哈夫曼编码以及LZ编码四个模块,每一个模块都用groupbox控件来单独设计,使得整个系统看起来更加合理清晰

图1 初始界面

2.每一个部分的设计过程:

(1)登录

private void button1_Click(object sender, EventArgs e){string result=textBox1.Text +" 你好!欢迎使用信源编码程序";Form2 mfrm = new Form2(result);mfrm.ShowDialog();}

图2 用户登录

点击登录后弹出出的对话框设计

public partial class Form2 : Form{private string message;public Form2(string msg){InitializeComponent();message = msg;}private void Form2_Load(object sender, EventArgs e){label1.Text = message;}private void button1_Click(object sender, EventArgs e){this.Close();}}

图3 登录后弹出的对话框

(2)克劳夫特不等式(对话框设计与图3一致)

private void button2_Click(object sender, EventArgs e){Double m;String a;m = Convert.ToDouble(textBox2.Text);int k;double[] y = new double[richTextBox1.Lines.Length];double sum = 0;for (int i = 0; i < richTextBox1.Lines.Length; i++){a = richTextBox1.Lines[i];k =a.Length;sum += Math.Pow(m, -k);}if (sum <= 1){       Form2 mfrm = new Form2(Convert.ToString(sum) + "<=1,满足克劳夫特不等式,存在唯一可译码");mfrm.Show();}else{Form2 mfrm = new Form2(Convert.ToString(sum) + ">1,不满足克劳夫特不等式,不存在唯一可译码");mfrm.Show();}

图4 克劳夫特不等式模块

(3)哈夫曼编码(重点)

定义类:

public class Node                                 //哈夫曼树结点{public string code;public double prioirry;                           //保存权值public Node lchild;                           //左孩子指针public Node rchild;                           //右孩子指针}

定义字典存储结果:

private Dictionary<string, string> dictcode = new Dictionary<string, string>(); //结果字典

比较函数:

public int comparisonNode(Node n1, Node n2){return (int)(100*n1.prioirry -100*(n2.prioirry ));}

遍历哈夫曼树的函数:

private void viewTree(Node n, string v){if ( n.code !=null){dictcode.Add(n.code, v);}else{if (n.lchild != null){string vl = v + "1";viewTree(n.lchild, vl);}if (n.rchild != null){string vr = v + "0";viewTree(n.rchild, vr);}}}

编码函数:

private string encode(double[] p){dictcode.Clear();Dictionary<string, double> priorityQueue = new Dictionary<string, double>();for (int i = 0; i < p.Length; i++){string ci ="x"+ Convert.ToString(i); priorityQueue.Add(ci, p[i]);}List<Node> listpc = new List<Node>();foreach (var item in priorityQueue){listpc.Add(new Node() { prioirry = item.Value, lchild = null, rchild = null,code = item.Key });}listpc.Sort(comparisonNode);while (listpc.Count > 1){Node n = new Node();n.prioirry = listpc[0].prioirry + listpc[1].prioirry;n.lchild = listpc[0];n.rchild = listpc[1];listpc.RemoveAt(0);listpc.RemoveAt(0);int index = -1;for (int i = 0; i < listpc.Count; i++){if (n.prioirry <= listpc[i].prioirry){index = i;break;}}if (index == -1){ index = listpc.Count; }listpc.Insert(index, n);}string encodestr = "";viewTree(listpc[0], "");for (int i = 0; i < p.Length; i++){encodestr += dictcode["x"+Convert.ToString(i)]+' ';}return encodestr;}

编码按钮中代码:

private void button3_Click(object sender, EventArgs e){string[] a = new string[richTextBox2.Lines.Length];double[] px = new double[richTextBox2.Lines.Length];string[] s = new string[richTextBox2.Lines.Length];double h = 0;double k = 0;for (int i = 0; i < richTextBox2.Lines.Length; i++){a[i] = richTextBox2.Lines[i];px[i] = Convert.ToDouble(a[i]);}s =encode(px).Split(' ');for (int i = 0; i < px.Length; i++){h += -px[i] * Math.Log(px[i], 2);k += px[i] * s[i].Length;}Form3 mfrm = new Form3(encode(px),h,k,h/k);mfrm.Show();}

图5 哈夫曼编码模块

图6 哈夫曼编码结果对话框

(4)LZ编码

编码按钮中的代码:

private void button6_Click(object sender, EventArgs e){Dictionary<string, int> dic = new Dictionary<string, int>();Dictionary<char, char> xl = new Dictionary<char, char>();xl['a'] = '0';xl['b'] = '1';int len = textBox3.Text.Length;int i = 0;int n = 0;string u="";//短语string nn="";//段号string w="";//码字string k="";//二进制码string str = textBox3.Text;label5.Text = "";while (i < len){string a = Convert.ToString(str[i]);if (!dic.ContainsKey(a)){k += "(0," + xl[str[i]]+")  ";w += "(0," + str[i] + ")  ";u += str[i] + "     ";dic[a] = dic.Count + 1;i += 1;n += 1;nn += Convert.ToString(n) + "      ";}else if (i == len - 1){w +="("+Convert.ToString( dic[a]) + ", )  ";u += str[i] + "     ";n+=1;   k+="("+Convert.ToString(dic[a],2).PadLeft(Convert.ToInt16(Math.Ceiling( Math.Log(n,2))))+", )”; nn += Convert.ToString(n) + "      ";i += 1;}else{for (int j = i + 1; j < len; j++){if (!dic.ContainsKey(str.Substring(i, j + 1 - i))){n += 1;u += str.Substring(i, j - i+1) + "     ";nn += Convert.ToString(n) + "      ";w += "(" + Convert.ToString(dic[str.Substring(i, j - i)]) + ',' + str[j] + ")  ";                       k+="("+Convert.ToString(dic[str.Substring(i,j-i)],2).PadLeft(Convert.ToInt16(Math.Ceiling( Math.Log(n,2))),'0') +','+ xl[str[j]]+")  ";dic[str.Substring(i, j + 1 - i)] = dic.Count + 1;i = j + 1;break;}else if (j == len - 1){n += 1;nn += Convert.ToString(n) + "      ";u += str.Substring(i, j+1-i) + "     ";w +="("+Convert.ToString( dic[str.Substring(i, j + 1 - i)]) +", )  ";k +='(' + Convert.ToString(dic[str.Substring(i, j+1-i)], 2).PadLeft(Convert.ToInt16(Math.Ceiling(Math.Log(n, 2))), '0') + ", )  ";i = j + 1;}}}}Form4 mfrm = new Form4(u,nn,w,k);mfrm.Show();}

图7  LZ编码模块

图8  LZ编码结果对话框

设计完成

3. 测试

图9 登录测试

克劳夫特不等式:输入相应的码字之后点击按钮出现对应信息,例如下图中不等式大于1,所以可以判断不存在唯一可译码

图10 克劳夫特不等式测试

以上模块较为简单,经过验证已经可以满足要求,接下里着重对于哈夫曼以及LZ编码模块进行测试:

第一个哈夫曼测试采用书上例5-6的原题:

图11 原书例5-6

图12 哈夫曼编码测试1

对比原题与本系统计算出的结果可以发现,测试完全正确,与答案保持一致,编码效率达到了96%

第二个哈夫曼编码测试:

概率分别为 0.4,0.2,0.2,0.1,0.1

图13 哈夫曼编码测试2

通过计算可以得知该测试的结果完全正确,由此基本可以判断该模块可以成功实现哈夫曼编码,但是在计算过程中我发现如果将码字编为 00.10,11,010,011的话,虽然编码效率和图7中一样,但是此编码结果码方差为0.16,而图7中编码方差为1.36。经过分析得知,程序在编码过程中每一次概率的排序并不一定会把合并的概率放到前面,因此造成了有的信源符号被赋予更长的码。

第1个LZ编码测试:

序列(abbabaabbabbaaaaba)

图14  LZ编码测试1

经验证,测试1结果完全正确

第2个LZ编码测试:

序列(baabbbaaababb)

图15  LZ编码测试2

可以发现最后一个短语对应的码字以及二进制码都没有后缀,这是由于bb在第4个短语的位置就出现过了,所以前缀为4,而bb后没有其它符号所以为空。因此测试结果同样正确。

4. 总结

本文加入了信源熵,码长,效率等编码指标,让整个程序更加完整地解决了哈夫曼编码地全部过程。但是在测试中我也发现了存在的问题,例如我的程序编码的结果虽然正确,但是却不一定是最佳的,因为它的码方差可能比最佳的编码更大

LZ编码的结构相对没有那么复杂,主要是对不同情况要分别讨论,同样,也添加了更加具体的结果以便更好的去分析它。

哈夫曼编码可以用于数据压缩,但是它的概率特性需要精确测定,在数据压缩的过程中可能就会降低速度。LZ编码可以应用于很多计算机数据存储,但是它通常在序列起始段压缩效果较差,随着长度增加效果会变好。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/675140.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python小白:Python 编辑器那么多种,到底怎么选!!

前言 我在刚刚接触编程的时候很纠结于这个问题&#xff0c;因为我想找一个功能强大&#xff0c;免费&#xff0c;可多平台&#xff0c;支持多种语言的编辑器&#xff0c;所以我特意花费了一些时间对 Python 的编辑器进行了调研&#xff0c;我最终选择了 VScode 作为我的首选编…

Redis 基本认识

文章目录 Redis八个特性Redis应用场景Redis应用缺陷Redis使用流程 Redis八个特性 速度快 原因: ① 单线程&#xff0c;避免了多线程竞争(如加锁/解锁)的时间开销 ② redis的数据存放在内存中 ③ 使用C语言编写&#xff0c;C语言更方便操做硬件 ④ Redis 源码优秀 利用键值对存…

【SpringBoot】JWT令牌

&#x1f4dd;个人主页&#xff1a;五敷有你 &#x1f525;系列专栏&#xff1a;SpringBoot ⛺️稳重求进&#xff0c;晒太阳 什么是JWT JWT简称JSON Web Token&#xff0c;也就是通过JSON形式作为Web应用的令牌&#xff0c;用于各方面之间安全的将信息作为JSON对象传输…

【Git】Windows下通过Docker安装GitLab

私有仓库 前言基本思路拉取镜像创建挂载目录创建容器容器启动成功登录仓库设置中文更改密码人员审核配置邮箱 前言 由于某云存在人数限制&#xff0c;这个其实很好理解&#xff0c;毕竟使用的是云服务器&#xff0c;人家也是要交钱的。把代码完全放在别人的服务器上面&#xf…

507. Perfect Number(完美数)

题目描述 对于一个 正整数&#xff0c;如果它和除了它自身以外的所有 正因子 之和相等&#xff0c;我们称它为 「完美数」。 给定一个 整数 n&#xff0c; 如果是完美数&#xff0c;返回 true&#xff1b;否则返回 false。 问题分析 按照题目要求找出每一个因子&#xff0c…

1897_野火FreeRTOS教程阅读笔记_链表

1897_野火FreeRTOS教程阅读笔记_链表 全部学习汇总&#xff1a; g_FreeRTOS: FreeRTOS学习笔记 (gitee.com) 之前我自己通过直接啃代码的方式对FreeRTOS也算是有了一点理解了&#xff0c;这次趁着些许闲暇翻看一下野火的FreeRTOS教程。一者算是一种复习&#xff1b;二者可能对自…

Leetcode刷题笔记题解(C++):面试题 08.07. 无重复字符串的排列组合

思路&#xff1a;因为字符之间互不相同&#xff0c;故使用全排列的方式去解题&#xff1b; 字符串长度为n&#xff0c;将第一个字母分别与后面每一个字母进行交换&#xff0c;生成n种不同的全排列&#xff1b;再用第二个元素与后面每一个元素进行交换&#xff0c;生成n - 1种不…

爪哇部落算法组2024新生赛热身赛题解

第一题&#xff08;签到&#xff09;&#xff1a; 1、题意&#xff1a; 2、题解: 我们观察到happynewyear的长度是12个字符&#xff0c;我们直接从前往后遍历0到n - 12的位置&#xff08;这里索引从0开始&#xff09;&#xff0c;使用C的substr()函数找到以i开头的长度为12的字…

git flow与分支管理

git flow与分支管理 一、git flow是什么二、分支管理1、主分支Master2、开发分支Develop3、临时性分支功能分支预发布分支修补bug分支 三、分支管理最佳实践1、分支名义规划2、环境与分支3、分支图 四、git flow缺点 一、git flow是什么 Git 作为一个源码管理系统&#xff0c;…

【转载】原生社区交友婚恋视频即时通讯双端APP源码 ONE兔2.0版

原生社区交友婚恋视频即时通讯双端APP源码下载ONE兔2.0版 包含后端、H5源码源码&#xff0c;Android源码&#xff0c;IOS源码

3.4-媒资管理之视频处理+xx-job分布式任务

文章目录 媒资管理6 视频处理6.1 需求6.1.1 总体需求6.7.3 FFmpeg 的基本使用6.7.4 视频处理工具类 6.2 分布式任务处理6.2.1 什么是分布式任务调度6.2.2 XXL-JOB介绍6.2.3 搭建XXL-JOB6.2.3.1 调度中心6.2.3.2 执行器6.2.3.3 执行任务 6.2.4 分片广播 6.3 技术方案6.3.1 作业分…

Java基础常见面试题总结-集合(一)

常见的集合有哪些&#xff1f; Java集合类主要由两个接口Collection和Map派生出来的&#xff0c;Collection有三个子接口&#xff1a;List、Set、Queue。 Java集合框架图如下&#xff1a; List代表了有序可重复集合&#xff0c;可直接根据元素的索引来访问&#xff1b;Set代表…

8个简约精美的WordPress外贸网站主题模板

Simplify WordPress外贸网站模板 Simplify WordPress外贸网站模板&#xff0c;简洁实用的外贸公司wordpress外贸建站模板。 查看演示 Invisible Trade WP外贸网站模板 WordPress Invisible Trade外贸网站模板&#xff0c;做进出口贸易公司官网的wordpress网站模板。 查看演…

Vue3编写简单的App组件(二)

一、Vue3页面渲染基本流程 1、入口文件 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><link rel"icon" href"/favicon.ico"><meta name"viewport" content"widthde…

js手写Promise(下)

目录 resolve与reject的调用时机封装优化 回调返回PromiseisPromise手动调用then 微队列catchresolverejectall传入的序列为空传入的值非Promise race完整的Promise代码 如果没有看过上半部分的铁铁可以看看这篇文章 js手写Promise&#xff08;上&#xff09; resolve与reject…

在Visual Studio中引用和链接OpenSceneGraph (OSG) 库

在Visual Studio中引用和链接OpenSceneGraph (OSG) 库&#xff0c;按照以下步骤操作&#xff1a; 构建或安装OSG库 下载OpenSceneGraph源代码&#xff08;如3.0版本&#xff09;并解压。使用CMake配置项目&#xff0c;为Visual Studio生成解决方案文件。通常您需要设置CMake中的…

Office2013下载安装教程,保姆级教程,附安装包和工具

前言 Microsoft Office是由Microsoft(微软)公司开发的一套基于 Windows 操作系统的办公软件套装。常用组件有 Word、Excel、PowerPoint、Access、Outlook等。 准备工作 1、Win7 及以上系统 2、提前准备好 Office 2013 安装包 安装步骤 1.鼠标右击【Office2013(64bit)】压缩…

Vue中 常用的修饰符有哪些

Vue是一款建立在JavaScript框架上的开源前端库&#xff0c;已经成为当今前端开发人员最喜爱的选择之一。它的简洁语法和强大的功能使得开发者可以轻松地构建交互性的网页应用程序。在Vue中&#xff0c;修饰符是一个重要的概念&#xff0c;它们可以帮助我们更好地控制和定制DOM元…

PV、UV、IP

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言1. PV1.1 PV 计算1.2 PV 的影响因素 2. UV2.1 UV 计算2.2UV 的影响因素 3. IP3.1 IP和UV①UV大于IP②UV小于IP 三者的关系PV 和 UV 前言 PV、UV、IP是我们在运…

深度学习入门笔记(九)自编码器

自编码器是一个无监督的应用&#xff0c;它使用反向传播来更新参数&#xff0c;它最终的目标是让输出等于输入。数学上的表达为&#xff0c;f(x) x&#xff0c;f 为自编码器&#xff0c;x 为输入数据。 自编码器会先将输入数据压缩到一个较低维度的特征&#xff0c;然后利用这…