IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 【算法java版10】:java实现对二进制数进行HDB3编码(第一个非零码为正数) -> 正文阅读

[数据结构与算法]【算法java版10】:java实现对二进制数进行HDB3编码(第一个非零码为正数)


一、题目描述

从文件中读入一段二进制数,进行HDB3编码(假设第一个非零码是 +1),打印输出在控制台

二、HDB3编码规则

HDB3码的全称是三阶高密度双极性码.它是AMI码的一种改进型,改进目的是为了保持AMI码的优点而克服其缺点,使连零个数不超过三个。其编码规则如下:

  • 先检查消息码的连零个数。当连零数目小于等于3时,则与AMI码的编码规则一样
  • 当连零数目超过3个时,则将每4个连零化作一小节,用 000V 替代,V (取值 +1 或 -1)应与其前一个相邻的非 0 脉冲的极性相同(因为这破坏了极性交替的规则,所以V称为破坏脉冲)。
  • 相邻的V码极性必须交替。当V码取值能满足 (2) 中的要求但不能满足此要求时,则将 0000B00V 替代,B的取值与后面的V的脉冲一致,用于解决此问题。因此,B称为调节脉冲
  • V 码后面的传号码极性也要交替。例如

消息码: 1 0 0 0 0 1 0 0 0 0 1 1 0 0 0 0 0 0 0 0 1 1
AMI码: -1 0 0 0 0 +1 0 0 0 0 -1 +1 0 0 0 0 0 0 0 0 -1 +1
HDB3码: -1 0 0 0 -V +1 0 0 0 +V -1 +1 -B 0 0 -V +B 0 0 +V -1 +1

其中:±V 脉冲 和 ±B 脉冲 与 ±1 脉冲波形相同,用 V 或 B 符号表示的目的是为了示意该非零码是由原信码中的 0 变换而来的。

四、解题思路

  • 当编码过程中没有出现连零的情况时,按照AMI编码算法,使 1 进行 正负交替,0 保持不变,具体我们可以定义变量来记录 1 出现的个数,以此题为例,我们的第奇数个1的极性为正,第偶数个1的极性就为负。
  • 当编码过程中出现了连零的情况,我们定义变量来记录连零的个数,当连零个数大于等于4时,将四个连零中的第四个零修改为 破坏码V 并判断 V 的极性。
  • 当只有一个破坏码时 V 的极性必定和其相邻的非零数的极性相同。
  • 当有多个 破坏码V 时,就要使 V 的极性交替,我们可以定义集合来存储破坏码,并将这次出现的破坏码和上一次出现的破坏码的极性进行比较,从而确定其极性。
  • 如果这次出现的破坏码极性和上次不同,则直接修改四个连零中的第四个零为破坏码,否则 我们要修改破坏码的极性并引入 调节码B ,B 的极性 和 修改后 V 的极性相同,然后 将 四个连零中的第一个零修改为调节码 B。
    注意:当出现破坏码以后,之后的编码过程中的 1 的极性要受到 前一个 1 或 V 的极性的影响。

三、核心示例代码

public void HDB3(char[] buffer, int len) {
        int count_0 = 0; // 记录连零的个数
        int count_1 = 0; // 记录1的个数
        int count_v = 0; // 记录破坏码v的个数
        int destroy_v = 1; // 破坏码v
        ArrayList<Integer> integers = new ArrayList<>(); // 存储破坏码
        String bin[] = new String[len];
        for (int i = 0; i < len; i++) {
            if (buffer[i] == '1') {  // 二进制数为 1 的情况
                count_0 = 0;
                count_1++;
                bin[i] = ((count_1 & 0x01) == 1) ? "1" : "-1"; // 第 奇数 个 1 的极性为正,第 偶数 个 1 的极性为负
            } else {
                count_0++;
                if (count_0 >= 4) {   // 当连零个数等于4时,第四个零变为破坏码
                    count_0 = 0;
                    count_v++;    // 破坏码的个数加一
                    if (count_v == 1) {       // 如果只有一个破坏码,则破坏码的极性一定和与之相邻的 1 的极性相同
                        destroy_v = ((count_1 & 0x01) == 1) ? 1 : -1;  // 破坏码和前一个相邻的 1 的极性相同(奇正,偶负)
                        integers.add(destroy_v);  // 保存破坏码
                        bin[i] = (destroy_v == 1) ? "V" : "-V";
                        count_1 = (destroy_v == 1) ? 1 : 2;  // 如果破坏码为 1(V)则 将 1 的个数 重置为 1(奇数),如果破坏码不是 1(V) 则 将 1 的个数 重置为 2(偶数)
                    } else if (count_v > 1) {  // 当破坏码个数超过两个,破坏码的极性和 1 或 V 的极性相关
                        if(bin[i - 4] == "1" || bin[i - 4] == "-1"){   // 当四个连零的二进制数所相邻的前一个数是 1 或 -1时,破坏码极性由 1 的极性确定
                            destroy_v = (bin[i - 4] == "1") ? 1 : -1;
                        }else if(bin[i - 4] == "V" || bin[i - 4] == "-V"){  // 当四个连零的二进制数所相邻的前一个数是 V 或 -V时,破会码极性由 V 的极性确定
                            destroy_v = (bin[i - 4] == "V") ? 1 : -1;
                        }
                        
                        if (destroy_v != integers.get(count_v - 2)) {   // 如果相邻的两个 破坏码极性不相同,则直接修改四个连零中的第四个零为破坏码
                            integers.add(destroy_v);
                            bin[i] = (destroy_v == 1) ? "V" : "-V";
                            count_1 = (destroy_v == 1) ? 1 : 2;
                        } else if (destroy_v == integers.get(count_v - 2)) { // 如果相邻两个破坏码极性相同,则修改后一个极性码的极性,并添加调节码赋值给连零中的第一个零
                            destroy_v = -destroy_v;     // 破坏码极性反转
                            integers.add(destroy_v);
                            bin[i] = (destroy_v == 1) ? "V" : "-V";        // 将修改后的破坏码赋值给连零中的第四个
                            bin[i - 3] = (destroy_v == 1) ? "B" : "-B";  // 将调节码(B)赋值给 连零中的第一个(调节码极性交替)
                            count_1 = (destroy_v == 1) ? 1 : 2;
                        }
                    }
                } else {
                    bin[i] = "0";
                }
            }
        }
        System.out.println("编码后:");
        for (String values : bin) {
            System.out.print(values + "  ");
        }
    }

