zoukankan      html  css  js  c++  java
  • C#数据结构-赫夫曼树

    什么是赫夫曼树?

    赫夫曼树(Huffman Tree)是指给定N个权值作为N个叶子结点,构造一棵二叉树,若该树的带权路径长度达到最小。哈夫曼树(也称为最优二叉树)是带权路径长度最短的树,权值较大的结点离根较近。

     1    public class HNode<T>
     2     {
     3         public HNode()
     4         {
     5             data = default(T);
     6             weight = 0;
     7             leftNode = null;
     8             rightNode = null;
     9         }
    10 
    11         public HNode(T val)
    12         {
    13             data = val;
    14             weight = 0;
    15             leftNode = null;
    16             rightNode = null;
    17         }
    18 
    19         /// <summary>
    20         /// 权重
    21         /// </summary>
    22         public int weight { get; set; }
    23 
    24         /// <summary>
    25         /// 内容
    26         /// </summary>
    27         public T data { get; set; }
    28 
    29         /// <summary>
    30         /// 左树
    31         /// </summary>
    32         public HNode<T> leftNode { get; set; }
    33 
    34         /// <summary>
    35         /// 右树
    36         /// </summary>
    37         public HNode<T> rightNode { get; set; }
    38     }
     1    /// <summary>
     2     /// 赫夫曼树
     3     /// </summary>
     4     /// <typeparam name="T"></typeparam>
     5     public class HTree<T>
     6     {
     7         /// <summary>
     8         /// 树的头结点
     9         /// </summary>
    10         public HNode<T> head { get; set; }
    11 
    12         /// <summary>
    13         /// 构造函数
    14         /// </summary>
    15         /// <param name="val"></param>
    16         public HTree(T val)
    17         {
    18             head = new HNode<T>(val);
    19         }
    20 
    21         public HTree()
    22         {
    23             head = new HNode<T>();
    24         }
    25         /// <summary>
    26         /// 构建树结构
    27         /// </summary>
    28         /// <param name="list"></param>
    29         public void build(List<T> list)
    30         {
    31             //判断是否能构建树结构
    32             if (list == null || list.Count <2)
    33                 throw new ArgumentOutOfRangeException("params error");
    34             //分组统计
    35             List<HNode<T>> nodes = new List<HNode<T>>();
    36             nodes.AddRange(from m in list group m by m into g 
    37                            select new HNode<T> { data = g.Key,weight = g.Count()});
    38             //排序
    39             nodes = nodes.OrderBy(i => i.weight).ToList();
    40 
    41             for (int i =1; i< nodes.Count; i++)
    42             {
    43                 HNode<T> parentNode = new HNode<T>();
    44                 if (i == 1)
    45                 {
    46                     //先取最小的两个节点
    47                     parentNode.leftNode = nodes[0];
    48                     parentNode.rightNode = nodes[1];
    49                     parentNode.weight = nodes[0].weight + nodes[1].weight;
    50                 }
    51                 else
    52                 {
    53                     //依次取节点构建树
    54                     if (head.weight >= nodes[i].weight)
    55                     {
    56                         parentNode.leftNode = head;
    57                         parentNode.rightNode = nodes[i];
    58                     }
    59                     else
    60                     {
    61                         parentNode.rightNode = head;
    62                         parentNode.leftNode = nodes[i];
    63                     }
    64                     parentNode.weight = head.weight + nodes[i].weight;
    65                 }
    66                 head = parentNode;
    67             }
    68         }
    69 
    70         /// <summary>
    71         /// 先序遍历
    72         /// </summary>
    73         /// <param name="index"></param>
    74         public void PreorderTraversal(HNode<T> node)
    75         {
    76             //递归的终止条件
    77             if (head == null)
    78             {
    79                 Console.WriteLine("当前树为空");
    80                 return;
    81             }
    82             if (node != null)
    83             {
    84                 if(node.data != null)
    85                 Console.WriteLine($"{node.data} {node.weight}");
    86                 PreorderTraversal(node.leftNode);
    87                 PreorderTraversal(node.rightNode);
    88             }
    89         }
    90     }

    测试代码:

    1 List<string> list = new List<string>() { "A","B", "B", "C", "C", "C", "D", "D", "D", "D", "E", "E", "E", "E", "E" };
    2 HTree<string> tree = new HTree<string>();
    3 tree.build(list);
    4 tree.PreorderTraversal(tree.head);

    打印结果:

    A 1
    B 2
    C 3
    D 4
    E 5

    用这个例子现在我们看下构建的二叉树结构:


     

  • 相关阅读:
    GCD and LCM HDU 4497 数论
    c++ const 修饰变量位置含义
    洛谷 P1017 进制转换
    洛谷 P1029 最大公约数和最小公倍数问题
    Buses and People CodeForces 160E 三维偏序+线段树
    Python学习-第三天-面向对象编程基础
    Python学习-第二天-字符串和常用数据结构
    关于Python学习的一点说明
    Python学习-第一天-函数和模块的使用
    Super Mario HDU 4417 主席树区间查询
  • 原文地址:https://www.cnblogs.com/xtt321/p/14161100.html
Copyright © 2011-2022 走看看