mirror of
https://github.com/TMD44/elte-ik-pti-bsc-zarovizsga.git
synced 2025-08-11 21:39:05 +02:00
A gyerek és annak gyerekei, illetve szülő és annak szülei kifejezés félreérthető volt (úgy is értelmezhető. hogy a sor megáll az unokáknál, nagyszülőknél). Ezt igyekeztem rekurzióval javítani
400 lines
28 KiB
TeX
400 lines
28 KiB
TeX
\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 leszármazottai
|
|
\item \textit{ősök}: egy csúcs szülője és annak ősei
|
|
\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} |