哈夫曼编码(Java图形界面实现)

                                      4.1 哈夫曼编/译码器

4.1.1 项目简介
哈夫曼编/译码器问题:利用哈夫曼编码(加密)进行信息通讯可以大大提高信道利用率,缩短信息传输时间,降低传输成本,保证报文安全。这要求在发送端通过一个编码系统对待传数据预先编码;在接收端将传来的数据进行译码(解密)。设计要求如下:
一个完整的系统应具有以下功能:
(1)初始化 (Initialization):从终端读入n个字符,建立哈夫曼树;
(2)编码 (Coding):利用已建好的哈夫曼树,对字符进行编码,然后将正文编码结果存入文件codefile中;
(3)译码 (Decoding):利用已建好的哈夫曼树将文件codefile中的代码进行译码,结果存入文件textfile中。

建议:

  1. 将本次实验与《计算机网络》或者《计算机组成原理》中的通讯协议相结合,对报文进行加密\解密。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

代码清单
在这里插入图片描述
MainJFrame

package ex4_Huffman;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

/**
 * @Version 1.0
 * @Author:刘昕
 * @Date:2021/3/30 11:06
 * @Software: IntelliJ IDEA
 * @Content:
 */
public class MainJFrame extends JFrame implements ActionListener {
    public static Label text;
    JPanel functionPanel, textPanel, loadPanel, encodePanel, decodePanel, plainTextPanel, encodeTextPanel, decodeTextPanel;
    static JTextArea plainText;
    static JTextArea encodeText;
    static JTextArea decodeText;
    JScrollPane plainTextScroll, encodeTextScroll, decodeTextScroll;
    JButton loadButton, encodeButton, decodeButton;
    JTextField path;
    JLabel pathLabel;
    //存储明文
    static String plain_text = "";
    public MainJFrame(){
        super("哈夫曼编码/译码");
        this.setLayout(new BorderLayout());
        this.setSize(900, 600);
        this.setLocationRelativeTo(null);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        //添加功能面板
        functionPanel = new BackgroundPanel();
        functionPanel.setBorder(BorderFactory.createTitledBorder("功能区"));
        loadPanel = new JPanel();
        encodePanel = new JPanel();
        decodePanel = new JPanel();
        loadButton = new JButton("加载");
        loadButton.addActionListener(this);
        encodeButton = new JButton("编码");
        encodeButton.addActionListener(this);
        decodeButton = new JButton("译码");
        decodeButton.addActionListener(this);
        pathLabel = new JLabel("路径:");
        path = new JTextField(26);
        this.getContentPane().add(BorderLayout.NORTH, functionPanel);
        functionPanel.add(loadPanel);
        functionPanel.add(encodePanel);
        functionPanel.add(decodePanel);
        loadPanel.add(pathLabel);

        loadPanel.add(path);
        loadPanel.add(loadButton);
        encodePanel.add(encodeButton);
        decodePanel.add(decodeButton);
        //添加文本面板
        textPanel = new JPanel(new GridLayout(1,3));
        textPanel.setBorder(BorderFactory.createTitledBorder("文本区"));
        textPanel.setBackground(Color.GRAY);
        this.getContentPane().add(BorderLayout.CENTER, textPanel);

        plainTextPanel = new BackgroundPanel();
        plainTextPanel.setBorder(BorderFactory.createTitledBorder("明文"));
        textPanel.add(plainTextPanel);
        encodeTextPanel = new BackgroundPanel();
        encodeTextPanel.setBorder(BorderFactory.createTitledBorder("编码"));
        textPanel.add(encodeTextPanel);
        decodeTextPanel = new BackgroundPanel();
        decodeTextPanel.setBorder(BorderFactory.createTitledBorder("译文"));
        textPanel.add(decodeTextPanel);

        plainText = new JTextArea(57,29);
        plainText.setBackground(Color.pink);
        plainText.setLineWrap(true);
        plainText.setFont(new Font("楷体",Font.BOLD,16));
        encodeText = new JTextArea(57,29);
        encodeText.setBackground(Color.pink);
        encodeText.setLineWrap(true);
        encodeText.setFont(new Font("楷体",Font.BOLD,16));
        decodeText = new JTextArea(57,29);
        decodeText.setBackground(Color.pink);
        decodeText.setLineWrap(true);
        decodeText.setFont(new Font("楷体",Font.BOLD,16));

        plainTextScroll = new JScrollPane(plainText);
        plainTextScroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
        encodeTextScroll = new JScrollPane(encodeText);
        encodeTextScroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
        decodeTextScroll = new JScrollPane(decodeText);
        decodeTextScroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);

        plainTextPanel.add(plainTextScroll);
        encodeTextPanel.add(encodeTextScroll);
        decodeTextPanel.add(decodeTextScroll);

