157 lines
4.2 KiB
C#
157 lines
4.2 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Runtime.CompilerServices;
|
|
using System.Runtime.InteropServices;
|
|
using System.Text;
|
|
|
|
namespace StgSharp.Data
|
|
{
|
|
public partial class HuffmanTree<T> where T : struct
|
|
{
|
|
public Dictionary<T, HuffmanKey<T>> BuildHuffmanDictionary()
|
|
{
|
|
Dictionary<T, HuffmanKey<T>> ret = new Dictionary<T, HuffmanKey<T>>();
|
|
TreeNode<T> root = Root;
|
|
HuffmanKey<T> key = new HuffmanKey<T>();
|
|
key = key.SetSide(KeySide.Right);
|
|
InternalBuildDictionary(ret, root, key);
|
|
return ret;
|
|
}
|
|
|
|
public void InternalBuildDictionary(
|
|
Dictionary<T, HuffmanKey<T>> dict,
|
|
TreeNode<T> node,
|
|
HuffmanKey<T> valueTemp
|
|
)
|
|
{
|
|
HuffmanKey<T> nativeNode = new HuffmanKey<T>(valueTemp.bitList);
|
|
nativeNode.AddIndexLevel();
|
|
//检查左节点
|
|
if (node._left.Value == null)
|
|
{
|
|
//左节点不是叶子节点,继续搜索
|
|
InternalBuildDictionary(
|
|
dict,
|
|
node._left,
|
|
nativeNode.SetSide(KeySide.Left));
|
|
}
|
|
else
|
|
{
|
|
//左节点是叶子节点,添加值
|
|
dict.Add(node._left.Value.Value, nativeNode.SetSide(KeySide.Left));
|
|
}
|
|
//检查右节点
|
|
if (node._right.Value == null)
|
|
{
|
|
//右节点不是叶子节点,继续搜索
|
|
InternalBuildDictionary(
|
|
dict,
|
|
node._right,
|
|
nativeNode.SetSide(KeySide.Right));
|
|
}
|
|
else
|
|
{
|
|
//右节点是叶子节点,添加值
|
|
dict.Add(node._right.Value.Value, nativeNode.SetSide(KeySide.Right));
|
|
}
|
|
//这里检查自己是不是叶子节点
|
|
//但是上面已经检查过了,不需要被检查
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public class HuffmanKey<T> where T : struct
|
|
{
|
|
internal List<bool> bitList;
|
|
internal BitArray code;
|
|
|
|
public HuffmanKey()
|
|
{
|
|
bitList = new List<bool>();
|
|
bitList.Add(false);
|
|
}
|
|
|
|
public HuffmanKey(List<bool> former)
|
|
{
|
|
bitList = new List<bool>(former);
|
|
}
|
|
|
|
public unsafe byte[] GetBytes()
|
|
{
|
|
byte[] bytes = new byte[bitList.Count / 8 +1];
|
|
BitArray array = new BitArray(bitList.ToArray());
|
|
array.CopyTo(bytes, 0);
|
|
return bytes;
|
|
}
|
|
|
|
public void Freeze()
|
|
{
|
|
if (code != null)
|
|
{
|
|
return;
|
|
}
|
|
bitList.RemoveAt(0);
|
|
code = new BitArray(bitList.ToArray());
|
|
}
|
|
|
|
public BitArray GetBitArray()
|
|
{
|
|
if (code == null)
|
|
{
|
|
List<bool> list = new List<bool>(bitList);
|
|
list.RemoveAt(0);
|
|
return new BitArray(list.ToArray());
|
|
}
|
|
return code;
|
|
}
|
|
|
|
public unsafe HuffmanKey<T> SetSide(KeySide side)
|
|
{
|
|
HuffmanKey<T> newKey = new HuffmanKey<T>(bitList);
|
|
newKey.bitList[newKey.bitList.Count - 1] = (side == KeySide.Left);
|
|
return newKey;
|
|
}
|
|
|
|
public unsafe void AddIndexLevel()
|
|
{
|
|
bitList.Add(true);
|
|
}
|
|
|
|
public bool IsSupported
|
|
{
|
|
get
|
|
{
|
|
return
|
|
typeof(T) == typeof(byte) ||
|
|
typeof(T) == typeof(uint) ||
|
|
typeof(T) == typeof(ushort) ||
|
|
typeof(T) == typeof(ulong) ||
|
|
#if NET7_0_OR_GREATER
|
|
typeof(T) == typeof(UInt128) ||
|
|
#endif
|
|
typeof(T) == typeof(M128);
|
|
}
|
|
}
|
|
|
|
public override string ToString()
|
|
{
|
|
string str = "";
|
|
foreach (var bit in bitList)
|
|
{
|
|
str += $"{bit} ";
|
|
}
|
|
return str;
|
|
}
|
|
}
|
|
|
|
public enum KeySide
|
|
{
|
|
Left,
|
|
Right
|
|
}
|
|
|
|
}
|