logo

Хуффман Цодинг Јава

Хафманов алгоритам кодирања је предложио Давид А. Хуффман 1950. То је а компресију података без губитака механизам. Такође је познато као кодирање компресије података. Широко се користи у компресији слика (ЈПЕГ или ЈПГ). У овом одељку ћемо разговарати о Хафманово кодирање и декодирање, а такође имплементира свој алгоритам у Јава програм.

Знамо да је сваки знак низ од 0 и 1 и да се складишти помоћу 8-бита. Механизам се зове кодирање фиксне дужине јер сваки знак користи исти број фиксних битова.

јава лонг то инт

Овде се поставља питање, да ли је могуће смањити количину простора потребног за чување карактера?

Да, могуће је коришћењем кодирање променљиве дужине. У овом механизму користимо неке знакове који се јављају чешће у поређењу са другим ликовима. У овој техници кодирања, можемо представити исти део текста или стринг смањењем броја битова.

Хуффман Енцодинг

Хафманово кодирање имплементира следеће кораке.

  • Свим датим знаковима додељује код променљиве дужине.
  • Дужина кода знака зависи од тога колико се често појављује у датом тексту или низу.
  • Знак добија најмањи код ако се често јавља.
  • Знак добија највећи код ако се најмање појави.

Хафманово кодирање следи а правило префикса што спречава двосмисленост током декодирања. Правило такође обезбеђује да се код додељен знаку не третира као префикс кода додељеног било ком другом знаку.

Постоје следећа два главна корака укључена у Хафманово кодирање:

  • Прво, конструишите а Хафманово дрво из датог улазног низа или знакова или текста.
  • Доделите Хафманов код сваком знаку преласком преко дрвета.

Хајде да укратко објаснимо горња два корака.

Хуффман Трее

Корак 1: За сваки знак чвора креирајте листни чвор. Листни чвор знака садржи фреквенцију тог знака.

Корак 2: Поставите све чворове сортираним редоследом према њиховој фреквенцији.

Корак 3: Може постојати стање у којем два чвора могу имати исту фреквенцију. У том случају урадите следеће:

  1. Креирајте нови унутрашњи чвор.
  2. Учесталост чвора биће збир фреквенција та два чвора који имају исту фреквенцију.
  3. Означите први чвор као лево дете, а други чвор као десно дете новокреираног унутрашњег чвора.

4. корак: Поновите кораке 2 и 3 док сви чворови не формирају једно стабло. Тако добијамо Хафманово дрво.

Пример Хуффмановог кодирања

Претпоставимо да морамо да кодирамо стринг Абра Цадабра. Одредите следеће:

  1. Хафманов код за све ликове
  2. Просечна дужина кода за дати стринг
  3. Дужина кодираног низа

(и) Хафманов код за све ликове

Да бисмо одредили код за сваки знак, прво конструишемо а Хафманово дрво.

Корак 1: Направите парове знакова и њихове фреквенције.

јава визуализатор

(а, 5), (б, 2), (ц, 1), (д, 1), (р, 2)

Корак 2: Сортирај парове у односу на фреквенцију, добијамо:

(ц, 1), (д, 1), (б, 2) (р, 2), (а, 5)

Корак 3: Изаберите прва два знака и придружите их под надређеним чвором.

Хуффман Цодинг Јава

Примећујемо да родитељски чвор нема фреквенцију, па му морамо доделити фреквенцију. Фреквенција родитељског чвора биће збир његових подређених чворова (левог и десног), тј. 1+1= 2.

Хуффман Цодинг Јава

4. корак: Понављајте кораке 2 и 3 док не добијемо једно дрво.

Примећујемо да су парови већ сортирани (по кораку 2). Поново одаберите прва два пара и спојите их.

Хуффман Цодинг Јава

Примећујемо да родитељски чвор нема фреквенцију, па му морамо доделити фреквенцију. Фреквенција родитељског чвора биће збир његових подређених чворова (левог и десног), тј. 2+2= 4.

Хуффман Цодинг Јава

Опет, проверавамо да ли су парови поређани или не. У овом кораку морамо да сортирамо парове.

Хуффман Цодинг Јава

Према кораку 3, изаберите прва два пара и спојите их, добијамо:

Хуффман Цодинг Јава

Примећујемо да родитељски чвор нема фреквенцију, па му морамо доделити фреквенцију. Фреквенција родитељског чвора биће збир његових подређених чворова (левог и десног), тј. 2+4= 6.

трећи нормални облик
Хуффман Цодинг Јава

Опет, проверавамо да ли су парови поређани или не. У овом кораку морамо да сортирамо парове. Након сортирања дрво изгледа овако:

Хуффман Цодинг Јава

Према кораку 3, изаберите прва два пара и спојите их, добијамо:

Хуффман Цодинг Јава

Примећујемо да родитељски чвор нема фреквенцију, па му морамо доделити фреквенцију. Фреквенција родитељског чвора биће збир његових подређених чворова (левог и десног), тј. 5+6= Једанаест.

Хуффман Цодинг Јава

Дакле, добијамо једно дрво.

Коначно ћемо пронаћи код за сваки знак уз помоћ горњег стабла. Доделите тежину свакој ивици. Имајте на уму да сваки пондерисана лева ивица је 0 анд тхе пондерисана десна ивица је 1.

Хуффман Цодинг Јава

Примећујемо да су улазни карактери представљени само у излазним чворовима, а унутрашњи чворови имају нулте вредности. Да бисте пронашли Хафманов код за сваки знак, пређите преко Хафмановог стабла од коренског чвора до лисног чвора тог одређеног знака за који желимо да пронађемо код. Табела описује код и дужину кода за сваки знак.

карактер Фреквенција Код Дужина кода
А 5 0 1
Б 2 111 3
Ц 1 1100 4
Д 1 1101 4
Р 2 10 2

Примећујемо да најчешћи знак добија најкраћу дужину кода, а ређе карактер добија највећу дужину кода.

Сада можемо да кодирамо стринг (Абра Цадабра) које смо горе узели.

к-нн алгоритам
 0 111 10 0 1100 0 1101 0 111 10 0 

(ии) Просечна дужина кода за стринг

Просечна дужина кода Хафмановог стабла се може одредити коришћењем формуле дате у наставку:

 Average Code Length = ∑ ( frequency × code length ) / ∑ ( frequency ) 

= { (5 к 1) + (2 к 3) + (1 к 4) + (1 к 4) + (2 к 2) } / (5+2+1+1+2)

= 2,09090909

(иии) Дужина кодираног низа

Дужина кодиране поруке се може одредити коришћењем следеће формуле:

 length= Total number of characters in the text x Average code length per character 

= 11 к 2,09090909

= 23 бита

Хафманов алгоритам кодирања

 Huffman (C) n=|C| Q=C for i=1 to n-1 do z=allocate_Node() x=left[z]=Extract_Min(Q) y=right[z]=Extract_Min(Q) f[z]=f[x]+f[y] Insert(Q,z) return Extract_Min(Q) 

Хафманов алгоритам је похлепан алгоритам. Пошто у свакој фази алгоритам тражи најбоље доступне опције.

Временска сложеност Хафмановог кодирања је О(нлогн). Где је н број знакова у датом тексту.

Хуффман Децодинг

Хафманово декодирање је техника која конвертује кодиране податке у почетне податке. Као што смо видели у кодирању, Хафманово стабло је направљено за улазни низ и карактери се декодирају на основу њихове позиције у стаблу. Процес декодирања је следећи:

индекоф јава
  • Почните да прелазите преко дрвета од корен чвор и потражите карактер.
  • Ако се померимо лево у бинарном стаблу, додајте 0 коду.
  • Ако се померимо десно у бинарном стаблу, додајте 1 коду.

Подређени чвор садржи улазни карактер. Додељује му се код формиран од наредних 0 и 1. Временска сложеност декодирања низа је На), где је н дужина низа.

Хуффман програм за кодирање и декодирање Јава

У следећем програму користили смо структуре података као што су приоритетни редови, стекови и стабла да дизајнирамо логику компресије и декомпресије. Засноваћемо наше услужне програме на широко коришћеној алгоритамској техници Хафмановог кодирања.

