【数据结构课设】数据压缩与解压缩(java实现 javafx实现GUI)

目录

一、问题描述

二、基本要求

三、逻辑结构设计

四、存储结构设计

五、主要操作设计

六、技术难点与解决方法

七、实现与展示

八、详细代码


一、问题描述

利用哈夫曼编码进行信息通讯可以大大提高信道利用率,缩短信息传输时间,降低传输成本。但是,这要求在发送端通过一个编码系统对待传数据预先编码;在接收端将传来的数据进行译码(复原)。对于双工信道 (即可以双向传输信息的信道),每端都需要一个完整的编/译码系统。试对于任意的一段文本(可能是直接输入的,也可能是保存在本地文件中或者网络上的),写一个哈夫曼码的编译码系统。

二、基本要求

一个完整的系统应具有以下功能:

(l)I:初始化 (Initialization)。从终端读入字符集大小 n,及 n 个字符和 m 个权值,建立哈夫曼树,并将它存于文件 hfmtree 中。

(2)C:编码 (Coding)。利用已建好的哈夫曼树(如不在内存,则从文件 hfmtree 中读入),对文件 tobetrans 中的正文进行编码,然后将结果存入文件 codefile 中。

(3)D:解码(Decoding)。利用已建好的哈夫曼树将文件 codefile 中的代码进行译码,结果存入文件 textfile 中。

(4)P:打印代码文件 (Print)。将文件 codefile 以紧凑格式显示在终端上,每行 50 个代码。同时将此字符形式的编码文件写入文件 codeprint 中。

(5)T:打印哈夫曼树 (Tree printing)。将已在内存中的哈夫曼树以直观的方式 (树或凹入表形式)显示在终端上,同时将此字符形式的哈夫曼树写入文件 treeprint 中。

三、逻辑结构设计

  Huffman编码过程中会根据字符出现的概率高低来构造一棵树,存在一对多的关系,直观呈现“层次”特征,故Huffman编码用树形结构。

四、存储结构设计

  Huffman树结构上有左右子结点的关系,故可以让一个存储结点包含其子树的邻接关系,也就是用链式存储结构。

 图Huffman UML

 

五、主要操作设计

1.编码:当Huffman树tree初始化之后,tree调用coding()方法,获取单个字符与编码的关系,然后tree调用encoding()方法,与文件中的所有字符进行比对,完成输入内容的编码。

2. 解码:map中存放着字符与编码的关系,将传进来的字符串从头到尾一个一个地与map中的数据进行比对,发现相同,就将其输入到textfile中。

六、技术难点与解决方法

难点:实现过程中哈夫曼树的打印用JavaFX比较困难。

解决方法:在createPrintTree方法,传入相关参数,node是该哈夫曼树的root结点,row是X轴的偏移量,col是Y轴的偏移量,deep是树的深度。进入方法之后,根据坐标的计算,分别将对应的结点放在相应的位置。然后递归调用,先后处理父节点的左右孩子。

七、实现与展示

八、详细代码

 


import java.io.*;
import java.util.*;

public class Coding {
    private Map<String,Object> codes;
//当Huffman树tree初始化之后,tree调用coding()方法,获取单个字符与编码的关系,然后tree调用encoding()方法,与文件中的所有字符进行比对,完成输入内容的编码
    public Coding(){
        codes=new HashMap<>();
    }

    public void buildHuffmanCodes() throws Exception{
        HuffmanTreeNode Htree=readTree();
        String buildCode="";
        code(Htree,buildCode,codes);
    }

    private void code(HuffmanTreeNode Htree,String buildCode,Map<String ,Object> codes){
        if (Htree!=null){
            if (Htree.getLeftChild()==null && Htree.getRightChild()==null){
                codes.put(buildCode,Htree.getData());
            }
            code(Htree.getLeftChild(),buildCode+"0",codes);
            code(Htree.getRightChild(),buildCode+"1",codes);
        }
    }

    private HuffmanTreeNode readTree() throws Exception{
        ObjectInputStream ois=new ObjectInputStream(new FileInputStream("hfmtree.txt"));
        try {
            return (HuffmanTreeNode) ois.readObject();
        } catch (IOException e){
            System.out.println("读取文件失败!");
            return null;
        }
    }

    public void save() throws Exception{
        DataOutputStream os=new DataOutputStream(new FileOutputStream("codefile.txt"));
        List<Object> text=readText();
        Set<String > keys=codes.keySet();
        try {
            for (int i=0;i<text.size();i++){
                for (String key: keys){
                    if (text.get(i).equals(codes.get(key))) {
                         os.writeUTF(key);
                         break;
                    }
                }
            }
            os.close();
            System.out.println("编码成功!已保存至文件(codefile.txt)!");
        } catch (IOException e){
            System.out.println("保存失败!");
        }
    }

