Binárny strom - Morseova abeceda (riešené príklady)

Z Kiwiki
Skočit na navigaci Skočit na vyhledávání
Imbox draft.png
Toto je projekt, na ktorom sa ešte stále pracuje!!

Aj keď sú v tomto dokumente použiteľné informácie, ešte nie je dokončený. Svoje návrhy môžete vyjadriť v diskusii o tejto stránke.

Algoritmy a programovanie - zbierka úloh


Štruktúry

Rekurzia

Dynamická alokácia pamäti

Vyhľadávanie

Triedenie

Lineárny zoznam

Binárny strom

>Binárny strom - Morseova abeceda
>Binárny strom - Huffmanovo kódovanie

Numerické algoritmy

Zadanie[1]

Vytvorte program na dekódovanie správy napísanej v Morseovej abecede. Správu prečítajte z textového súboru.

Analýza úlohy

Pri dekódovaní využijeme binárny vyhľadávací strom. V jeho vrcholoch budú uložené jednotlivé písmená abecedy, v koreni je ako špeciálny znak medzera. Pre potreby tohto príkladu si upravíme dátovú štruktúru binárny strom nasledovne

  • dátová časť bude jeden znak (znak kódovanej abecedy)
  • smerníky lavy a pravy nahradíme smerníkmi bodka a ciarka. Smerníky majú i naďalej význam ľavého a pravého potomka, ale pre ľahšiu orientáciu v kódovacom strome si ich premenujeme.
struct TUzol{
       char  znak;
       TUzol *bodka, *ciarka;
};

Zo súboru čítame postupnosti bodiek a čiarok. Znak bodka znamená presun ukazovateľa na ľavý podstrom, znak čiarka na pravý podstrom.

Bnárny strom reprezentujúci kódovanie morseovej abecedy

Dekódovanie Morseovej abecedy

Ak prečítame zo súboru kód --.. pôjdeme z koreňa vpravo, vpravo, vľavo, vľavo. Skončíme vo vrchole s písmenom z. Takýmto spôsobom pre každý prečítaný kód nájdeme rýchlo zodpovedajúce písmeno. Princíp dekódovanie je v nasledujúcom pseudokóde:

procedure dekoduj(TUzol strom)
begin
   p - pomocný prvok TUzol
   c - premenná typu znak
   p = strom // p je pomocná premenná s ktorou prechádzame strom
   pokiaľ sa zo súboru načítal znak (do premennej c)
   begin
      ak je c znak '.'
        tak  p=p->bodka // presunieme sa na ľavý podstrom
      inak
         ak je c znak '-'
           tak  p=p->ciarka // presunieme sa na pravý podstrom
         inak // načátali sme oddeľovací znak
         begin
            vypíš hodnotu uzla p
            p=strom //v ďalšom cykle budeme dekódovať ďalší znaka  musíme začať od koreňa stromu
         end
   end
end

Pred čítaním kódu ďalšieho písmena nastavíme ukazovateľ opäť na koreň stromu!

Pre jednoduchosť budeme predpokladať, že na vstupe je správa v dohodnutom formáte - za kódom písmena ako oddeľovač nasleduje vždy znak /, za každým slovom aspoň dva znaky //.

Vytvorený program má tri časti - vytvorenie dekódovacieho stromu, otvorenie súboru pre čítanie a postupné dekódovanie správy.

Vzorový príklad

Vzorový vstup

-../-.--/-./.-/--/../-.-./-.-/.//.../-/.-./..-/-.-/-/..-/.-./-.--/

Vzorový výstup

dynamicke struktury

Riešenie v jazyku C

 1 #include <stdlib.h>
 2 #include <iostream.h>
 3 #include <fstream.h>
 4 
 5 struct TUzol{
 6        char  znak;
 7        TUzol *bodka, *ciarka;
 8 };
 9 //------------------------------------------------------------------------------
10 TUzol *vytvor(char z, TUzol *b, TUzol *c)
11 {
12   TUzol *novy = new TUzol;
13   
14   novy->znak = z;
15   novy->bodka  = b;
16   novy->ciarka = c;
17   return(novy);
18 }
19 //------------------------------------------------------------------------------
20 void dekoduj(TUzol *strom)
21 {
22    ifstream fr;
23    fr.open("sprava.txt");
24       
25    TUzol *p;
26    char c;
27    p = strom;
28 
29    while (fr>>c ) 
30    {
31      if (c == '.') 
32         p = p->bodka;
33      else 
34         if (c == '-') 
35            p = p->ciarka;
36         else 
37         {
38           cout<<p->znak;
39           p = strom;
40         }
41   }
42   fr.close();
43 }
44 //------------------------------------------------------------------------------
45 void vypis(TUzol *v) 
46 {
47    if (v != NULL) {
48      vypis(v->bodka);
49      cout<<v->znak;
50      vypis(v->ciarka);
51    }
52 }
53 //------------------------------------------------------------------------------
54 int main()
55 {
56   TUzol *strom = NULL;
57   
58   /* vytvorenie dekódovacieho stromu */
59   strom = vytvor(' ',
60            vytvor('e',
61              vytvor('i',
62                vytvor('s', vytvor('h', NULL, NULL), vytvor('v', NULL, NULL)),
63                vytvor('u', vytvor('f', NULL, NULL), NULL)),
64              vytvor('a',
65                vytvor('r', vytvor('l', NULL, NULL), NULL),
66                vytvor('w', vytvor('p', NULL, NULL), vytvor('j', NULL, NULL)))),
67            vytvor('t',
68              vytvor('n',
69                vytvor('d', vytvor('b', NULL, NULL), vytvor('x', NULL, NULL)),
70                vytvor('k', vytvor('c', NULL, NULL), vytvor('y', NULL, NULL))),
71              vytvor('m',
72                 vytvor('g', vytvor('z', NULL, NULL), vytvor('q', NULL, NULL)),
73                 vytvor('o', NULL, NULL))));
74 
75 
76 
77  cout<<"Sprava: ";
78  dekoduj(strom);
79  return 0;
80 }