四、完整代码

package com.easy.java;

import org.junit.Test;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;

/**
 * @ClassName HDB3Test
 * @Description 从文件读取二进制数,并进行HDB3编码,打印输出到控制台(假设编码后第一个非零码为正数)
 * @Author wk
 * @Date 2022/3/9 8:54
 * @Version 1.0
 */
public class HDB3Test {

    @Test
    public void HDB3Test() {
        FileReader fileReader = null;
        try {
            fileReader = new FileReader(new File("HDB3.txt"));
            char[] buffer = new char[1024];
            int len = 0;
            while ((len = fileReader.read(buffer)) != -1) {
                System.out.println("编码前:");
                for (char key : buffer) {
                    System.out.print(key + "  ");
                }
                System.out.println();
                HDB3(buffer, len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (fileReader != null) {
                    fileReader.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public void HDB3(char[] buffer, int len) {
        int count_0 = 0; // 记录连零的个数
        int count_1 = 0; // 记录1的个数
        int count_v = 0; // 记录破坏码v的个数
        int destroy_v = 1; // 破坏码v
        ArrayList<Integer> integers = new ArrayList<>(); // 存储破坏码
        String bin[] = new String[len];
        for (int i = 0; i < len; i++) {
            if (buffer[i] == '1') {  // 二进制数为 1 的情况
                count_0 = 0;
                count_1++;
                bin[i] = ((count_1 & 0x01) == 1) ? "1" : "-1"; // 第 奇数 个 1 的极性为正,第 偶数 个 1 的极性为负
            } else {
                count_0++;
                if (count_0 >= 4) {   // 当连零个数等于4时,第四个零变为破坏码
                    count_0 = 0;
                    count_v++;    // 破坏码的个数加一
                    if (count_v == 1) {       // 如果只有一个破坏码,则破坏码的极性一定和与之相邻的 1 的极性相同
                        destroy_v = ((count_1 & 0x01) == 1) ? 1 : -1;  // 破坏码和前一个相邻的 1 的极性相同(奇正,偶负)
                        integers.add(destroy_v);  // 保存破坏码
                        bin[i] = (destroy_v == 1) ? "V" : "-V";
                        count_1 = (destroy_v == 1) ? 1 : 2;  // 如果破坏码为 1(V)则 将 1 的个数 重置为 1(奇数),如果破坏码不是 1(V) 则 将 1 的个数 重置为 2(偶数)
                    } else if (count_v > 1) {  // 当破坏码个数超过两个,破坏码的极性和 1 或 V 的极性相关
                        if(bin[i - 4] == "1" || bin[i - 4] == "-1"){   // 当四个连零的二进制数所相邻的前一个数是 1 或 -1时,破坏码极性由 1 的极性确定
                            destroy_v = (bin[i - 4] == "1") ? 1 : -1;
                        }else if(bin[i - 4] == "V" || bin[i - 4] == "-V"){  // 当四个连零的二进制数所相邻的前一个数是 V 或 -V时,破会码极性由 V 的极性确定
                            destroy_v = (bin[i - 4] == "V") ? 1 : -1;
                        }

                        if (destroy_v != integers.get(count_v - 2)) {   // 如果相邻的两个 破坏码极性不相同,则直接修改四个连零中的第四个零为破坏码
                            integers.add(destroy_v);
                            bin[i] = (destroy_v == 1) ? "V" : "-V";
                            count_1 = (destroy_v == 1) ? 1 : 2;
                        } else if (destroy_v == integers.get(count_v - 2)) { // 如果相邻两个破坏码极性相同,则修改后一个极性码的极性,并添加调节码赋值给连零中的第一个零
                            destroy_v = -destroy_v;     // 破坏码极性反转
                            integers.add(destroy_v);
                            bin[i] = (destroy_v == 1) ? "V" : "-V";        // 将修改后的破坏码赋值给连零中的第四个
                            bin[i - 3] = (destroy_v == 1) ? "B" : "-B";  // 将调节码(B)赋值给 连零中的第一个(调节码极性交替)
                            count_1 = (destroy_v == 1) ? 1 : 2;
                        }
                    }
                } else {
                    bin[i] = "0";
                }
            }
        }
        System.out.println("编码后:");
        for (String values : bin) {
            System.out.print(values + "  ");
        }
    }
}

五、测评结果

  • 测评实例1:
    1011000000000101

在这里插入图片描述

  • 测评实例2:
    1000010000110000000011

在这里插入图片描述

  • 测评实例3:
    010111000011010110000011110101110000101110000001011000000000000111010

在这里插入图片描述

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-03-12 17:47:47  更:2022-03-12 17:52:07 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 13:40:40-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码