    private List<Object> readText() throws Exception{
        DataInputStream is=new DataInputStream(new FileInputStream("tobetrans.txt"));
        List<Object> text=new ArrayList<>();
        try{
            while (true){
                text.add(is.readChar());
            }
        } catch (EOFException e){}
        return text;
    }

    public Map<String, Object> getCodes() {
        return codes;
    }

    public void setCodes(Map<String, Object> codes) {
        this.codes = codes;
    }
}
package experimentFinal2;

import java.io.*;
import java.util.*;

public class Decoding {
    private Map<String,Object> codes;//map中存放着字符与编码的关系,将传进来的字符串从头到尾一个一个地与map中的数据进行比对,发现相同,就将其输入到textfile中。

    public Decoding() throws Exception{
        codes=createMap();
    }

    public Map<String,Object> createMap() throws Exception{
        codes=new HashMap<>();
        List<String> code=readCode();
        for (int i=0;i<code.size();i++) {
            codes.put(code.get(i),null);
        }
        return codes;
    }

    public void DecodingHuffmanTree() throws Exception{
        HuffmanTreeNode Htree=readTree();
        String buildCode="";
        decode(Htree,buildCode,codes);
    }

    private void decode(HuffmanTreeNode Htree,String buildCode,Map<String ,Object> codes){
        if (Htree!=null){
            if (Htree.getLeftChild()==null && Htree.getRightChild()==null){
                codes.put(buildCode,Htree.getData());
            }
            decode(Htree.getLeftChild(),buildCode+"0",codes);
            decode(Htree.getRightChild(),buildCode+"1",codes);
        }
    }

    private HuffmanTreeNode readTree() throws Exception{
        ObjectInputStream ois=new ObjectInputStream(new FileInputStream("hfmtree.txt"));
        try {
            return (HuffmanTreeNode) ois.readObject();
        } catch (IOException e){
            System.out.println("读取文件失败!");
            return null;
        }
    }

    public List<String> readCode() throws Exception{
        DataInputStream is=new DataInputStream(new FileInputStream("codefile.txt"));
        List<String> codes=new ArrayList<>();
        try {
            while (true){
               codes.add(is.readUTF());
            }
        } catch (EOFException e){}
        return codes;
    }

    public void save() throws Exception{
        DataOutputStream oos=new DataOutputStream(new FileOutputStream("textfile.txt"));
        List<String> code=readCode();
        Set<String> keys=codes.keySet();
        try {
            for (int i=0;i<code.size();i++){
                for (String key: keys){
                    if (code.get(i).equals(key)) {
                        oos.writeChar((char)codes.get(key));
                        break;
                    }
                }
            }
            oos.close();
            System.out.println("解码成功!已保存至文件(textfile.txt)!");
        } catch (IOException e){
            System.out.println("保存失败!");
        }
    }

    public Map<String, Object> getCodes() {
        return codes;
    }

    public void setCodes(Map<String, Object> codes) {
        this.codes = codes;
    }
}
package experimentFinal2;

import java.io.*;
import java.util.ArrayList;
import java.util.List;

public class HuffmanTree {
    private HuffmanTreeNode Htree;
    private int leafNode=0;
    private int depth=0;


    public HuffmanTree(){
        Htree=new HuffmanTreeNode();
    }

    public void createHuffmanTree() throws Exception{
        List<HuffmanTreeNode> leafNodes=readFromlFile();
        this.leafNode=leafNodes.size();
        if (leafNode==0){
            return;
        }

        while (leafNodes.size()>1){
            sort(leafNodes);//排序
            HuffmanTreeNode LChild=leafNodes.get(0);//左孩子为0
            HuffmanTreeNode RChild=leafNodes.get(1);//右孩子为1
            HuffmanTreeNode parent=new HuffmanTreeNode(null,LChild.getWeight()+RChild.getWeight());
            //双亲的权值合为左孩子、右孩子权值的合
            parent.setLeftChild(LChild);
            parent.setRightChild(RChild);
            leafNodes.remove(0);
            leafNodes.remove(0);
            leafNodes.add(parent);
        }
        Htree=leafNodes.get(0);
    }

    public void creatNew(String s) throws Exception {
        DataOutputStream os=new DataOutputStream(new FileOutputStream("tobetrans.txt"));
        for (int i=0;i<s.length();i++){
            os.writeChar(s.charAt(i));
        }
        os.close();
    }

