\documentclass[margin=0px]{article}

\usepackage{listings}
\usepackage[utf8]{inputenc}
\usepackage{graphicx}
\usepackage{float}
\usepackage[a4paper, margin=0.7in]{geometry}
\usepackage{amsthm}
\usepackage{amssymb}
\usepackage{t1enc}
\usepackage{fancyhdr}
\usepackage{setspace}

\onehalfspacing

\newenvironment{tetel}[1]{\paragraph{#1 \\}}{}

\pagestyle{fancy}
\lhead{\it{PTI BSc Záróvizsga tételek}}
\rhead{15. Adatszerkezetek és adattípusok}

\title{\textbf{{\Large ELTE IK - Programtervező Informatikus BSc} \vspace{0.2cm} \\ {\huge Záróvizsga tételek}} \vspace{0.3cm} \\ 15. Adatszerkezetek és adattípusok}
\author{}
\date{}

\begin{document}
\maketitle

\begin{tetel}{Adatszerkezetek és adattípusok}
    Tömb, verem, sor, láncolt listák; bináris fa, általános fa, bejárások, ábrázolások; bináris
kupac, prioritásos sor; bináris kereső fa és műveletei, AVL fa, B+ fa; hasító táblák, hasító
függvények, kulcsütközés és feloldásai: láncolással, nyílt címzéssel, próbasorozat; gráfok
ábrázolásai.
\end{tetel}

\section{Egyszerű adattípusok}

\subsection{Adattípus}

\textit{Adatszerkezet}: $\sim$ struktúra. \\
\textit{Adattípus}: adatszerkezet és a hozzá tartozó műveletek. \\
\textit{Adatszerkezetek}:
\begin{itemize}
    \item \textit{Tömb}: azonos típusú elemek sorozata, fix méretű.
    \item \textit{Verem}: Mindig a verem tetejére rakjuk a következő elemet, csak a legfelsőt kérdezhetjük le, és vehetjük ki.
          \begin{figure}[H]
              \centering
              \includegraphics[width=0.3\textwidth]{img/Verembe.jpg}
              \includegraphics[width=0.3\textwidth]{img/Verembol.jpg}
              \caption{Verem műveletei}
          \end{figure}
    \item \textit{Sor}: Egyszerű, elsőbbségi és kétvégű. A prioritásos sornál az elemekhez tartozik egy érték, ami alapján rendezhetjük  őket.
          \begin{figure}[H]
              \centering
              \includegraphics[width=0.3\textwidth]{img/Sorba.jpg}
              \includegraphics[width=0.3\textwidth]{img/Sorbol.jpg}
              \caption{Sor műveletei}
          \end{figure}
    \item \textit{Lista}: Láncolt ábrázolással reprezentáljuk. 3 szempont szerint különböztethetjük meg a listákat: fejelem van/nincs, láncolás iránya egy/kettő, ciklusosság van/nincs. Ha fejelemes a listánk, akkor a fejelem akkor is létezik, ha üres a lista. \\
          A lista node-okból áll, minden node-nak van egy, a következőre mutató pointere, illetve lehet az előzőre is, ha kétirányú. Ezen kívül van egy első és egy aktuális node-ra mutató pointer is, és az utolsó elem mutatója NIL. A listát megvalósíthatjuk úgy, hogy tetszőleges helyre lehessen elemet beszúrni, illetve törölni.
          \begin{figure}[H]
              \centering
              \includegraphics[width=0.3\textwidth]{img/Listaba.jpg}
              \includegraphics[width=0.3\textwidth]{img/Torol.jpg}
              \caption{Lista műveletei}
          \end{figure}
\end{itemize}

\section{Fák és bejárásaik, ábrázolásaik}

\subsection{Bináris fa}

A fákat nagy méretű adathalmazok és multihalmazok ábrázolására,
de egyéb adatreprezentációs célokra is gyakran használjuk.
A (bináris) fák esetében minden adatelemnek vagy szokásos nevén csúcsnak 
legfeljebb kettő rákövetkezője van: egy bal és/vagy egy
jobb rákövetkezője.

\textit{Fogalmak:}
\begin{itemize}
    \item \textit{gyerek}: a csúcs bal vagy jobb rákövetkezője
    \item \textit{szülő}: a gyerekek csúcsa
    \item \textit{testvérek}: azonos csúcs gyerekei
    \item \textit{levél}: gyerek nélküli szülő
    \item \textit{gyökércsúcs}: nincs szülője
    \item \textit{belső csúcs}: nem-levél csúcs
    \item \textit{leszármazottak}: egy csúcs gyerekei és annak gyerekei
    \item \textit{ősök}: egy csúcs szülője és annak szülei
\end{itemize}

\subsection{Általános fa}
A bináris fa fogalma általánosítható. Ha a fában egy tetszőleges csúcsnak legfeljebb r rákövetkezője van, r-áris fáról beszélünk. Egy csúcs gyerekeit és a hozzájuk tartozó részfákat ilyenkor [0..r)-beli szelektorokkal szokás sorszámozni. Ha egy csúcsnak nincs i-edik gyereke (i $\epsilon$  [0..r)), akkor az i-edik
részfa üres. Így tehát a bináris fa és a 2-áris fa lényegében ugyanazt jelenti, azzal,
hogy itt a left $\sim$  0 és a right $\sim$ 1 szelektor-megfeleltetést alkalmazzuk.

A fa szintjeit a következők képpen határozzuk meg. A gyökér van a nulladik szinten. Az
i-edik szintű csúcsok gyerekeit az (i + 1)-edik szinten találjuk. A fa magassága egyenlő a legmélyebben fekvő levelei szintszámával. Az üres fa magassága h($\oslash$) = -1.

Az itt tárgyalt fákat gyökeres fáknak is nevezik, mert tekinthetők olyan irányított gráfoknak, amiknek az élei a gyökércsúcstól a levelek felé vannak
irányítva, a gyökérből minden csúcs pontosan egy úton érhető el.


\subsection{Bejárásaik}
A fákkal dolgozó programok gyakran kapcsolódnak a négy klasszikus
bejárás némelyikéhez, amelyek adott sorrend szerint bejárják a fa csúcsait,
és minden csúcsra ugyanazt a műveletet hívják meg, amivel kapcsolatban
megköveteljük, hogy futási ideje $\Theta$  (1) legyen (ami ettől még persze összetett
művelet is lehet). A *f csúcs feldolgozása lehet például f → key kiíratása.
Üres fára mindegyik bejárás az üres program. 
\textit{Nemüres r-áris fákra}
\begin{itemize}
    \item \textit{Preorder}: először a fa gyökerét dolgozza fel, majd sorban bejárja a 0..r - 1-edik részfákat;
        \begin{figure}[H]
            \centering
            \includegraphics[width=0.3\textwidth]{img/preorder.png}
            \caption{Preorder bejárás}
        \end{figure}
    \item \textit{Inorder}: először bejárja a nulladik részfát, ezután a fa gyökerét dolgozza fel, majd sorban bejárja az 1..r - 1-edik részfákat;
        \begin{figure}[H]
            \centering
            \includegraphics[width=0.3\textwidth]{img/inorder.png}
            \caption{Inorder bejárás}
        \end{figure}
    \item \textit{Postorder}: előbb sorban bejárja a 0..r - 1-edik részfákat, és a fa gyökerét csak a részfák után dolgozza fel
        \begin{figure}[H]
            \centering
            \includegraphics[width=0.3\textwidth]{img/postorder.png}
            \caption{Postorder bejárás}
        \end{figure}
    \item \textit{LevelOrder}: a csúcsokat a gyökértől kezdve szintenként, minden szintet balról jobbra bejárva dolgozza fel.
        \begin{figure}[H]
            \centering
            \includegraphics[width=0.3\textwidth]{img/levelOrder.png}
            \caption{LevelOrder bejárás}
        \end{figure}
\end{itemize}

Az első három bejárás tehát nagyon hasonlít egymásra. Nevük megsúgja,
hogy a gyökércsúcsot a részfákhoz képest mikor dolgozzák fel.

\subsection{Ábrázolásaik}
\subsubsection{Grafikus}
A legtermészetesebb és az egyik leggyakrabban használt a bináris fák láncolt
ábrázolása:
\begin{figure}[H]
    \centering
    \includegraphics[width=0.6\textwidth]{img/abrazolas.png}
    \caption{Ugyanaz a bináris fa grafikus és láncolt ábrázolással.}
\end{figure}


\subsubsection{Absztrakt}
Az üres fa reprezentációja a $\oslash$  pointer, jelölése tehát ugyanaz, mint az
absztrakt fáknál. A bináris fa csúcsait pl. az alábbi osztály objektumaiként
ábrázolhatjuk, ahol a BinTree absztrakt típus reprezentációja egyszerűen a
Node*.

\begin{figure}[H]
    \centering
    \includegraphics[width=0.5\textwidth]{img/absztrakt_node.png}
\end{figure}

Néha hasznos, ha a csúcsokban van egy parent szülő pointer is, mert a fában
így felfelé is tudunk haladni.
\begin{figure}[H]
    \centering
    \includegraphics[width=0.5\textwidth]{img/absz_node_parenttel.png}
\end{figure}

\subsubsection{Zárójelezett}

Tetszőleges nemüres bináris fa zárójeles, azaz szöveges alakja:
    ( balRészFa Gyökér jobbRészFa )
Az üres fát az üres string reprezentálja. A könnyebb olvashatóság kedvéért
többféle zárójelpárt is használhatunk. A zárójeles ábrázolás lexikai elemei:
nyitózárójel, csukó zárójel és a csúcsok címkéi.
\begin{figure}[H]
    \centering
    \includegraphics[width=0.5\textwidth]{img/grafikus_szoveges.png}
    \caption{Ugyanaz a bináris fa grafikus és szöveges ábrázolással.}
\end{figure}

\section{Kupac és sor}
A bináris kupac egy konkrét adatszerkezet,
amelyet a prioritásos sor implementálására használnak.
A prioritásos sor általánosabb fogalom, amely többféle adatszerkezetet
vagy algoritmust foglalhat magában a prioritás alapján történő rendezés 
és az elemek elérése szempontjából.

\subsection{Bináris kupac}
Egy teljes bináris fa, 
amelyben az elemek prioritása a csúcsokban található kulcsok alapján van meghatározva. 
A bináris kupac hatékonyan támogatja a prioritásos sor műveleteket,
például az elem beszúrását és eltávolítását a legmagasabb prioritással.
\begin{figure}[H]
    \centering
    \includegraphics[width=0.5\textwidth]{img/konkret_abrazolas.png}
    \caption{Példa}
\end{figure}

\subsection{Metódusai}
\subsubsection{Hozzáadás}
Új elemet hozzáadunk a kupachoz a levélszintre (a legközelebbi szabad pozícióba).
Ezután a kupacban felfelé haladva összehasonlítjuk az új elemet az ő szülőjével.
Ha az új elem prioritása nagyobb, akkor felcseréljük az elemeket, és folytatjuk a felfelé mozgást a egyel magasabb szintre.
Ezt addig ismételjük, amíg az új elem prioritása nem megfelelő a bináris kupac tulajdonságainak.
\begin{figure}[H]
    \centering
    \includegraphics[width=0.5\textwidth]{img/pr_add.png}
    \caption{Az add(x) algoritmusa}
\end{figure}

\subsubsection{Törlés}
A legmagasabb prioritással rendelkező elem mindig a kupac gyökerén található.
Eltávolítjuk(remMax) ezt az elemet, amely a legfelső elem a kupacban.
Ilyenkor a kupac üres lesz, vagy helyettesíteni kell a gyökérlemet az aljában található legutolsó elemmel.
Ha a kupac nem üres, a helyettesítő elemet lefelé mozgatjuk a kupacban, hogy helyreállítsuk a kupac tulajdonságait.
Az elemet összehasonlítjuk a gyermekével, majd a kisebb prioritású gyermekkel cseréljük(sink), ha az nagyobb.
Ezt a folyamatot addig ismételjük, amíg az elem megfelelő helyre nem kerül a kupacban.

\begin{figure}[H]
    \centering
    \includegraphics[width=0.4\textwidth]{img/pr_max.png}
    \caption{A remMax() algoritmusa}
\end{figure}

\begin{figure}[H]
    \centering
    \includegraphics[width=0.4\textwidth]{img/pr_sink.png}
    \caption{A sink(x) algoritmusa}
\end{figure}

\section{Különleges fák}
\subsection{Bináris kereső fa}
\begin{figure}[H]
    \centering
    \includegraphics[width=0.5\textwidth]{img/bin_sreach_tree_example.png}
    \caption{Példa bináris kereső fára}
\end{figure}
A bináris kereső fa egy olyan adatszerkezet, amelyet a rendezett adatok hatékony tárolására és lekérdezésére használnak.
\textit{Tulajdonságai}
\begin{itemize}
    \item \textit{Rendezettség}: Minden csúcsnak van egy kulcsa, amelyek alapján eldönthető, hogy a bal részfában (kisebb mint a csúcs) vagy a jobb részfában (nagyobb mint a csúcs) helyezkedik el.
    \item \textit{Gyors keresés}: Lehetővé teszi a gyors keresést a rendezettségnek köszönhetően. Tehát, ha egy elemet keresünk és a csúcstól indulunk egyből tudjuk, hogy jobbra vagy balra van a keresett elem.    
        \begin{figure}[H]
            \centering
            \includegraphics[width=0.4\textwidth]{img/search.png}
            \caption{Keresés bináris kereső fában}
        \end{figure}
    \item \textit{Beszúrás és törlés}: Beszúrásnál az új elemet a megfelelő helyre illesztjük, a rendezettséget figyelembe véve. Törlésnél pedig a struktúrát kell megváltoztatni, hogy a rendezettség megmaradjon.
        \begin{figure}[H]
            \centering
            \includegraphics[width=0.4\textwidth]{img/insert.png}
            \caption{Beszúrás bináris kereső fába}
        \end{figure}
        \begin{figure}[H]
            \centering
            \includegraphics[width=0.4\textwidth]{img/del.png}
            \caption{Törlés bináris kereső fából}
        \end{figure}
    \item \textit{In-order bejárás}: Ezt a bejárást használva, megkapjuk a bináris kereső fa elemeit rendezett sorrendben.
        \begin{figure}[H]
            \centering
            \includegraphics[width=0.4\textwidth]{img/inorder_bin_search_tree.png}
            \caption{In-order bejárás bináris kereső fában}
        \end{figure}
\end{itemize}

\subsection{AVL fa}
Az AVL fa egy speciális bináris kereső fa. Célja az, hogy fenntartsa az egyensúlyt a fa minden csomópontjában,
hogy a keresési, beszúrási és törlési műveletek hatékonyan végezhetők legyenek.
Tehát a bináris kereső fa tulajdonságain felül van még kettő: a magasság és az önkiegyensúlyozás.

\subsubsection{Magasságtulajdonság}
Az AVL fa az egyensúly fenntartása érdekében használja a magasságtulajdonságot. Minden csomópont rendelkezik egy magasságértékkel, amely a csomóponttól a legtávolabbi levél magasságát jelenti. 
Az AVL fában az összes csomópont magasságkülönbsége legfeljebb 1 lehet, vagyis az AVL fa egyensúlyban van.


\subsubsection{Önkiegyensúlyozás}
Ha egy beszúrási vagy törlési művelet után az AVL fa egyensúlyát megsértik, akkor a fa kiegyensúlyozására szolgáló rotációs műveleteket végeznek.
A rotációk célja, hogy a magasságkülönbséget korrigálják és visszaállítsák az AVL fa egyensúlyát.

\subsubsection{Rotációk}
Annak függvényében, hogy melyik oldal változott és mennyire az alábbi rotációkat kell használni.
Ha a bal oldali részfa süllyed egy szintet akkor - jelölést kap, ha a jobb akkor + jelölést.
A ++/-- azt jelenti, hogy az egyik oldalon a részfa magassága kettővel nagyobb mint a másikon.
\begin{figure}[H]
    \centering
    \includegraphics[width=0.5\textwidth]{img/ppp_rotation.png}
    \includegraphics[width=0.5\textwidth]{img/ppm_rotation.png}
    \includegraphics[width=0.5\textwidth]{img/mmm_rotation.png}
    \includegraphics[width=0.5\textwidth]{img/mmp_rotation.png}
    \includegraphics[width=0.5\textwidth]{img/ppn_rotation.png}
    \includegraphics[width=0.5\textwidth]{img/mmn_roatation.png}
\end{figure}

\subsection{B+ fa}
A B+ fa, amiben minden csúcs legfeljebb d mutatót (4 $\leq$  d), és legfeljebb d-1 kulcsot tartalmaz,ahol d a fára jellemző állandó, a B+ fa fokszáma. 
Úgy tekintjük, hogy a belső csúcsokban mindegyikreferencia
két kulcs "között" van, azaz egy olyan részfa gyökerére mutat, amiben minden érték a kétkulcs között található.

\begin{figure}[H]
    \centering
    \includegraphics[width=0.5\textwidth]{img/b_plus.png}
    \caption{4-es fokszámú B+ fa}
\end{figure}

Tetszőleges d-ed fokú B+ fa a következő invariánsokat teljesíti, ahol 4 $\leq$ d állandó:
\begin{itemize}
    \item Minden levélben legfeljebb d-1 kulcs, és ugyanennyi, a megfelelő adatrekordrahivatkozó mutató található.
    \item A gyökértől mindegyik levél ugyanolyan távol található.
    \item Minden belső csúcsban eggyel több mutató van, mint kulcs, ahol d a felső határ a mutatók számára.
    \item Minden Cs belső csúcsra, ahol k a Cs csúcsban a kulcsok száma: az első gyerekhez tartozórészfában minden kulcs kisebb, mint a Cs első kulcsa; az utolsó gyerekhez tartozó részfábanminden kulcs nagyobb-egyenlő, mint a Cs utolsó kulcsa; és az i-edik gyerekhez tartozó részfában(2 $\leq$ i $\leq$ k) lévő tetszőleges r kulcsra Cs.kulcs[i-1] $\leq$ r < Cs.kulcs[i].
    \item A gyökércsúcsnak legalább két gyereke van. Kivéve, ha ez a fa egyetlen csúcsa.
    \item Minden, a gyökértől különböző belső csúcsnak legalább d/2 alsó egész-rész gyereke van.
    \item Minden levél legalább d/2 alsó egész-rész kulcsot tartalmaz. A B+ fa által reprezentált adathalmaz minden kulcsa megjelenik valamelyik levélben, balról jobbraszigorúan monoton növekvő sorrendben.
\end{itemize}

\subsubsection{Beszúrás}
Ha a fa üres, hozzunk létre egy új levélcsúcsot, és a beszúrandókulcs/mutató pár a tartalma! 
Különben keressük meg a kulcsnak megfelelő levelet! Ha a levélben márszerepel a kulcs, a beszúrás sikertelen. Egyébként:
\begin{itemize}
    \item Ha a csúcsban van üres hely, szúrjuk be a megfelelő kulcs/mutató párt kulcs szerint rendezetten ebbe a csúcsba!
    \item  Ha a csúcs már tele van, vágjuk szét két csúccsá, középen és osszuk el a d darab kulcsot egyenlően a kétcsúcs között! Ha a létre jött csúcs egy levél, vegyük a létrejött második csúcs legkisebb értékének másolatát, és ismételjük meg ezt a beszúró algoritmust, hogy beszúrjuk azt a szülő csúcsba! Ha a csúcs nemlevél, vegyük ki a középső értéket a kulcsok elosztása során, és ismételjük meg ezt a beszúróalgoritmust, hogy beszúrjuk ezt a középső értéket a szülő csúcsba! (Ha kell, a szülő csúcsot előbblétrehozzuk. Ekkor a B+ fa magassága nő.)
\end{itemize} 

\subsubsection{Törlés}
Keressük meg a törlendő kulcsot tartalmazó levelet! Ha ilyen nincs, a törlés meghiúsul.
\begin{itemize}
    \item Ha keresés során megtalált levélcsúcs egyben a gyökércsúcs is:
    \begin{itemize}
        \item Töröljük a megfelelő kulcsot és a hozzá tartozó mutatót a csúcsból!
        \item Ha a csúcs tartalmaz még kulcsot, kész vagyunk.
        \item Különben töröljük a fa egyetlen csúcsát, és üres fát kapunk.
    \end{itemize}
    \item  A keresés során megtalált levélcsúcs nem a gyökércsúcs:
    \begin{itemize}
        \item Töröljük a megfelelő kulcsot és a hozzá tartozó mutatót a levélcsúcsból!
        \item Ha a levélcsúcs még tartalmaz elég kulcsot és mutatót, hogy teljesítse az invariánsokat, készvagyunk.
        \item Ha a levélcsúcsban már túl kevés kulcs van ahhoz, hogy teljesítse az invariánsokat, de a következő,vagy a megelőző testvérének több van, mint amennyi szükséges, osszuk el a kulcsokat egyenlően közte és a megfelelő testvére között! Írjuk át a két testvér közös szülőjében a két testvérhez tartozóhasító kulcsot a két testvér közül a második minimumára!
        \item Ha a levélcsúcsban már túl kevés kulcs van ahhoz, hogy teljesítse az invariánst, és a következő,valamint a megelőző testvére is a minimumon van, hogy teljesítse az invariánst, akkor egyesítsükegy vele szomszédos testvérével! Ennek során a két testvér közül a (balról jobbra sorrend szerinti)másodikból a kulcsokat és a hozzájuk tartozó mutatókat sorban átmásoljuk az elsőbe, annak eredetikulcsai és mutatói után, majd a második testvért töröljük. Ezután meg kell ismételnünk a törlőalgoritmust a szülőre, hogy eltávolítsuk a szülőből a hasító kulcsot (ami eddig elválasztotta a mostegyesített levélcsúcsokat), a most törölt második testvérre hivatkozó mutatóval együtt. 
    \end{itemize}
    \item Belső — a gyökértől különböző — csúcsból való törlés:
    \begin{itemize}
        \item Töröljük a belső csúcs éppen most egyesített két gyereke közti hasító kulcsot és az egyesítés sorántörölt gyerekére hivatkozó mutatót a belső csúcsból!
        \item Ha a belső csúcsnak van még floor(d/2) gyereke, (hogy teljesítse az invariánsokat) kész vagyunk.
        \item Ha a belső csúcsnak már túl kevés gyereke van ahhoz, hogy teljesítse az invariánsokat, de a következő, vagy a megelőző testvérének több van, mint amennyi szükséges, osszuk el a gyerekeketés a köztük levő hasító kulcsokat egyenlően közte és a megfelelő testvére között, a hasító kulcsokközé a testvérek közti (a közös szülőjükben lévő) hasító kulcsot is beleértve! A gyerekek és ahasító kulcsok újraelosztása során, a középső hasító kulcs a testvérek közös szülőjében a kéttestvérhez tartozó régi hasító kulcs helyére kerül úgy, hogy megfelelően reprezentálja a köztükmegváltozott vágási pontot! (Ha a két testvérben a gyerekek összlétszáma páratlan, akkor azújraelosztás után is annak a testvérnek legyen több gyereke, akinek előtte is több volt!)
        \item Ha a belső csúcsnak már túl kevés gyereke van ahhoz, hogy teljesítse az invariánst, és a következő,valamint a megelőző testvére is a minimumon van, hogy teljesítse az invariánst, akkor egyesítsükegy vele szomszédos testvérével! Az egyesített csúcsot a két testvér közül a (balról jobbra sorrendszerinti) elsőből hozzuk létre. Gyerekei és hasító kulcsai először a saját gyerekei és hasító kulcsaiaz eredeti sorrendben, amiket a két testvér közti (a közös szülőjükben lévő) hasító kulcs követ, ésvégül a második testvér gyerekei és hasító kulcsai jönnek, szintén az eredeti sorrendben. Ezutántöröljük a második testvért. A két testvér egyesítése után meg kell ismételnünk a törlő algoritmusta közös szülőjükre, hogy eltávolítsuk a szülőből a hasító kulcsot
         (ami eddig elválasztotta a mostegyesített testvéreket), a most törölt második testvérre hivatkozó mutatóval együtt.
    \end{itemize}
    \item A gyökércsúcsból való törlés, ha az nem levélcsúcs:
    \begin{itemize}
        \item Töröljük a gyökércsúcs éppen most egyesített két gyereke közti hasító kulcsot és az egyesítés sorántörölt gyerekére hivatkozó mutatót a gyökércsúcsból!
        \item Ha a gyökércsúcsnak van még 2 gyereke, kész vagyunk.
        \item Ha a gyökércsúcsnak csak 1 gyereke maradt, akkor töröljük a gyökércsúcsot, és a megmaradtegyetlen gyereke legyen az új gyökércsúcs! (Ekkor a B+ fa magassága csökken.)    
    \end{itemize}
\end{itemize} 

\section{Hasító táblák}
A hasító tábla (hash table), más néven hasítótábla vagy hash map, egy hatékony adatszerkezet, amely kulcs-érték párokat tárol.
A hasító tábla kulcsokat használ a tárolt értékekhez való gyors hozzáférésre. 
A hasító tábla alapvetően egy tömb, amely az adatokat ún. hash funkció segítségével tárolja és keresi.
\subsection{Hasító függvények}
Amikor egy kulcshoz tartozó értéket hozzá szeretnénk adni a hasító táblához,
először egy hash funkciót alkalmazunk a kulcsra. A hash funkció egy olyan algoritmus, amely egyedi hash kódot generál a kulcs alapján.
A hash kód egy indexet határoz meg a tömbben, ahol az értéket tárolni fogjuk.
\begin{itemize}
    \item \textit{Tárolás:} Az előző lépésben generált hash kód alapján elhelyezzük az értéket a hasító táblában lévő tömb megfelelő indexénél. Ha két vagy több kulcsnak véletlenül ugyanaz a hash kódja, akkor azt hash ütközésnek nevezzük.
    \item \textit{Hash ütközések kezelése:} A hash ütközések kezelése kritikus szerepet játszik a hasító tábla hatékonyságában.
    \begin{itemize}
        \item \textit{Láncolás:} Minden hash kódhoz egy "lánc" tartozik, amely az ütköző kulcsokat tárolja egy adatszerkezetben (általában egy láncolt lista vagy tömb). Ha egy új kulcsnak azonos hash kódja van, a megfelelő láncra kerül, és az érték hozzáadódik a láncolt listához vagy tömbhöz.
        \item \textit{Nyílt címzés:} Az ütköző kulcsokat közvetlenül a tömbben tároljuk, anélkül, hogy külön adatszerkezetet használnánk. Ha egy új kulcsnak ütközik a hash kódja, különböző üres helyeket próbálunk meg keresni a tömbben, amíg üres helyet találunk a tároláshoz.
    \end{itemize}
    \item \textit{Keresés:} A keresés műveletekor ismét alkalmazzuk a hash funkciót a keresett kulcsra, és meghatározzuk az érték tárolásának helyét a hasító táblában. Ha láncolást használunk, akkor végigmegyünk a láncolt listán, hogy a kulcshoz tartozó értéket keresük a hasító táblában, alkalmazzuk a hash funkciót a keresett kulcsra, és meghatározzuk az érték tárolásának helyét a hasító táblában. Ha láncolást használunk, akkor végigmegyünk a láncolt listán vagy a tömbben, és összehasonlítjuk a kulcsokat, hogy megtaláljuk a megfelelő értéket.
    \item \textit{Törlés:} A törlés művelete hasonló a kereséshez. Először alkalmazzuk a hash funkciót a kulcsra, és meghatározzuk az érték tárolásának helyét a hasító táblában. Ha láncolást használunk, akkor végigmegyünk a láncolt listán vagy a tömbben, megtaláljuk a megfelelő értéket, és töröljük azt.
\end{itemize}
A hasító tábla előnyei közé tartozik a gyors adatelérés. Ha a hash funkció jól tervezett és a hash ütközéseket hatékonyan kezeljük, a keresési, beszúrási és törlési műveletek átlagos időkomplexitása O(1) közelíthető, ami nagyon hatékony.
Azonban a hasító tábla néhány korlátot is felvet. Először is, a hash funkció nem mindig garantálja a teljesen egyedi hash kódokat, így lehetőség van a hash ütközések előfordulására. Ezt a megfelelő ütközéskezeléssel kell kezelni. Másodsorban, a hasító tábla fogyasztja a memóriát, különösen, ha nagy méretű tömböt kell tartalmaznia. Az adatmennyiség és a hash funkció hatékonysága közötti egyensúly megtalálása fontos szempont a hatékonyság szempontjából.

\subsection{Próbasorozat}
A próbasorozat egy adatszerkezetekben, például hasító táblákban vagy hasábokban alkalmazott módszer, amelyet a kulcsok egyedi helyét meghatározására használnak.
Amikor egy kulcsot beszúrunk vagy keresünk egy hasító táblában vagy hasábokban, a próbasorozatot használjuk annak meghatározására, hogy hol található a kulcs tárolási helye a táblában.
A próbasorozat olyan sorozat vagy sorrend, amelyet a hash kódhoz vagy a kulcs alapján generálunk.
A leggyakoribb próbasorozatok közé tartoznak:
\begin{itemize}
    \item \textit{Lineáris próbasorozat:} A kiválasztott hash kód vagy index már foglalt a táblában, az algoritmus egymás után következő indexeket próbál meg, amíg üres helyet nem talál. Például, ha az eredeti hash kód 5, és az 5-ös index már foglalt, az algoritmus a 6-os, majd a 7-es indexet próbálja meg, és így tovább.
    \item \textit{Négyzetes próbasorozat:} Az algoritmus négyzet alakban növeli az indexet az ütközés esetén. Például, ha az eredeti hash kód 5, és az 5-ös index már foglalt, az algoritmus a $(5+1^2 = 6)$, majd a $(5+2^2 = 9)$ indexet próbálja meg, és így tovább.
    \item \textit{Dupla hasításos próbasorozat:} Az algoritmus egy második hash funkciót használ az ütközés esetén a következő index meghatározására. A második hash funkció különböző hash kódot generál, amely segít elkerülni az összeomlást és a ciklusokat az indexek között.
\end{itemize}

\section{Gráfok ábrázolásai}
\begin{itemize}
    \item \textit{Szomszédsági mátrix:} A szomszédsági mátrix egy n x n méretű mátrix, ahol n a gráf csúcsainak száma. Az i. sor és j. oszlop eleme az i. és j. csúcs közötti élek jelenlétét vagy súlyát jelzi. Ha az élek irányítottak, akkor a mátrix nem szimmetrikus. Ez a reprezentáció hatékonyan tárolja a gráf szerkezetét, de erőforrásigénye négyzetes arányban nő a csúcsok számával.
    \item \textit{Éllista:} Az éllista egy olyan lista, amely az összes él adatait tartalmazza. Minden élhez tartozik a kezdőcsúcs, a végcsúcs és esetleges további tulajdonságok, például súly. Ez a reprezentáció kevés memóriát igényel, de a gráf szerkezetének lekérdezésekor időigényesebb lehet.
    \item \textit{Szomszédsági lista:} A szomszédsági lista minden csúcshoz tartozó listát tartalmaz, amelyben felsorolják a csúcs közvetlenül szomszédos csúcsait vagy éleit. Ez a reprezentáció általában hatékonyabb a ritka gráfoknál, mivel csak a ténylegesen szomszédos csúcsokat tárolja. Azonban a gráf szerkezetének lekérdezésekor lineáris időigényű lehet.
    \item \textit{Incidencia mátrix:} Az incidencia mátrix egy n x m méretű mátrix, ahol n a csúcsok száma, m pedig az élek száma. Az i. sor és j. oszlop eleme 1, ha az i. csúcs érintett az j. élben, különben 0 vagy más jelölés lehet. Ez a reprezentáció hatékonyan tárolja a gráf szerkezetét és az élek attribútumait, de az erőforrásigénye arányos a csúcsok és élek számával.
\end{itemize}
    

\end{document}