zoukankan      html  css  js  c++  java
  • 20182309 哈夫曼树

    哈夫曼树的实现

    1.找到一个哈夫曼树的例子

    • 这个例子需要自己输入字符个数、字符集、频率分布
    import java.util.Scanner;
    public class HuffmanCode{
        //建立数的节点类
        static class Node{
            int weight;//频数
            int parent;
            int leftChild;
            int rightChild;
    
            public Node(int weight,int parent,int leftChild,int rightChild){
                this.weight=weight;
                this.parent=parent;
                this.leftChild=leftChild;
                this.rightChild=rightChild;
            }
    
            void setWeight(int weight){
                this.weight=weight;
            }
    
            void setParent(int parent){
                this.parent=parent;
            }
    
            void setLeftChild(int leftChild){
                this.leftChild=leftChild;
            }
    
            void setRightChild(int rightChild){
                this.rightChild=rightChild;
            }
    
            int getWeight(){
                return weight;
            }
    
            int getParent(){
                return parent;
            }
    
            int getLeftChild(){
                return leftChild;
            }
    
            int getRightChild(){
                return rightChild;
            }
        }
    
        //新建哈夫曼编码
        static class NodeCode{
            String character;
            String code;
            NodeCode(String character,String code){
                this.character=character;
                this.code=code;
            }
            NodeCode(String code){
                this.code= code;
            }
    
            void setCharacter(String character){
                this.character=character;
            }
    
            void setCode(String code){
                this.code=code;
            }
    
            String getCharacter(){
                return character;
            }
    
            String getCode(){
                return code;
            }
        }
    
        //初始化一个huffuman树
        public static void initHuffmanTree(Node[] huffmanTree,int m){
            for(int i=0;i<m;i++){
                huffmanTree[i] = new Node(0,-1,-1,-1);
            }
        }
    
        //初始化一个huffmanCode
        public static void initHuffmanCode(NodeCode[] huffmanCode,int n){
            for(int i=0;i<n;i++){
                huffmanCode[i]=new NodeCode("","");
            }
        }
    
        //获取huffmanCode的符号
        public static void getHuffmanCode(NodeCode[] huffmanCode , int n){
            Scanner input = new Scanner(System.in);
            for(int i=0;i<n;i++){
                String temp = input.next();
                huffmanCode[i] = new NodeCode(temp,"");
            }
        }
    
        //获取huffman树节点频数
        public static void getHuffmanWeight(Node[] huffmanTree , int n){
            Scanner input = new Scanner(System.in);
            for(int i=0;i<n;i++){
                int temp = input.nextInt();
                huffmanTree[i] = new Node(temp,-1,-1,-1);
            }
        }
    
        //从n个结点中选取最小的两个结点
        public static int[] selectMin(Node[] huffmanTree ,int n)
        {
            int min[] = new int[2];
            class TempNode
            {
                int newWeight;//存储权
                int place;//存储该结点所在的位置
    
                TempNode(int newWeight,int place){
                    this.newWeight=newWeight;
                    this.place=place;
                }
    
                void setNewWeight(int newWeight){
                    this.newWeight=newWeight;
                }
    
                void setPlace(int place){
                    this.place=place;
                }
    
                int getNewWeight(){
                    return newWeight;
                }
    
                int getPlace(){
                    return place;
                }
            }
    
            TempNode[] tempTree=new TempNode[n];
    
            //将huffmanTree中没有双亲的结点存储到tempTree中
            int i=0,j=0;
            for(i=0;i<n;i++)
            {
                if(huffmanTree[i].getParent()==-1&& huffmanTree[i].getWeight()!=0)
                {
                    tempTree[j]= new TempNode(huffmanTree[i].getWeight(),i);
                    j++;
                }
            }
    
            int m1,m2;
            m1=m2=0;
            for(i=0;i<j;i++)
            {
                if(tempTree[i].getNewWeight()<tempTree[m1].getNewWeight())//此处不让取到相等,是因为结点中有相同权值的时候,m1取最前的
                    m1=i;
            }
            for(i=0;i<j;i++)
            {
                if(m1==m2)
                    m2++;//当m1在第一个位置的时候,m2向后移一位
                if(tempTree[i].getNewWeight()<=tempTree[m2].getNewWeight()&& i!=m1)//此处取到相等,是让在结点中有相同的权值的时候,
    
                    //m2取最后的那个。
                    m2=i;
            }
    
            min[0]=tempTree[m1].getPlace();
            min[1]=tempTree[m2].getPlace();
            return min;
        }
    
        //创建huffmanTree
        public static void createHaffmanTree(Node[] huffmanTree,int n){
            if(n<=1)
                System.out.println("Parameter Error!");
            int m = 2*n-1;
            //initHuffmanTree(huffmanTree,m);
    
            for(int i=n;i<m;i++)
            {
                int[] min=selectMin(huffmanTree,i);
                int min1=min[0];
                int min2=min[1];
                huffmanTree[min1].setParent(i);
                huffmanTree[min2].setParent(i);
                huffmanTree[i].setLeftChild(min1);
                huffmanTree[i].setRightChild(min2);
                huffmanTree[i].setWeight(huffmanTree[min1].getWeight()+ huffmanTree[min2].getWeight());
            }
        }
    
        //创建huffmanCode
        public static void createHaffmanCode(Node[] huffmanTree,NodeCode[] huffmanCode,int n){
            Scanner input = new Scanner(System.in);
            //只给了十个空???
            char[] code = new char[30];
            int start;
            int c;
            int parent;
            int temp;
    
            code[n-1]='0';
            for(int i=0;i<n;i++)
            {
                StringBuffer stringBuffer = new StringBuffer();
                start=n-1;
                c=i;
                while( (parent=huffmanTree[c].getParent()) >=0 )
                {
                    start--;
                    code[start]=((huffmanTree[parent].getLeftChild()==c)?'0':'1');
                    c=parent;
    
                }
                for(;start<n-1;start++){
                    stringBuffer.append(code[start]);
                }
                huffmanCode[i].setCode(stringBuffer.toString());
            }
        }
    
        //输出hufmanCode
        public static void ouputHaffmanCode(NodeCode[] huffmanCode,int n){
            System.out.println("字符与编码的对应关系如下:");
            for(int i=0;i<n;i++){
                System.out.println(huffmanCode[i].getCharacter()+":"+huffmanCode[i].getCode());
            }
        }
    
        //主函数
        public static void main(String[] args){
            Scanner input = new Scanner(System.in);
            int n;
            int m;
            System.out.print("请输入字符个数:");
            n = input.nextInt();
            m=2*n-1;
            Node[] huffmanTree = new Node[m];
            NodeCode[] huffmanCode = new NodeCode[n];
    
            //初始化huffmanTree,huffmanCode
            initHuffmanTree(huffmanTree,m);
            initHuffmanCode(huffmanCode,n);
    
            //获取huffmanCode的符号
            System.out.print("请输入哈夫曼编码的字符:");
            getHuffmanCode(huffmanCode,n);
    
            //获取huffmanTree的频数
            System.out.print("请输入哈夫曼编码字符对应的频数:");
            getHuffmanWeight(huffmanTree,n);
    
            //创建huffmanTree
            createHaffmanTree(huffmanTree,n);
            //创建huffmanCode
            createHaffmanCode(huffmanTree,huffmanCode,n);
    
            //输出huffmanCode编码
            ouputHaffmanCode(huffmanCode,n);
    
        }
    }
    

    改造成我需要的哈夫曼树并添加所需功能

    • 重写节点的比较方法
        public int compareTo(HuffmanNode node) {
            if (this.count >= node.count){
                return 1;
            }
            else {
                return -1;
            }
        }
    
    • 构建哈夫曼树
        public HuffmanNode createTree(List<HuffmanNode> nodes) {
            while (nodes.size() > 1) {
                Collections.sort(nodes);
    
                HuffmanNode left = nodes.get(nodes.size() - 2);
                left.setCode("0");
                HuffmanNode right = nodes.get(nodes.size() - 1);
                right.setCode("1");
                HuffmanNode parent = new HuffmanNode(null, left.getLength() + right.getLength());
                parent.setLeft(left);
                parent.setRight(right);
                nodes.remove(left);
                nodes.remove(right);
                nodes.add(parent);
            }
            return nodes.get(0);
        }
    
    • 给出字符的哈夫曼编码(利用List)
        public List<HuffmanNode> breadth(HuffmanNode root) {
            List<HuffmanNode> list = new ArrayList<HuffmanNode>();
            Queue<HuffmanNode> queue = new ArrayDeque<HuffmanNode>();
    
            if (root != null) {
                queue.offer(root);
                root.getLeft().setCode(root.getCode() + "0");
                root.getRight().setCode(root.getCode() + "1");
            }
    
            while (!queue.isEmpty()) {
                list.add(queue.peek());
                HuffmanNode node = queue.poll();
                if (node.getLeft() != null)
                    node.getLeft().setCode(node.getCode() + "0");
                if (node.getRight() != null)
                    node.getRight().setCode(node.getCode() + "1");
    
                if (node.getLeft() != null) {
                    queue.offer(node.getLeft());
                }
    
                if (node.getRight() != null) {
                    queue.offer(node.getRight());
                }
            }
            return list;
        }
    
    • 主函数
      • 读取文件
          File file = new File("编码文件.txt");
          if (!file.exists()) {
              file.createNewFile();
          }
          BufferedReader br = new BufferedReader(new FileReader(file));
          String s;
          String message = "";
          while((s = br.readLine()) != null){
              message += s;
          }
      
      • 按字符拆分字符串
      String[] result = message.split("");
      
      • 统计频率
      for (int n = 0;n < result.length; n++){
              for (int i = 0; i < 27; i++){
                  if (result[n].equals(list.get(i))){
                      number[i] += 1;
                  }
              }
          }
      
      • 构建哈夫曼树
          HuffmanTree huffmanTree = new HuffmanTree();
          HuffmanNode node = huffmanTree.createTree(nodeList);
          List<HuffmanNode> inlist = new ArrayList<HuffmanNode>();
          inlist = huffmanTree.breadth(node);
      
      • 加密
          String res = "";
          for(int f = 0; f < sum; f++){
              for(int j = 0;j<name.length;j++){
                  if(message.charAt(f) == name[j].charAt(0))
                      res += code[j];
              }
          }
      
      • 解密
          String string2 = "";
          for(int h = putlist.size(); h > 0; h--){
              string1 = string1 + putlist.get(0);
              putlist.remove(0);
              for(int i=0;i<code.length;i++){
                  if (string1.equals(code[i])) {
                      string2 = string2+""+ name[i];
                      string1 = "";
                  }
              }
          }
      

    运行结果

    总代码连接

  • 相关阅读:
    VS2008正式版序列号
    清空SQL Server数据库中所有的用户表
    [原创]JavaScript调用Button的服务器端事件
    动态加载枚举 到 DropdownList
    [转载]静态构造函数
    SQL 事务 [两种]
    Jpg文件格式[参考]
    Delegate Event
    javascript 操作cookie类
    [共享]一个文件上传的控件,绝对是精品源码
  • 原文地址:https://www.cnblogs.com/blueflameashe/p/11924457.html
Copyright © 2011-2022 走看看