    private List<HuffmanTreeNode> readFromlFile() throws Exception{
        DataInputStream is=new DataInputStream(new FileInputStream("tobetrans.txt"));
        List<HuffmanTreeNode> leafNodes=new ArrayList<>();
        HuffmanTreeNode p;
        try {
            while (true) {
                //统计字符在文档中出现的概率 概率的大小作为权值
                p=new HuffmanTreeNode();
                char data=is.readChar();
                int index=weighting(leafNodes,data);
                if (index!=-1){
                    leafNodes.get(index).setWeight(leafNodes.get(index).getWeight()+1);
                } else {
                    p.setData(data);
                    p.setWeight(1);
                    leafNodes.add(p);
                }
            }
        } catch (EOFException e){}
        is.close();
        return leafNodes;
    }

    public void print() throws Exception{
        List<HuffmanTreeNode> leafNodes=readFromlFile();
        System.out.println("文件字符集:");
        for (HuffmanTreeNode node: leafNodes){
            System.out.println("字符:"+node.getData()+"   权值:"+node.getWeight());
        }
        System.out.println();
    }

    private int weighting( List<HuffmanTreeNode> leafNodes,char c){
        //找到相应的叶子结点并返回下标
        for (int i=0;i<leafNodes.size();i++){
            if (leafNodes.get(i).getData().equals(c)){
                return i;
            }
        }
        return -1;
    }

    private void sort(List<HuffmanTreeNode> leafNodes){
        //按权值排序
        for (int i=0;i<leafNodes.size();i++){
            for (int j=0;j<leafNodes.size()-1-i;j++){
                if (leafNodes.get(j).getWeight()>leafNodes.get(j+1).getWeight()){
                    HuffmanTreeNode p=leafNodes.get(j);
                    leafNodes.set(j,leafNodes.get(j+1));
                    leafNodes.set(j+1,p);
                }
            }
        }
    }



    public void save() throws Exception{
        ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("hfmtree.txt"));
        try{
            oos.writeObject(Htree);
            oos.close();
            System.out.println("初始化成功!哈夫曼树已创建!");
        } catch (IOException e){
            System.out.println(e.getMessage());
        }
    }

    public void deepCount(HuffmanTreeNode Htree,int count){
        //求深度
        if (Htree!=null){
            count++;
            if (Htree.getLeftChild()==null && Htree.getRightChild()==null){
                //如果没有孩子
                if (count>this.depth){
                    this.depth=count;
                }
            }
            deepCount(Htree.getLeftChild(),count);
            deepCount(Htree.getRightChild(),count);
        }
    }

    public HuffmanTreeNode getHtree() {
        return Htree;
    }

    public void setHtree(HuffmanTreeNode htree) {
        Htree = htree;
    }

    public int getLeafNode() {
        return leafNode;
    }

    public void setLeafNode(int leafNode) {
        this.leafNode = leafNode;
    }

    public int getDepth() {
        int count=0;
        deepCount(this.Htree,count);
        return depth;
    }

    public void setDepth(int depth) {
        this.depth = depth;
    }
}
package experimentFinal2;

import java.io.Serializable;

public class HuffmanTreeNode implements Serializable {
    private Object data;
    private int weight=0;
    private HuffmanTreeNode leftChild=null;
    private HuffmanTreeNode rightChild=null;
    private int parent=-1;

    public HuffmanTreeNode(){
    }

    public HuffmanTreeNode(Object data,int weight){
        this(data,weight,null,null,-1);
    }

    public HuffmanTreeNode(Object data,int weight,HuffmanTreeNode leftChild,HuffmanTreeNode rightChild, int parent){
        this.data=data;
        this.weight=weight;//权值
        this.leftChild=leftChild;//左孩子
        this.rightChild=rightChild;//右孩子
        this.parent=parent;//双亲
    }

    public Object getData() {
        return data;
    }

    public void setData(Object data) {
        this.data = data;
    }

    public int getWeight() {
        return weight;
    }

    public void setWeight(int weight) {
        this.weight = weight;
    }

    public HuffmanTreeNode getLeftChild() {
        return leftChild;
    }

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

    public HuffmanTreeNode getRightChild() {
        return rightChild;
    }

    public void setRightChild(HuffmanTreeNode rightChild) {
        this.rightChild = rightChild;
    }

    public int getParent() {
        return parent;
    }

    public void setParent(int parent) {
        this.parent = parent;
    }
}
package experimentFinal2;

import java.io.*;

public class Print {
    private StringBuilder code;

