【算法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

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

☆*往事随風*☆

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值