Алгоритм Хаффмана, реализация - C#
Формулировка задачи:
Всем здравствуйте, нужна помощь в реализации алгоритма Хаффмана. Приведу пример с с++ : есть класс X с переменными a float и s string и указателями X *left, *right. создаём лист указателей list<*Х>(заполняем, в каждом объекте кл. храним символ и его частоту). Далее создаём два новых указателя X *d, X*r, сортируем лист по возрастанию, 1эл=d 2эл=r, удаляем первые два эл из листа. Создаём объект класса Х parent передаём посредством конструктора d,r, также в конструкторе вычисляем a=d.a+r.a. Parent записываем в лист. Вроде как-то так, как можно реализовать это на c#?
Код создает дерево, проходит от "листьев" к "корню", как можно реализовать проход обратно от корня к "листьям" ? Что в C# для этого использовать? В с++ это делается с помощью указателей, в шарпе указатели не применяются(
Сформулирую более понятно. Есть такой вот код
using System;
using System.IO;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Text.RegularExpressions;
using MathNet.Numerics;
using MathNet.Numerics.LinearAlgebra.Double;
using MathNet.Numerics.LinearAlgebra.Solvers;
using System.Collections;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
string path;
bool u;
int i1, size;
private void button1_Click(object sender, EventArgs e)
{
float[] mas = new float[size];
List<Ver_Symbol> Ver_S = new List<Ver_Symbol>();
// List<Uzel> Uzel_ = new List<Uzel>();
Dictionary<string, float> ar = new Dictionary<string, float>();
List<float> bezYsl_ver = new List<float>();
List<float> Symbol2 = new List<float>();
List<float> Symbol3 = new List<float>();
string r;
int q = 0, h = 0, k = 0, count =1;
float f;
double D = 0;
string b;
char[] a = new char[27] { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I',
'J','K','L','M','N','O','P','Q','R','S','T',
'U','V','W','X','Y','Z',' '};
char[] rus = new char[34] {'А', 'Б', 'В', 'Г', 'Д', 'Е', 'Ё', 'Ж', 'З',
'И','Й','К','Л','М','Н','О','П','Р','С','Т',
'У','Ф','Х','Ц','Ч','Ш','Щ','Ъ','Ы','Ь','Э','Ю','Я',' '};
using (StreamReader sr = new StreamReader(path))
{
string text = sr.ReadToEnd();
char[] chars = text.ToCharArray(); // посимвольный проход по тексту
if(u==true)
mas = Chastota(a, chars,size);
else
mas = Chastota(rus, chars,size);
}
richTextBox1.Text = " Частоты символов алфавита: "+"\n";
for (int i = 0; i < mas.Length; i++)
{
if(mas[i]!=0)
richTextBox1.Text +=count++ +"\t" +mas[i].ToString()+"\n";
}
f = mas.Sum();
for (int i = 0; i < mas.Length; i++)
{
if (mas[i] != 0)
{
bezYsl_ver.Add(mas[i]/f);
}
}
richTextBox1.Text += "\n Безусловная вер. символов алфавита: " + "\n";
richTextBox1.Text += "\n";
for (int i = 0; i < bezYsl_ver.Count; i++)
{
if (u == true)
{
Ver_s.Add(new Ver_Symbol(a[i].ToString(), bezYsl_ver[i]));
}
else
{
Ver_s.Add(new Ver_Symbol(rus[i].ToString(), bezYsl_ver[i]));
}
}
for (int i = 0; i < Ver_s.Count; i++)
{
if (u == true)
richTextBox1.Text += Ver_s[i] + "\n";
else
richTextBox1.Text += Ver_s[i].ToString() + "\n";
}
Ver_S.Sort(delegate(Ver_Symbol mc1, Ver_Symbol mc2) // сортировка
{
return mc1.a.CompareTo(mc2.a);
});
richTextBox1.Text += "\n";
for (int i = 0; i < Ver_S.Count; i++)
richTextBox1.Text += Ver_S[i].s + "\t" + Ver_S[i].a + "\n";
richTextBox1.Text += "\n";
while (Ver_S.Count != 1)
{
Ver_S.Sort(delegate(Ver_Symbol mc1, Ver_Symbol mc2) // сортировка
{
return mc1.a.CompareTo(mc2.a);
});
r = Ver_S[0].s;
for (int i = 1; i < Ver_S.Count; i++) // присваиваем отсорт. лист переменной r
r+=Ver_S[i].s;
// Ver_Symbol Left_ = Ver_S[0];
// Ver_Symbol Right_= Ver_S[1];
// Uzel parent = new Uzel(Left_, Right_);
Ver_S[0].a = Ver_S[0].a + Ver_S[1].a; // суммируем минимальные элементы
Ver_S[0].s = Ver_S[0].s + Ver_S[1].s;
richTextBox1.Text += r + "\t\t" + Ver_S[0].s + "\t" + Ver_S[0].a; // выводим отсортированный лист и сумму мин. элементов
richTextBox1.Text += "\n";
ar.Add(Ver_S[0].s, Ver_S[0].a);
Ver_S.RemoveAt(0);
Ver_S.RemoveAt(1);
// Ver_S.Add(parent);
}
// foreach (var i in ar)
// richTextBox1.Text += i.Key + "\t" + i.Value + "\n";
richTextBox1.Text += "\n";
for (int i = 0; i < Ver_S.Count; i++)
richTextBox1.Text += Ver_S[i].s + "\t" + Ver_S[i].a + "\n"; // вывод основания дерева
}
private void button2_Click(object sender, EventArgs e)
{
OpenFileDialog openfile = new OpenFileDialog();
openfile.Filter = "txt files (*.txt)|*.txt|All files (*.*)|*.*";
if (openfile.ShowDialog() == DialogResult.OK)
path = openfile.FileName;
}
private void button3_Click(object sender, EventArgs e)
{
richTextBox1.Clear();
textBox1.Clear();
}
public static float[] Chastota(char[] alfavit, char[] chars1,int size1)
{
float[] mas2 = new float[size1];
for (int i = 0; i < alfavit.Length; i++)
{
for (int j = 0; j < chars1.Length; j++)
{
if (alfavit[i] == Char.ToUpper(chars1[j]))
{
mas2[alfavit[i]]++;
}
}
}
return mas2;
}
private void button5_Click(object sender, EventArgs e)
{
u = true;
size = 256;
}
private void button4_Click(object sender, EventArgs e)
{
u = false;
size = 2560;
}
class Ver_Symbol
{
public float a;
public string s;
public Ver_Symbol(string ch, float number)
{
this.s = ch; this.a = number;
}
}
/* class Uzel
{
public float a;
public Ver_Symbol left;
public Ver_Symbol right;
public Uzel(Ver_Symbol L, Ver_Symbol R)
{
this.left = L; this.right = R;
a = L.a + R.a;
}
}
*/
}
}class Node
{
public:
int a;
char c;
Node *left, *right;
Node(){left=right=NULL;}
Node(Node *L, Node *R)
{ left = L;
right = R;
a = L->a + R->a; }
};
void BuildTable(Node *root)
{
if (root->left!=NULL)
{ code.push_back(0);
BuildTable(root->left);}
if (root->right!=NULL)
{ code.push_back(1);
BuildTable(root->right);}
if (root->left==NULL && root->right==NULL) table[root->c]=code;
code.pop_back();
}
////// записываем начальные узлы в список list
list<Node*> t;
for( map<char,int>::iterator itr=m.begin(); itr!=m.end(); ++itr)
{
Node *p = new Node;
p->c = itr->first;
p->a = itr->second;
t.push_back(p); }
////// создаем дерево
while (t.size()!=1)
{
t.sort(MyCompare());
Node *SonL = t.front();
t.pop_front();
Node *SonR = t.front();
t.pop_front();
Node *parent = new Node(SonL,SonR);
t.push_back(parent);
}
Node *root = t.front(); //root - указатель на вершину дерева
////// создаем пары 'символ-код':
BuildTable(root);Решение задачи: «Алгоритм Хаффмана, реализация»
textual
Листинг программы
class Node
{
public:
int a;
char c;
Node *left, *right;
Node(){left=right=NULL;}
Node(Node *L, Node *R)
{ left = L;
right = R;
a = L->a + R->a; }
};