    public Print() throws Exception{
        code=readCode();
    }
    public void printCodefile(){
        System.out.println("codefile.txt:");
        int begin=0;
        int end=50;
        for (;begin<code.length();begin=begin+50,end=end+50){
            if (end>code.length()){
                end=code.length();
            }
            System.out.println(code.substring(begin,end));
        }
    }

    private StringBuilder readCode() throws Exception{
        DataInputStream is=new DataInputStream(new FileInputStream("codefile.txt"));
        StringBuilder codes=new StringBuilder();
        try {
            while (true){
                codes.append(is.readUTF());
            }
        } catch (EOFException e){}
        return codes;
    }

    public void save() throws Exception{
        DataOutputStream os=new DataOutputStream(new FileOutputStream("codeprint.txt"));
        try {
            os.writeUTF(code.toString());
            os.close();
            System.out.println("代码已写入文件(codeprint.txt)!");
        } catch (IOException e){
            System.out.println("保存失败!");
        }
    }
}
package experimentFinal2;

import java.util.Scanner;

public class Test {
    public static void main(String[] args) throws  Exception{
        System.out.println("数据压缩与解压缩:");
        int choice;
        boolean running=true;
        while (running){
            choice=menu();
            switch (choice){
                case 1: initialization();break;
                case 2: coding();break;
                case 3: decoding();break;
                case 4: print();break;
                case 5: treePrint();break;
                case 6: running=false;
            }
        }
        System.out.println("谢谢使用");
    }

    public static int menu(){
        while (true){
            System.out.println("-----------------------------------");
            System.out.println("请选择功能:                        ");
            System.out.println("   1. I:初始化(Initialization)    ");
            System.out.println("   2. C:编码(Coding)              ");
            System.out.println("   3. D:解码(Decoding)            ");
            System.out.println("   4. P:打印代码文件(Print)        ");
            System.out.println("   5. T:打印哈夫曼树(Tree printing)");
            System.out.println("   6. 退出                          ");
            System.out.println("-----------------------------------");
            System.out.print("请输入您的选择:");
            Scanner input =new Scanner(System.in);
            int choice=input.nextInt();
            if (choice>0 && choice<7){
                return choice;
            } else {
                System.out.println("该选项不存在,请重新输入!\n");
            }
        }
    }

    public static void initialization() throws Exception{
        Scanner input=new Scanner(System.in);
        HuffmanTree Htree=new HuffmanTree();
        System.out.println("--------------------------");
        System.out.println("1.新建字符集   2.读取文件");
        System.out.println("--------------------------");
        System.out.print("请输入您的选择:");
        int choice;
        while (true){
            choice=input.nextInt();
            if (choice==1 || choice==2){
                break;
            }
            System.out.println("选择错误,重新选择!");
        }
        if (choice==1){
            System.out.print("新字符集:");
            String s=input.next();
            Htree.creatNew(s);
        }
        Htree.print();
        Htree.createHuffmanTree();
        Htree.save();
    }

    //当Huffman树tree初始化之后,tree调用coding()方法,获取单个字符与编码的关系
    public static void coding() throws Exception{
        Coding coding=new Coding();
        coding.buildHuffmanCodes();
        coding.save();
    }

    public static void decoding() throws Exception{
        Decoding decoding=new Decoding();
        decoding.DecodingHuffmanTree();
        decoding.save();
    }

    public static void print() throws Exception{
        Print print=new Print();
        print.printCodefile();
        print.save();
    }

    public static void  treePrint() throws Exception{
        TreePrinting treePrinting=new TreePrinting();
        TreePrinting.main();
        treePrinting.save();
    }
}
package experimentFinal2;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Line;
import javafx.scene.text.Text;
import javafx.stage.Stage;
import java.io.DataOutputStream;
import java.io.FileOutputStream;


public class TreePrinting extends Application {
    private String codes="";

    public static void main(){
            Application.launch();
    }