        this.setVisible(true);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        //加载明文按键
        if (e.getSource() == loadButton){
            String Path = path.getText();
            ReadFile.readTextFile(Path);
        }
        //输出编码按键
        else if (e.getSource() == encodeButton){
            new Huffman();
            Huffman.encodeFunc();
        }
        //输出译码按键
        else if (e.getSource() == decodeButton){
            Huffman.decodeFunc();
        }

    }
    public static void main(String[] args){
        new MainJFrame();
    }
}

Node

package ex4_Huffman;

/**
 * @Version 1.0
 * @Author:刘昕
 * @Date:2021/3/30 10:55
 * @Software: IntelliJ IDEA
 * @Content: class Node
 */
public class Node {
    String ch;
    int num;
    Node leftChild = null;
    Node rightChild = null;

    public Node(){}
    public Node(String ch, int num) {
        this.ch = ch;
        this.num = num;
    }
    @Override
    public String toString() {
        return "Node{" +
                "ch='" + ch + '\'' +
                ", num=" + num +
                '}';
    }

    public String getCh() {
        return ch;
    }

    public void setCh(String ch) {
        this.ch = ch;
    }

    public int getNum() {
        return num;
    }

    public void setNum(int num) {
        this.num = num;
    }

    public Node getLeftChild() {
        return leftChild;
    }

    public void setLeftChild(Node leftChild) {
        this.leftChild = leftChild;
    }

    public Node getRightChild() {
        return rightChild;
    }

    public void setRightChild(Node rightChild) {
        this.rightChild = rightChild;
    }
    public int compareTo(Node o2){
        return this.getNum() - o2.getNum();
    }
}

Huffman

package ex4_Huffman;

import ex1_学生报考系统.Student;

import java.util.*;

/**
 * @Version 1.0
 * @Author:刘昕
 * @Date:2021/3/30 10:59
 * @Software: IntelliJ IDEA
 * @Content:
 */
public class Huffman {

    //字符及出现频率放入哈希表中
    HashMap<String, Integer> map = new HashMap<>();
    //编码
    static HashMap<String, String> encodeMap = new HashMap<>();
    //译码
    static HashMap<String, String> decodeMap = new HashMap<>();
    //哈希表中的数据放入数组中, 方便排序建树
    ArrayList<Node> array = new ArrayList<>();
    static Node tree;

    public Huffman(){
        //把字符放入到哈希表中, key代表字符, value是出现频率
        for (int i = 0; i < MainJFrame.plain_text.length(); i++){
            String ch = MainJFrame.plain_text.charAt(i) + "";
            //这个字符在map中没有,放入map
            if (map.get(ch) == null){
                map.put(ch, 1);
            }
            //这个字符在map中存在,value+1重新放入
            else{
                map.replace(ch, map.get(ch), map.get(ch)+1 );
            }
        }
        //哈希表中的数据放入数组中
        for (Map.Entry<String, Integer> t : map.entrySet()){
            Node temp = new Node(t.getKey(), t.getValue());
            array.add(temp);
        }
        //进行排序
        sortFunc();
        //n为叶子节点数目, n2为2度节点数目
        int n = array.size();
        int n2 = n - 1;

        //建立哈夫曼树
        for (int j = 0; j < n2; j++){
            Node t  = new Node(null,  array.get(0).getNum()+array.get(1).getNum());
            t.leftChild = array.get(0);
            t.rightChild = array.get(1);
            array.add(t);

            array.remove(0);
            array.remove(0);
            sortFunc();
        }
        tree = array.get(0);
    }

    public void sortFunc(){
        Collections.sort(array, new Comparator<Node>() {
            @Override
            public int compare(Node o1, Node o2) {
                return o1.compareTo(o2);
            }
        });
    }
    //编码函数
    public static void encodeFunc(){
        encodeFunc2(Huffman.tree, "", encodeMap, decodeMap);
        for (int i = 0; i < MainJFrame.plain_text.length(); i++){
            MainJFrame.encodeText.append(encodeMap.get(MainJFrame.plain_text.charAt(i)+""));
        }
    }
    public static void encodeFunc2(Node tree, String code, HashMap<String, String> encodeMap, HashMap<String, String> decodeMap){
        if (tree.rightChild == null ){
            //编码表
            encodeMap.put(tree.ch, code);
            //译码表

            decodeMap.put(code, tree.ch);
        }
        else{
            encodeFunc2(tree.leftChild, code + "0", encodeMap, decodeMap);
            encodeFunc2(tree.rightChild, code + "1", encodeMap, decodeMap);
        }
    }
    //译码函数
    public static void decodeFunc(){
        String s_decodeFunc = MainJFrame.encodeText.getText();
        int j = 0;
        for (int i = 0; i < s_decodeFunc.length(); ){
            j++;
            String s_decodeFunc2 = s_decodeFunc.substring(i, j);
            if (decodeMap.get(s_decodeFunc2) != null){
                MainJFrame.decodeText.append(decodeMap.get(s_decodeFunc2));
                i = j;
            }
        }
    }
}