ХуффманЦоде.јава

 import java.util.Comparator; import java.util.HashMap; import java.util.Map; import java.util.PriorityQueue; //defining a class that creates nodes of the tree class Node { //storing character in ch variable of type character Character ch; //storing frequency in freq variable of type int Integer freq; //initially both child (left and right) are null Node left = null; Node right = null; //creating a constructor of the Node class Node(Character ch, Integer freq) { this.ch = ch; this.freq = freq; } //creating a constructor of the Node class public Node(Character ch, Integer freq, Node left, Node right) { this.ch = ch; this.freq = freq; this.left = left; this.right = right; } } //main class public class HuffmanCode { //function to build Huffman tree public static void createHuffmanTree(String text) { //base case: if user does not provides string if (text == null || text.length() == 0) { return; } //count the frequency of appearance of each character and store it in a map //creating an instance of the Map Map freq = new HashMap(); //loop iterates over the string and converts the text into character array for (char c: text.toCharArray()) { //storing character and their frequency into Map by invoking the put() method freq.put(c, freq.getOrDefault(c, 0) + 1); } //create a priority queue that stores current nodes of the Huffman tree. //here a point to note that the highest priority means the lowest frequency PriorityQueue pq = new PriorityQueue(Comparator.comparingInt(l -&gt; l.freq)); //loop iterate over the Map and returns a Set view of the mappings contained in this Map for (var entry: freq.entrySet()) { //creates a leaf node and add it to the queue pq.add(new Node(entry.getKey(), entry.getValue())); } //while loop runs until there is more than one node in the queue while (pq.size() != 1) { //removing the nodes having the highest priority (the lowest frequency) from the queue Node left = pq.poll(); Node right = pq.poll(); //create a new internal node with these two nodes as children and with a frequency equal to the sum of both nodes&apos; frequencies. Add the new node to the priority queue. //sum up the frequency of the nodes (left and right) that we have deleted int sum = left.freq + right.freq; //adding a new internal node (deleted nodes i.e. right and left) to the queue with a frequency that is equal to the sum of both nodes pq.add(new Node(null, sum, left, right)); } //root stores pointer to the root of Huffman Tree Node root = pq.peek(); //trace over the Huffman tree and store the Huffman codes in a map Map huffmanCode = new HashMap(); encodeData(root, &apos;&apos;, huffmanCode); //print the Huffman codes for the characters System.out.println(&apos;Huffman Codes of the characters are: &apos; + huffmanCode); //prints the initial data System.out.println(&apos;The initial string is: &apos; + text); //creating an instance of the StringBuilder class StringBuilder sb = new StringBuilder(); //loop iterate over the character array for (char c: text.toCharArray()) { //prints encoded string by getting characters sb.append(huffmanCode.get(c)); } System.out.println(&apos;The encoded string is: &apos; + sb); System.out.print(&apos;The decoded string is: &apos;); if (isLeaf(root)) { //special case: For input like a, aa, aaa, etc. while (root.freq-- &gt; 0) { System.out.print(root.ch); } } else { //traverse over the Huffman tree again and this time, decode the encoded string int index = -1; while (index <sb.length() - 1) { index="decodeData(root," index, sb); } traverse the huffman tree and store codes in a map function that encodes data public static void encodedata(node root, string str, huffmancode) if (root="=" null) return; checks node is leaf or not (isleaf(root)) huffmancode.put(root.ch, str.length()> 0 ? str : &apos;1&apos;); } encodeData(root.left, str + &apos;0&apos;, huffmanCode); encodeData(root.right, str + &apos;1&apos;, huffmanCode); } //traverse the Huffman Tree and decode the encoded string function that decodes the encoded data public static int decodeData(Node root, int index, StringBuilder sb) { //checks if the root node is null or not if (root == null) { return index; } //checks if the node is a leaf node or not if (isLeaf(root)) { System.out.print(root.ch); return index; } index++; root = (sb.charAt(index) == &apos;0&apos;) ? root.left : root.right; index = decodeData(root, index, sb); return index; } //function to check if the Huffman Tree contains a single node public static boolean isLeaf(Node root) { //returns true if both conditions return ture return root.left == null &amp;&amp; root.right == null; } //driver code public static void main(String args[]) { String text = &apos;javatpoint&apos;; //function calling createHuffmanTree(text); } } </sb.length()>

Излаз:

 Huffman Codes of the characters are: {p=000, a=110, t=111, v=001, i=010, j=011, n=100, o=101} The initial string is: javatpoint The encoded string is: 011110001110111000101010100111 The decoded string is: javatpoint