    public BorderPane pane() throws Exception{
        HuffmanTree Htree=new HuffmanTree();

        Pane pane=new Pane();
        GridPane gridPane=new GridPane();
        gridPane.setHgap(20);//水平间距
        gridPane.setVgap(20);//垂直间距

        BorderPane borderPane=new BorderPane();
        Text text=new Text("Enter a text");
        TextField textField=new TextField();
        textField.setMinWidth(800);
        Button button=new Button("Show Huffman Tree");
        button.setOnAction(e->{
            try {
                pane.getChildren().clear();
                Htree.creatNew(textField.getText());
                Htree.createHuffmanTree();
                Htree.save();
                Coding coding=new Coding();
                coding.buildHuffmanCodes();
                coding.save();
                Decoding decoding=new Decoding();

                String s=textField.getText()+" is encoded to ";
                for (String str: decoding.readCode()){
                    this.codes+=str;
                }
                s+=codes;
                if (textField.getText() .equals("")){
                    s="please enter a text !";
                }
                createTree(Htree.getHtree(),Htree.getDepth()*50,pane,50,400);

                Alert alert = new Alert(Alert.AlertType.INFORMATION);
                alert.titleProperty().set("Encode Text to Bits");
                alert.headerTextProperty().set(s);
                alert.showAndWait();

            } catch (Exception ex) {
                ex.printStackTrace();
            }
        });
        FlowPane flowPane=new FlowPane();
        flowPane.getChildren().addAll(text,textField,button);
        borderPane.setTop(flowPane);

        Text text1=new Text("Enter a bit string");
        TextField textField1=new TextField();
        textField1.setMinWidth(800);
        Button button1=new Button("Decode Text");
        button1.setMinWidth(100);
        button1.setOnAction(e->{
            try {
                Htree.createHuffmanTree();
                String codes=textField1.getText();
                StringBuilder s=new StringBuilder(textField1.getText()+" is encoded to ");
                decode(codes,s,Htree.getHtree());
                if (textField1.getText().equals("")){
                    s.replace(0,s.length(),"please enter a string !");
                }

                Alert alert = new Alert(Alert.AlertType.INFORMATION);
                alert.titleProperty().set("Decode Bits to Text");
                alert.headerTextProperty().set(s.toString());
                alert.showAndWait();
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        });
        FlowPane flowPane1=new FlowPane();
        flowPane1.getChildren().addAll(text1,textField1,button1);
        borderPane.setBottom(flowPane1);

        borderPane.setCenter(pane);
        return borderPane;
    }

    public void start(Stage primaryStage) throws Exception{
        Scene scene=new Scene(pane(),1000,800);
        primaryStage.setTitle("HuffmanTree");
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    public void decode(String codes,StringBuilder s,HuffmanTreeNode Htree){
        for (int i=0;i<codes.length();i++) {
            HuffmanTreeNode p=Htree;
            for (;i<codes.length();i++) {
                if (codes.charAt(i) == '1') {
                    p=p.getRightChild();
                } else {
                    p=p.getLeftChild();
                }
                if(p.getLeftChild()==null && p.getRightChild()==null){
                    s.append(p.getData());
                    break;
                }
            }
        }
    }

    public void createTree(HuffmanTreeNode Htree,int depth,Pane pane,int row,int col){
        if (Htree!=null) {
            Circle circle = new Circle(20);
            circle.setFill(null);
            circle.setStroke(Color.BLACK);
            Label label = new Label(Htree.getWeight() + "", circle);
            label.setContentDisplay(ContentDisplay.CENTER);
            label.setLayoutX(col);
            label.setLayoutY(row);
            pane.getChildren().add(label);
            row+=50;col-=depth;
            int row1=row,col1=2*depth+col;
            depth/=2;
            if(Htree.getLeftChild()!=null){
                Line line=new Line(label.getLayoutX(),label.getLayoutY()+30,col+35,row+5);
                Text text1=new Text("0");
                text1.setX((line.getStartX()+line.getEndX())/2-5);
                text1.setY((line.getStartY()+line.getEndY())/2-5);
                pane.getChildren().addAll(line,text1);
            }
            if (Htree.getRightChild()!=null){
                Line line2=new Line(label.getLayoutX()+40,label.getLayoutY()+30,col1+5,row1+5);
                Text text2=new Text("1");
                text2.setX((line2.getStartX()+line2.getEndX())/2-5);
                text2.setY((line2.getStartY()+line2.getEndY())/2-5);
                pane.getChildren().addAll(line2,text2);
            }
            if(Htree.getLeftChild()==null && Htree.getRightChild()==null){
                Text text=new Text(Htree.getData()+"");
                text.setX(label.getLayoutX()+20);
                text.setY(label.getLayoutY()+60);
                pane.getChildren().add(text);
            }
            createTree(Htree.getLeftChild(),depth, pane,row,col);
            createTree(Htree.getRightChild(),depth, pane,row1,col1);
        }
    }

    public void save() throws Exception{
        DataOutputStream os=new DataOutputStream(new FileOutputStream("TreePrint.txt"));
        os.writeUTF(this.codes);
        os.close();
    }
}

 

  • 4
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

天的命名词

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

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

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

打赏作者

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

抵扣说明:

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

余额充值