哈弗曼算法_C#代码

这是链接上一篇文章所写的代码,上一篇链接如下:

http://www.cnblogs.com/HONT/archive/2013/06/05/3118531.html

 

StringToHuffmanCode这个函数相当于把转换步奏打包执行,其中树的一些遍历使用递归实现,由于用了不少.Net3.5的特性,造成看着费劲实在抱歉。。

public string StringToHuffmanCode(out Dictionary<char, string> key, string str)

{

    string result = "";



    var tmps = GetWeightArray(str);

    //构建权值数组



    var tree = CreateHuffmanTree(tmps);

    //构建哈弗曼树,即最优二叉树



    var dict = CreateHuffmanDict(tree);

    //构建哈弗曼字典.



    result = ToHuffmanCode(str, dict);

    //输出哈弗曼代码



    key = dict;

    return result;

}
StringToHuffmanCode

 

下面给出全部代码

===================================================================================

在VS2012和.Net3.5中 测试通过.

具体实现:按照权值提取数据 - 转换最优二叉树 - 进行编码 - 返回字典和编码后文件

 

首先是Main函数中的代码:

class Program

{

        static void Main(string[] args)

        {

            string source = "哈夫曼曼曼曼曼";



            Huffman hf = new Huffman();

            Dictionary<char, string> key = null;

            var hfCode = hf.StringToHuffmanCode(out key, source);



            Console.WriteLine("--------------------编码与解析");

            Console.WriteLine("编码: "+hfCode);



            var text = hf.ToText(hfCode, key);

            Console.WriteLine("解析: " + text);



            Console.ReadLine();

        }

}

-----------------------------------------------------------------------------------------------------------------------------------

然后是类里面的代码:

using System;

using System.Collections.Generic;

using System.Linq;





public class Huffman

{

    public class Node : IComparable

    {

        /// <summary>

        /// 左子树

        /// </summary>

        public Node LChild { get; set; }

        /// <summary>

        /// 右子树

        /// </summary>

        public Node RChild { get; set; }

        /// <summary>

        /// 权值

        /// </summary>

        public int Weight { get; set; }

        /// <summary>

        /// 原字符

        /// </summary>

        public char Key { get; set; }



        public Node()

        {



        }



        public Node(int weight, char value)

        {

            this.Weight = weight;

            this.Key = value;

        }

        /// <summary>

        /// 实现比较接口,用于排序

        /// </summary>

        public int CompareTo(object obj)

        {

            int result = 0;

            Node tmp = obj as Node;



            if (tmp.Weight > this.Weight)

            {

                result = 1;

            }

            else if (tmp.Weight < this.Weight)

            {

                result = -1;

            }



            return result;

        }

    }



    /// <summary>

    /// 获得权值数组

    /// </summary>

    /// <param name="str"></param>

    /// <returns></returns>

    public Node[] GetWeightArray(string str)

    {

        List<Node> result = new List<Node>();



        char[] charArr = str.ToCharArray();



        while (charArr.Length > 0)

        {

            char[] cntChars = null;

            var tmp = charArr.Where(m => m == charArr[0]);

            cntChars = new char[tmp.Count()];

            tmp.ToArray().CopyTo(cntChars, 0);

            charArr = charArr.Where(m => m != tmp.First()).ToArray();



            result.Add(new Node(cntChars.Length, cntChars[0]));

        }



        return result.ToArray();

    }



    /// <summary>

    /// 构建哈弗曼树

    /// </summary>

    /// <param name="sources">权值数组</param>

    /// <returns>返回哈弗曼树根</returns>

    public Node CreateHuffmanTree(Node[] sources)

    {

        Node result = null;

        Node[] nodes = sources;

        bool isNext = true;



        while (isNext)

        {

            if (nodes.Length == 2)

            {

                result = new Node();

                result.LChild = nodes[0];

                result.RChild = nodes[1];

                isNext = false;

            }



            Array.Sort(nodes);

            Node n1 = nodes[nodes.Length - 1];

            Node n2 = nodes[nodes.Length - 2];

            Node tmp = new Node();

            tmp.Weight = n1.Weight + n2.Weight;

            tmp.LChild = n1;

            tmp.RChild = n2;



            Node[] tmpNds = new Node[nodes.Length - 1];

            Array.Copy(nodes, 0, tmpNds, 0, nodes.Length - 1);

            tmpNds[tmpNds.Length - 1] = tmp;



            nodes = tmpNds;

        }



        return result;

    }



    /// <summary>

    /// 字符串转换为哈弗曼代码.当然可以改成二进制数据

    /// </summary>

    /// <param name="key">编码字典</param>

    /// <param name="str">传入字符串</param>

    /// <returns>编码后的字符串</returns>

    public string StringToHuffmanCode(out Dictionary<char, string> key, string str)

    {

        string result = "";



        var tmps = GetWeightArray(str);



        var tree = CreateHuffmanTree(tmps);

        var dict = CreateHuffmanDict(tree);



        foreach (var item in dict)

        {

            Console.WriteLine(item);

        }



        result = ToHuffmanCode(str, dict);



        key = dict;

        return result;

    }



    /// <summary>

    /// 创建哈弗曼代码字典

    /// </summary>

    /// <param name="hTree">哈弗曼树</param>

    /// <returns></returns>

    public Dictionary<char, string> CreateHuffmanDict(Node hTree)

    {

        return CreateHuffmanDict("", hTree);

    }



    private Dictionary<char, string> CreateHuffmanDict(string code, Node hTree)

    {

        Dictionary<char, string> result = new Dictionary<char, string>();



        if (hTree.LChild == null && hTree.RChild == null)

        {

            result.Add(hTree.Key, code);

        }

        else

        {

            var dictL = CreateHuffmanDict(code + "0", hTree.LChild);

            var dictR = CreateHuffmanDict(code + "1", hTree.RChild);



            foreach (var item in dictL)

            {

                result.Add(item.Key, item.Value);

            }



            foreach (var item in dictR)

            {

                result.Add(item.Key, item.Value);

            }

        }



        return result;

    }



    /// <summary>

    /// 源字符串转换到哈弗曼代码

    /// </summary>

    /// <param name="source">源字符串</param>

    /// <param name="hfdict">哈弗曼代码字典</param>

    /// <returns>编译后代码</returns>

    public string ToHuffmanCode(string source, Dictionary<char, string> hfdict)

    {

        string result = "";



        for (int i = 0; i < source.Length; i++)

        {

            result += hfdict.First(m => m.Key == source[i]).Value;

        }



        return result;

    }



    /// <summary>

    /// 解析回字符串

    /// </summary>

    /// <param name="code">哈弗曼代码</param>

    /// <param name="hfdict">哈弗曼代码字典</param>

    /// <returns>解析后字符串</returns>

    public string ToText(string code, Dictionary<char, string> hfdict)

    {

        string result = "";



        for (int i = 0; i < code.Length; )

        {

            foreach (var item in hfdict)

            {

                if (    code[i] == item.Value[0]

                    && item.Value.Length + i <= code.Length)

                {

                    char[] tmpArr = new char[item.Value.Length];



                    Array.Copy(code.ToCharArray(), i, tmpArr, 0, tmpArr.Length);



                    if (new String(tmpArr) == item.Value)

                    {

                        result += item.Key;

                        i += item.Value.Length;

                        break;

                    }

                }

            }

        }



        return result;

    }

}

 

你可能感兴趣的:(C#)