数据结构之哈夫曼树

 所谓哈夫曼树就是要求最小加权路径长度,这是什么意思呢?简而言之,就是要所有的节点对应的路径长度(高度-1)乘以该节点的权值,然后保证这些结果之和最小。

   哈夫曼树最常用的应用就是解决编码问题。一般我们用的ASCII是固定长度的编码,对于那些常用的字符,使用很长的长度就显得略为浪费空间了。

  下面以一个实例来构建一颗哈夫曼编码树。

   设字符集S={A,B,C,D,E,F},字符出现的频率W={2,3,5,7,9,12},对字符集进行哈夫曼编码

   (1)以频率为树的节点值,构建6个树节点,保存在一个数据集合T中

     (2)选择频率集W中最小的两个频率,然后相加,将结果作为树的节点值,构建新的树节点,将这两个最小值对应的树节点,分别作为新的节点的左右孩子。从T重删除这两个最小值对应的节点,最后将新节点放到T中。

   (3)重复第2步,直到T中只剩下一个节点,那么该节点就是所需要的哈夫曼树

 其实说的容易,实现起来也有一点小麻烦,下面用Java实现:

     树节点:

              

[java]  view plain  copy
  1. public class TreeNode<T>  
  2.     {  
  3.         public TreeNode<T> leftNode;  
  4.         public TreeNode<T> rightNode;  
  5.         public T data;  
  6.         public TreeNode(T data)  
  7.             {  
  8.                 this.data=data;  
  9.             }  
  10.     }  
   构建哈夫曼树:

[java]  view plain  copy
  1. public class TestTree  
  2.     {  
  3.         /* 
  4.          * 设S={A,B,C,D,E,F},W={2,3,5,7,9,12} 
  5.          */  
  6.         static HashMap<Character, Integer> map;  
  7.         public TestTree()  
  8.             {  
  9.                 // TODO Auto-generated constructor stub  
  10.             }  
  11.   
  12.         public static void main(String[] args)  
  13.             {  
  14.                 Character[] character = { 'A''B''C''D''E''F' };  
  15.                 int[] weight = { 2357912 };// 有序或者无序都一样  
  16.                 map=new HashMap<Character, Integer>();  
  17.                 for(int i=0;i<weight.length;i++)  
  18.                     map.put(character[i], weight[i]);  
  19.                   
  20.                 ArrayList<TreeNode<Integer>> nodes = new ArrayList<TreeNode<Integer>>();  
  21.                 for (int i = 0; i < weight.length; i++)  
  22.                     {  
  23.                         nodes.add(new TreeNode<Integer>(weight[i]));  
  24.                     }  
  25.                 while (true)  
  26.                     {  
  27.                         if (nodes.size() <= 1)  
  28.                             break;  
  29.                         // 找两个最小的  
  30.                         TreeNode<Integer> minNode = nodes.get(0);  
  31.                         TreeNode<Integer> sminNode = nodes.get(1);  
  32.                         for (int i = 1; i < nodes.size(); i++)  
  33.                             {  
  34.                                 TreeNode<Integer> tempNode = nodes.get(i);  
  35.                                 if (minNode.data >=tempNode.data)  
  36.                                     {  
  37.                                         sminNode = minNode;  
  38.                                         minNode = tempNode;  
  39.                                     }  
  40.                             }  
  41.                         nodes.remove(minNode);  
  42.                         nodes.remove(sminNode);  
  43.                         TreeNode<Integer> newNode = new TreeNode<Integer>(  
  44.                                 minNode.data + sminNode.data);  
  45.                         newNode.leftNode = minNode;  
  46.                         newNode.rightNode = sminNode;  
  47.                         nodes.add(newNode);  
  48.                     }  
  49.                 TreeNode<Integer>hafmanTreeNode=nodes.get(0);  
  50.                 getHalmanCode(hafmanTreeNode," ");  
  51.                   
  52.             }  
  53.          public static void getHalmanCode(TreeNode<Integer>hafmanTreeNode,String blank)  
  54.          {  
  55.              if(hafmanTreeNode==null)  
  56.                  return;  
  57.              if(hafmanTreeNode.leftNode==null&&hafmanTreeNode.rightNode==null)  
  58.                  {  
  59.                    System.out.println("->"+getCharacter(hafmanTreeNode.data));  
  60.                  }  
  61.              else   
  62.                  {  
  63.                      System.out.print("0");  
  64.                      getHalmanCode(hafmanTreeNode.leftNode,blank+" ");  
  65.                      System.out.print(blank+"1");  
  66.                      getHalmanCode(hafmanTreeNode.rightNode,blank+" ");  
  67.                  }  
  68.          }  
  69.          //得到某一个字符的编码  
  70.          public static void getHalmanCode(TreeNode<Integer>hafmanTreeNode,Character character)  
  71.          {  
  72.              if(hafmanTreeNode==null)  
  73.                  return;  
  74.              if(hafmanTreeNode.leftNode==null&&hafmanTreeNode.rightNode==null)  
  75.                  {  
  76.                      if (getCharacter(hafmanTreeNode.data)==character)  
  77.                         {  
  78.                             System.out.print("");  
  79.                         }  
  80.                  }  
  81.          }  
  82.                 //得到权值对应的字符  
  83.          public static Character getCharacter(int weight)  
  84.          {  
  85.              Set<Map.Entry<Character, Integer>>set=map.entrySet();  
  86.              for(Iterator<Map.Entry<Character, Integer>> iterator=set.iterator();iterator.hasNext();)  
  87.                  {  
  88.                      Map.Entry<Character, Integer>entry=iterator.next();  
  89.                      if(entry.getValue()==weight)  
  90.                          {  
  91.                              map.remove(entry.getKey());  
  92.                              return entry.getKey();  
  93.                          }  
  94.                  }  
  95.              return null;  
  96.          }  
  97.     }  
  结果:

       

 D:00

 E:01

 A:1000

 B:1001

 C:101

 F:11

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值