C#数据结构-赫夫曼树
什么是赫夫曼树?
赫夫曼树(Huffman Tree)是指给定N个权值作为N个叶子结点,构造一棵二叉树,若该树的带权路径长度达到最小。哈夫曼树(也称为最优二叉树)是带权路径长度最短的树,权值较大的结点离根较近。
1 public class HNode2 { 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 /// 20 /// 权重 21 /// 22 public int weight { get; set; } 23 24 /// 25 /// 内容 26 /// 27 public T data { get; set; } 28 29 /// 30 /// 左树 31 /// 32 public HNode leftNode { get; set; } 33 34 /// 35 /// 右树 36 /// 37 public HNode rightNode { get; set; } 38 }
1 ///2 /// 赫夫曼树 3 /// 4 /// 5 public class HTree 6 { 7 /// 8 /// 树的头结点 9 /// 10 public HNode head { get; set; } 11 12 /// 13 /// 构造函数 14 /// 15 /// 16 public HTree(T val) 17 { 18 head = new HNode (val); 19 } 20 21 public HTree() 22 { 23 head = new HNode (); 24 } 25 /// 26 /// 构建树结构 27 /// 28 /// 29 public void build(List list) 30 { 31 //判断是否能构建树结构 32 if (list == null || list.Count <2) 33 throw new ArgumentOutOfRangeException("params error"); 34 //分组统计 35 List > nodes = new List >(); 36 nodes.AddRange(from m in list group m by m into g 37 select new HNode { 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 parentNode = new HNode (); 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 /// 71 /// 先序遍历 72 /// 73 /// 74 public void PreorderTraversal(HNode 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
用这个例子现在我们看下构建的二叉树结构: