//----------------------------------------------------------------------- //----------------------------------------------------------------------- // file="HuffmanTree.cs" // Project: StgSharp // AuthorGroup: Nitload Space // Copyright (c) Nitload Space. All rights reserved. // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation // files (the “Software”), to deal in the Software without restriction, // including without limitation the rights to use, copy, modify, merge, // publish, distribute, sublicense, and/or sell copies of the Software, // and to permit persons to whom the Software is furnished to do so, // subject to the following conditions: // // The above copyright notice and // this permission notice shall be included in all copies // or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED “AS IS”, // WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, // ARISING FROM, OUT OF OR IN CONNECTION WITH // THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // //----------------------------------------------------------------------- //----------------------------------------------------------------------- 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; internal HuffmanTree(HuffmanNodeList nodeList) { leaves = nodeList; } public HuffmanNodeList LeafList => leaves; public TreeNode Root => leaves.Last; 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)); } 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 TreeNode BeforeLast => this[Count - 2]; public TreeNode Last => this[Count - 1]; public TreeNode OverLast => this[Count - 3]; public TreeNode RemoveAndGetBeforeLast { get { TreeNode ret = this[Count - 2]; RemoveAt(Count - 2); return ret; } } public TreeNode RemoveAndGetLast { get { TreeNode ret = this[Count - 1]; RemoveAt(Count - 1); return ret; } } public TreeNode RemoveAndGetOverLast { get { TreeNode ret = this[Count - 3]; RemoveAt(Count - 3); return ret; } } public void Add(T element, ulong f) { base.Add(new TreeNode(element, f)); } } public class TreeNode where T : struct { internal ulong _frequency; internal TreeNode _left; internal TreeNode _right; internal T? _value; 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; } public TreeNode(T? value, ulong frequncy) { _value = value; _frequency = frequncy; } public ulong frequency => _frequency; public TreeNode Left => _left; public TreeNode Right => _right; public T? Value => _value; } }