Vysvetlenie zdrojového kódu

Hlavný program main

Ako prvé je potrebné vytvoriť binárny strom (riadok 56). Ďalší krok je vytvoriť kódovací strom Morseovej abecedy ako je na obrázku. Na to použijeme funkciu vytvor. Zaujímavý je spôsob jej použitia. Funkcia vytvor má 3 parametre: znak, ktorý predstavuje dekódovanú postupnosť bodiek a čiarok. Ďalej sú to dva smerníky na potomkov aktuálneho uzla. Ľavý potomok (bodka) a pravý potomok (ciarka).

Na riadku 59 je prvý krát použitá funkcia vytvor. Pri tomto volaní vytvárame koreň stromu. Znak obsiahnutý v koreni je medzera. (' '). Druhým parametrom funkcie má byť uzol ktorý je ľavý potomok. Namiesto vytvorenia nového uzla a jeho následného vloženia do stromu strom, opäť použijeme funkciu vytvor, pomocou ktorej vytvárame znak 'e'. Druhý parameter funkcie (pravý potomok uzla - ciarka) je znak 't' - riadok 67. V nasledujúcom kóde je uvedený ekvivalentný zápis pri vytváraní stromu. V tomto príklade nebude použité vnáranie funkcie vytvor.

 1  TUzol *strom = NULL;
 2 
 3  TUzol *h = vytvor('h',NULL,NULL);
 4  TUzol *v = vytvor('v',NULL,NULL);
 5  TUzol *f = vytvor('f',NULL,NULL);
 6  TUzol *s = s=vytvor('s',h,v);
 7  TUzol *u = u=vytvor('u',f,NULL);
 8  TUzol *i = vytvor('i',s,u); 
 9  
10  TUzol *l = vytvor('j',NULL,NULL);
11  TUzol *p = vytvor('p',NULL,NULL);
12  TUzol *j = vytvor('j',NULL,NULL); 
13  TUzol *r = vytvor('r',l,NULL);
14  TUzol *w = vytvor('w',p,j);
15  TUzol *a = a=vytvor('a',r,w);
16  TUzol *e = a=vytvor('e',i,a);
17  
18  TUzol *b = vytvor('b',NULL,NULL);
19  TUzol *x = vytvor('x',NULL,NULL);
20  TUzol *c = vytvor('c',NULL,NULL);
21  TUzol *y = s=vytvor('y',NULL,NULL);
22  TUzol *z = s=vytvor('z',NULL,NULL);
23  TUzol *q = s=vytvor('q',NULL,NULL);
24  
25  TUzol *d = u=vytvor('d',b,x);
26  TUzol *k = vytvor('k',c,y);   
27  TUzol *g = vytvor('g',z,q);   
28  TUzol *o = s=vytvor('o',NULL,NULL);
29 
30  TUzol *m = u=vytvor('m',g,o);
31  TUzol *n = vytvor('n',d,k);   
32  TUzol *t = vytvor('t',n,m); 
33  
34  strom=  vytvor(' ',e,t);

Funkcia vytvor

Opis funkcie Funkcia vytvorí a vráti nový uzol binárneho stromu. Hodnota časti znak nového uzla bude použitá z 1. parametra funkcie.

Parametre funkcie

  • z - znak, ktorý bude obsahovať nový uzol. Tento znak je zakódované písmeno v kódovacom strome Morseovej abecedy.
  • b - smerník na ľavého potomka nového uzla. Určuje ďalší kódový znak v kódovacom strome. Ďalší znak pokračuje kódom '.' (bodka)
  • c - smerník na pravého potomka nového uzla. Určuje ďalší kódový znak v kódovacom strome. Ďalší znak pokračuje kódom '-' (čiarka)

Poznámka: ak má nový uzol potomkov (podľa kódovacieho stromu napríklad znak 'e' má potomkov 'i' a 'a'). Tieto uzly už musia byť vytvorené. Smerníky na tieto existujúce uzly sú v parametroch funkcie vytvor.

Návratová hodnota

Funkcia vráti smerník na novo vytvorený uzol kódovacieho stromu Morseovej abecedy.

Funkcia dekoduj

Na začiatku funkcie je otvorený súbor so vstupnými údajmi. Potom nasleduje samotné dekódovanie. Princíp dekódovania bol vysvetlený v časti Dekódovanie Morseovej abecedy

Odkazy