using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Xml; using System.Xml.Linq; namespace StgSharp.Data { public partial class HuffmanTree where T : struct { HuffmanNodeList leaves; public TreeNode Root { get => leaves.Last; } public HuffmanNodeList LeafList { get => leaves; } internal HuffmanTree(HuffmanNodeList nodeList) { leaves = nodeList; } public static HuffmanTree BuildHuffmanTree(List<(T, ulong)> metaData) { if (metaData.Count<=3) { throw new Exception("Data is too little, no need to compress"); } HuffmanNodeList leaves = new HuffmanNodeList(); HuffmanNodeList all = new HuffmanNodeList(); foreach (var item in metaData) { leaves.Add(new TreeNode(item)); } int count = 0; while (leaves.Count >2) { TreeNode node, toMove; if (leaves.Last._frequency < leaves.BeforeLast._frequency) { if (leaves.BeforeLast._frequency < leaves.OverLast._frequency) { //第三节点最大 node = new TreeNode(leaves.BeforeLast, leaves.Last); toMove = leaves.RemoveAndGetLast; all.Add(toMove); toMove = leaves.RemoveAndGetLast; all.Add(toMove); leaves.Add(node); } else { //第二节点最大 node = leaves.Last._frequency < leaves.OverLast._frequency ? new TreeNode(leaves.OverLast, leaves.Last) : new TreeNode(leaves.Last, leaves.OverLast); toMove = leaves.RemoveAndGetLast; all.Add(toMove); toMove = leaves.RemoveAndGetBeforeLast; all.Add(toMove); leaves.Add(node); } } else { if (leaves.Last._frequency < leaves.OverLast._frequency) { //第三节点最大 node = new TreeNode(leaves.Last, leaves.BeforeLast); toMove = leaves.RemoveAndGetLast; all.Add(toMove); toMove = leaves.RemoveAndGetLast; all.Add(toMove); leaves.Add(node); } else { //第一节点最大 node = leaves.BeforeLast._frequency < leaves.OverLast._frequency? new TreeNode(leaves.OverLast, leaves.BeforeLast): new TreeNode(leaves.BeforeLast, leaves.OverLast); toMove = leaves.RemoveAndGetBeforeLast; all.Add(toMove); toMove = leaves.RemoveAndGetBeforeLast; all.Add(toMove); leaves.Add(node); } } leaves = new HuffmanNodeList( leaves.OrderByDescending(pair => pair.frequency) .Select(pair => pair).ToList()); } TreeNode lastOne = leaves[0]; TreeNode lastTwo = leaves[1]; TreeNode root = lastOne.frequency>lastTwo.frequency? new TreeNode(lastOne,lastTwo): new TreeNode(lastTwo, lastOne); all.Add(lastOne); all.Add(lastTwo); all.Add(root); leaves = all; return new HuffmanTree(all); } } public class HuffmanNodeList : List> where T : struct { public HuffmanNodeList():base() { } public HuffmanNodeList(IEnumerable> values):base(values) {} public void Add(T element, ulong f) { base.Add(new TreeNode(element,f)); } public TreeNode Last { get => this[Count-1 ]; } public TreeNode RemoveAndGetLast { get { TreeNode ret = this[Count-1]; RemoveAt(Count-1); return ret; } } public TreeNode BeforeLast { get => this[Count - 2]; } public TreeNode RemoveAndGetBeforeLast { get { TreeNode ret = this[Count - 2]; RemoveAt(Count - 2); return ret; } } public TreeNode OverLast { get => this[Count - 3]; } public TreeNode RemoveAndGetOverLast { get { TreeNode ret = this[Count - 3]; RemoveAt(Count - 3); return ret; } } } public class TreeNode where T: struct { internal TreeNode _left; internal TreeNode _right; internal T? _value; internal ulong _frequency; public ulong frequency => _frequency; public T? Value => _value; public TreeNode Left => _left; public TreeNode Right => _right; public TreeNode( T? value, ulong frequncy) { _value = value; _frequency = frequncy; } internal TreeNode(TreeNode left, TreeNode right) { _left = left; _right = right; _value = null; _frequency = left._frequency + right._frequency; } public TreeNode((T, ulong) data) { _value = data.Item1; _frequency = data.Item2; } } }