ハフマン ツリーの C# 実装

ハフマン木の説明は前回の記事「ハフマン木を学ぶための3つのステップ」 (https://blog.csdn.net/helloworldchina/article/details/105210054)を参考にしてください。コード。下記参照:

1 つの C# コード

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace HuffmanTree
{
    
    
    class Program
    {
    
    
        public static bool pr = false;//true  打印测试日志
        //哈夫曼树的结构
        struct HTNode
        {
    
    
            public int weight;    // 权值
            public int parent, lChild, rChild;    // 双亲及左右孩子的下标
            
        }
        
        //输出哈夫曼树各结点信息
        static void print(HTNode[] hT)
        {
    
    
            Console.WriteLine("index weight parent lChild rChild");
            String str = "";
            for (int i = 1, m = hT[0].weight; i <= m; i++)
            {
    
    

                str = String.Format("{0,-7}", i);
                Console.Write(str);

                str = String.Format("{0,-7}", hT[i].weight);
                Console.Write(str);

                str = String.Format("{0,-7}", hT[i].parent);
                Console.Write(str);

                str = String.Format("{0,-7}", hT[i].lChild);
                Console.Write(str);

                str = String.Format("{0,-7}", hT[i].rChild);
                Console.Write(str);

                Console.WriteLine();

            }
        }
        // 选择权值最小的两颗树
        static int[] selectMin(HTNode[] hT, int k, int index1, int index2)
        {
    
    
            index1 = index2 = 0;
            int[] resultInt = new int[2];
            int i, j;
            for (j = 1; j <= k; j++)
            {
    
    //使index1,index2分别指向hT中最前面的两个无双亲的结点
                if (0 == hT[j].parent)
                {
    
    
                    if (0 == index1)
                    {
    
    
                        index1 = j;
                    }
                    else
                    {
    
    
                        index2 = j;
                        break;
                    }
                }
            }

            if (hT[index1].weight > hT[index2].weight)
            {
    
    //使结点index1的权小于index2的权
                int t = index1;
                index1 = index2;
                index2 = t;
            }

            for (i = j + 1; i < k; i++)
            {
    
    //继续查找没有双亲且权值最小的两个结点,将其地址记在index1和index2中
                if (0 == hT[i].parent)
                {
    
    
                    if (hT[i].weight < hT[index1].weight)
                    {
    
    
                        index2 = index1;
                        index1 = i;
                    }
                    else if (hT[i].weight < hT[index2].weight)
                    {
    
    
                        index2 = i;
                    }
                }
            }
            resultInt[0] = index1;
            resultInt[1] = index2;
            return resultInt;
        }
        // 构造有n个权值(叶子结点)的哈夫曼树
        static bool createHufmanTree(HTNode[] hT, int n, int k)
        {
    
    
            if (n <= 1) return false;
            //给数组赋初值0
            for (int i = 0; i <= k; i++)
            {
    
    
                hT[i] = new HTNode();// 如不使用此行代码,执行到hT[i].parent =0时会报空指针异常
                hT[i].parent = 0;
                hT[i].lChild = 0;
                hT[i].rChild = 0;
            }
            Console.WriteLine("请依次输入权值,并回车确认");
            for (int i = 1; i <= n; i++)
            {
    
    
                string inputNumber;
                inputNumber = Console.ReadLine();// 输入权值
                hT[i].weight = Int32.Parse(inputNumber);    
            }
            hT[0].weight = k;    // 用0号结点保存结点数量

            if (pr)
            {
    
    
                Console.WriteLine("打印初始的数组:");
                print(hT);
            }

            /****** 初始化完毕, 创建哈夫曼树 ******/
            for (int i = n + 1; i <= k; i++)
            {
    
    
                int index1 = -1, index2 = -1;
                int[] resultInt = new int[2];
                resultInt = selectMin(hT, i, index1, index2);
                index1 = resultInt[0];
                index2 = resultInt[1];
                hT[index1].parent = hT[index2].parent = i;
                hT[i].lChild = index1; hT[i].rChild = index2;    // 作为新结点的孩子
                hT[i].weight = hT[index1].weight + hT[index2].weight;    // 新结点为左右孩子结点权值之和

                if (pr)
                {
    
    
                    Console.WriteLine("打印构建哈夫曼树过程中的数组:");
                    Console.WriteLine("i=" + i);
                    Console.WriteLine("index1=" + index1 + ";index2=" + index2);
                    print(hT);
                }
            }
            return true;
        }
        static int huffmanTreeWPL_w(HTNode[] hT, int i, int deepth)
        {
    
    
            if (hT[i].lChild == 0 && hT[i].rChild == 0)
            {
    
    
                return hT[i].weight * deepth;
            }
            else
            {
    
    
                return huffmanTreeWPL_w(hT, hT[i].lChild, deepth + 1) + huffmanTreeWPL_w(hT, hT[i].rChild, deepth + 1);
            }
        }
        // 计算WPL(带权路径长度)
        static int huffmanTreeWPL(HTNode[] hT)
        {
    
    
            return huffmanTreeWPL_w(hT, hT[0].weight, 0);
        }
        static void Main(string[] args)
        {
    
    
            Console.WriteLine("请输入权值的数量n=? ");
            int n, k;//n 权值数(叶子结点数)  k结点的个数
            string inputCount;
            inputCount = Console.ReadLine();// 输入权值
            n = Int32.Parse(inputCount);
            k = 2 * n - 1;
            //创建存储哈夫曼树的数组
            HTNode[] hT = new HTNode[k + 1];// 0号结点不使用
            if (createHufmanTree(hT, n, k))
            {
    
    
                Console.WriteLine("打印哈夫曼树数组:");
                print(hT);
                Console.WriteLine("WPL = " + huffmanTreeWPL(hT));
            }
            else Console.WriteLine("输入有误,不能创建哈夫曼树!");
        }
    }
}

2 走行結果
ここに画像の説明を挿入

おすすめ

転載: blog.csdn.net/helloworldchina/article/details/105691361