BackGroundPanel

package ex4_Huffman;


import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.ActionEvent;

import javax.swing.ImageIcon;
import javax.swing.JPanel;

/**
 * @Version 1.0
 * @Author:刘昕
 * @Date:2021/3/30 11:55
 * @Software: IntelliJ IDEA
 * @Content:
 */
public class BackgroundPanel extends JPanel {

    ImageIcon icon;
    Image img;

    public BackgroundPanel() {
        //  /img/HomeImg.jpg 是存放在你正在编写的项目的bin文件夹下的img文件夹下的一个图片
        icon = new ImageIcon(getClass().getResource("./Imag/3.jpg"));
        img = icon.getImage();
    }

    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        //下面这行是为了背景图片可以跟随窗口自行调整大小,可以自己设置成固定大小
        g.drawImage(img, 0, 0, this.getWidth(), this.getHeight(), this);
    }

}

ReadFile

package ex4_Huffman;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;

/**
 * @Version 1.0
 * @Author:刘昕
 * @Date:2021/3/30 14:28
 * @Software: IntelliJ IDEA
 * @Content:
 */
public class ReadFile {
    public static void readTextFile(String path){
        String encoding = "utf-8";
        try{
            File file = new File(path);
            if (file.isFile() && file.exists()){
                InputStreamReader read = new InputStreamReader(new FileInputStream(file),encoding);
                BufferedReader bufferedReader = new BufferedReader(read);
                String lineTxt = null;
                while((lineTxt = bufferedReader.readLine()) != null){
                    MainJFrame.plainText.append(lineTxt);
                    MainJFrame.plain_text += lineTxt;
                }
                read.close();
            }
            else{
                System.out.println("文件不存在!");
            }

        }
        catch(Exception e){
            System.out.println("读取文件出错");
            e.printStackTrace();
        }
    }
}

源代码链接:
链接:https://pan.baidu.com/s/166JJ1cdQ2fqWoYg_BqtVGA
提取码:Code

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个C++实现的哈编译码器的示例代码: ```cpp #include <iostream> #include <queue> #include <unordered_map> using namespace std; // 哈树节点 struct Node { char data; int freq; Node* left; Node* right; Node(char data, int freq) { this->data = data; this->freq = freq; left = right = nullptr; } }; // 用于比较节点频度的函数对象 struct Compare { bool operator()(Node* left, Node* right) { return left->freq > right->freq; } }; // 构建哈树 Node* buildHuffmanTree(const unordered_map<char, int>& freqMap) { priority_queue<Node*, vector<Node*>, Compare> pq; // 将每个字符的频度作为节点加入优先队列 for (const auto& pair : freqMap) { pq.push(new Node(pair.first, pair.second)); } // 从优先队列中取出两个频度最小的节点,合并为一个新节点,直到只剩下一个节点 while (pq.size() > 1) { Node* left = pq.top(); pq.pop(); Node* right = pq.top(); pq.pop(); Node* newNode = new Node('$', left->freq + right->freq); newNode->left = left; newNode->right = right; pq.push(newNode); } return pq.top(); } // 递归构建哈编码表 void buildHuffmanCodes(Node* root, string code, unordered_map<char, string>& codes) { if (root == nullptr) { return; } if (root->data != '$') { codes[root->data] = code; } buildHuffmanCodes(root->left, code + "0", codes); buildHuffmanCodes(root->right, code + "1", codes); } // 哈编码 string encode(const string& text, const unordered_map<char, string>& codes) { string encodedText = ""; for (char c : text) { encodedText += codes.at(c); } return encodedText; } // 哈译码 string decode(const string& encodedText, Node* root) { string decodedText = ""; Node* curr = root; for (char bit : encodedText) { if (bit == '0') { curr = curr->left; } else { curr = curr->right; } if (curr->left == nullptr && curr->right == nullptr) { decodedText += curr->data; curr = root; } } return decodedText; } // 打印哈树 void printHuffmanTree(Node* root) { if (root == nullptr) { return; } cout << root->data << " - " << root->freq << endl; printHuffmanTree(root->left); printHuffmanTree(root->right); } int main() { string text = "hello world"; // 统计字符频度 unordered_map<char, int> freqMap; for (char c : text) { freqMap[c]++; } // 构建哈树 Node* root = buildHuffmanTree(freqMap); // 构建哈编码表 unordered_map<char, string> codes; buildHuffmanCodes(root, "", codes); // 哈编码 string encodedText = encode(text, codes); cout << "Encoded text: " << encodedText << endl; // 哈译码 string decodedText = decode(encodedText, root); cout << "Decoded text: " << decodedText << endl; // 打印哈树 cout << "Huffman tree:" << endl; printHuffmanTree(root); return 0; } ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值