Prezentowane materiały są przeznaczone dla uczniów szkół ponadgimnazjalnych Autor artykułu: mgr Jerzy Wałaszek |
©2014 mgr
Jerzy Wałaszek
|
Drzewo (ang. tree) jest strukturą danych zbudowaną z elementów, które nazywamy węzłami (ang. node). Dane przechowuje się w węzłach drzewa. Węzły są ze sobą powiązane w sposób hierarchiczny za pomocą krawędzi (ang. edge), które zwykle przedstawia się za pomocą strzałki określającej hierarchię. Pierwszy węzeł drzewa nazywa się korzeniem (ang. root node). Od niego "wyrastają" pozostałe węzły, które będziemy nazywać synami (ang. child node). Synowie są węzłami podrzędnymi w strukturze hierarchicznej. Synowie tego samego ojca są nazywani braćmi (ang. sibling node). Węzeł nadrzędny w stosunku do syna nazwiemy ojcem (ang. parent node). Ojcowie są węzłami nadrzędnymi w strukturze hierarchicznej. Jeśli węzeł nie posiada synów, to nazywa się liściem (ang. leaf node), w przeciwnym razie nazywa się węzłem wewnętrznym (ang. internal node, inner node, branch node).
Za wyjątkiem korzenia wszystkie pozostałe węzły w drzewie posiadają swojego ojca. W normalnym drzewie liczba synów dla dowolnego węzła nie jest ograniczona. Istnieje jednakże bardzo ważna klasa drzew, w których dany węzeł może posiadać co najwyżej dwóch synów. Noszą one nazwę drzew binarnych (ang. binary tree). Ciąg węzłów połączonych krawędziami nazwiemy ścieżką (ang. path). Od korzenia do określonego węzła w drzewie wiedzie zawsze dokładnie jedna ścieżka prosta, tzn. taka, iż zawarte w niej węzły pojawiają się tylko jeden raz. Długością ścieżki (ang. path length) nazwiemy liczbę krawędzi łączących węzły w ścieżce. Dla naszego drzewa mamy następujące ścieżki proste od korzenia do kolejnych węzłów:
Długość ścieżki prostej od korzenia do danego węzła nazywa się poziomem węzła (ang. node level). Korzeń drzewa ma zawsze poziom 0. W naszym drzewie węzły B, C i D mają poziom 1, a E, F, G i H mają poziom 2. Wysokość drzewa (ang. tree height) jest równa największemu poziomowi węzłów (lub najdłuższej ścieżce rozpoczynającej się w korzeniu). Dla naszego drzewa wysokość jest równa 2. Wysokość węzła (ang. node height), to długość najdłuższej ścieżki od tego węzła do liścia. Dla korzenia wysokość węzła jest równa wysokości drzewa:
Poziom drzewa (ang. tree level, the level of a tree) dla danego węzła to długość ścieżki prostej od korzenia do danego węzła.
Liczba krawędzi powiązanych z danym węzłem nosi nazwę stopnia węzła (ang. node degree). Krawędzie drzewa są krawędziami skierowanymi (ang. directed edge) i oznaczamy je za pomocą strzałek. Kierunek strzałki jednoznacznie określa pozycję w hierarchii – strzałka wychodzi od ojca i kończy się na synu. Z tego powodu stopień węzła rozbija się na dwa stopnie:
stopień wejściowy
(ang. node in-degree) – liczba krawędzi wchodzących do węzła, dla
drzewa nigdy nie przekracza 1, a jest równy 0 tylko dla korzenia,
stopień wyjściowy (ang. node out-degree) – liczba krawędzi wychodzących z węzła, określa liczbę synów.
Stopień węzła jest sumą stopnia wejściowego i wyjściowego.
Zwróć uwagę, że liście nie będące korzeniem (jeśli korzeń jest liściem, to jego stopień wynosi 0) mają zawsze stopień równy 1. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Drzewo binarneDrzewo, w którym węzły mogą posiadać co najwyżej dwóch synów, nazywa się drzewem binarnym (ang. binary tree, B-tree). Węzły potomne nazywamy odpowiednio synem lewym (ang. left child node) i synem prawym (ang. right child node). Drzewa binarne mają ogromne znaczenie w informatyce, ponieważ za ich pomocą można odwzorować również drzewa, których węzły posiadają dowolną liczbę synów – sposób takiego odwzorowania podamy w dalszej części rozdziału.
W drzewie binarnym stopień każdego węzła nie przekracza 3. Stopień korzenia nie przekracza 2. Regularne drzewo binarne (ang. regular binary tree, proper binary tree) zawiera wyłącznie węzły, których stopień wyjściowy jest albo równy 2 (węzeł posiada dwóch synów – jest węzłem wewnętrznym), albo 0 (węzeł nie posiada synów – jest liściem).
Dla regularnego drzewa binarnego liczba węzłów na poziomie k-tym
jest zawsze równa 2k.
Liczba wszystkich węzłów, czyli rozmiar drzewa
(ang. binary tree size) jest równa
Dla n węzłów liczba poziomów jest równa log2(n+1). Ponumerujmy poziomami kolejne węzły, idąc od strony lewej do prawej:
Otrzymane numery węzłów są powiązane ze strukturą hierarchii drzewa prostymi zależnościami:
Węzeł o numerze k znajduje się na poziomie o numerze [log2(k+1)]. Węzeł o numerze k jest wewnętrzny, jeśli 2k+2 < n. W przeciwnym razie węzeł jest liściem. Własności te pozwalają odwzorowywać regularne drzewo binarne w ciąg elementów i na odwrót
Kompletne drzewo binarne (ang. complete binary tree) posiada zapełnione węzłami wszystkie poziomy z wyjątkiem ostatniego, jednakże na ostatnim poziomie węzły są zapełnione począwszy od lewej strony.
Kompletne drzewo binarne również da się odwzorować w ciąg węzłów. W takim drzewie liczba elementów n może być mniejsza od maksymalnej liczby węzłów, ponieważ ostatni poziom nie musi posiadać kompletu węzłów. Jednakże w przeciwieństwie do drzewa regularnego węzeł wewnętrzny może posiadać tylko jednego, lewego syna (u nas węzłem takim jest węzeł 4). Dlatego w kompletnym drzewie binarnym o rozmiarze n dla węzła o numerze k zachodzi:
2k + 2 > n – węzeł
jest liściem
2k + 2 = n – węzeł jest ostatnim węzłem wewnętrznym i posiada tylko lewego syna 2k + 2 < n – węzeł jest węzłem wewnętrznym i posiada obu synów.
Poddrzewo (ang. subtree) jest drzewem zawartym w drzewie, gdy jako korzeń przyjmiemy jeden z węzłów. Dla danego węzła drzewa binarnego mogą istnieć dwa poddrzewa: lewe poddrzewo (ang. left subtree) – korzeniem jest lewy syn i analogicznie prawe poddrzewo (ang. right subtree) – korzeniem jest prawy syn:
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Reprezentacja drzew binarnych w programie
Istnieje wiele różnych rozwiązań dla reprezentacji drzew binarnych w pamięci
komputera. Tutaj podamy te najprostsze.
Kompletne drzewo binarneW tym przypadku drzewo możemy odwzorować w tablicy n-elementowej. Każdy element tablicy jest węzłem. Hierarchię drzewa przedstawiamy przy pomocy indeksów i ich własności dla kompletnych drzew binarnych. Korzeniem drzewa jest element o indeksie 0. Jego dwoma synami są kolejno elementy o indeksach 1 (lewy syn) i 2 (prawy syn). Postępując podobnie z pozostałymi węzłami otrzymamy całe drzewo binarne:
Niekompletne drzewo binarneDrzewo odwzorowujemy podobnie jak listę. Każdy element jest strukturą, która oprócz danych zawiera dwa lub trzy wskaźniki:
Gdzie:
up – wskazuje ojca danego węzła. Dla korzenia pole to
zawiera wskazanie puste
left – wskazuje lewego syna right – wskazuje prawego syna data – dane dowolnego typu przechowywane przez węzeł
Wskaźniki pozwalają na przemieszczanie się po węzłach w strukturze drzewa. Wskaźniki left i right umożliwiają przechodzenie w dół drzewa. Wskaźnik up prowadzi w górę do ojca danego węzła. Jeśli ten kierunek nie jest istotny, to wskaźnik może zostać pominięty (wersja uproszczona). |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Przechodzenie drzew binarnych – DFSDrzewa odzwierciedlają różnego rodzaju struktury. W węzłach są przechowywane różne informacje. Często będziemy spotykać się z zadaniem, które wymaga odwiedzenia każdego węzła drzewa i przetworzenia informacji przechowywanych w węźle. Zadanie to realizują algorytmy przechodzenia drzewa (ang. tree traversal algorithm). Polegają one na poruszaniu się po drzewie od węzła do węzła wzdłuż krawędzi w pewnym porządku i przetwarzaniu danych przechowywanych w węzłach. Istnieje kilka takich algorytmów o różnych własnościach. Omówimy je w tym rozdziale Algorytm DFSOdwiedzenie węzła (ang. node
visit)
polega na dojściu do danego węzła po strukturze drzewa oraz
przetworzenie danych zawartych w węźle. Przeszukiwanie w głąb
(ang. Depth First Search - DFS) jest bardzo popularnym algorytmem
przechodzenia przez wszystkie węzły poddrzewa, którego korzeniem jest
węzeł startowy (jeśli węzłem startowym będzie korzeń
drzewa, to DFS przejdzie przez wszystkie węzły zawarte w drzewie).
Zasada działania tego algorytmu opiera się na rekurencji lub stosie,
którym zastępujemy wywołania rekurencyjne. Ze względu na kolejność
odwiedzin węzłów wyróżniamy trzy odmiany DFS (istnieją
jeszcze trzy dalsze będące "lustrzanymi odbiciami"):
DFS: pre-order – przejście wzdłużneW przejściu wzdłużnym (ang. pre-order traversal) najpierw odwiedzamy korzeń poddrzewa, a następnie przechodzimy kolejno lewe i prawe poddrzewo. Prześledź poniższy przykład:
Na poniższym rysunku zaznaczyliśmy linię przejścia przez kolejne węzły drzewa.
Algorytm rekurencyjny DFS:preorder dla drzewa binarnegoWejście
Wyjście:przetworzenie wszystkich węzłów drzewa.
Lista kroków:
Algorytm stosowy DFS:preorder dla drzewa binarnegoWejście
Wyjście:przetworzenie wszystkich węzłów drzewa.
Elementy pomocnicze:
Lista kroków:
DFS: in-order – przejście poprzeczneW przejściu poprzecznym (ang. in-order traversal) najpierw przechodzimy lewe poddrzewo danego węzła, następnie odwiedzamy węzeł i na koniec przechodzimy prawe poddrzewo.
Algorytm rekurencyjny DFS:inorder dla drzewa binarnegoWejście
Wyjście:przetworzenie wszystkich węzłów drzewa.
Lista kroków:
Algorytm stosowy DFS:inorder dla drzewa binarnegoAlgorytm wykorzystuje stos oraz dodatkowy wskaźnik cp,
którym przemieszczamy się po drzewie.
Wejście
Wyjście:przetworzenie wszystkich węzłów drzewa.
Elementy pomocnicze:
Lista kroków:
DFS: post-order – przejście wsteczneW przejściu wstecznym (ang. post-order traversal) najpierw przechodzimy lewe poddrzewo, następnie prawe, a dopiero na końcu przetwarzamy węzeł.
Algorytm rekurencyjny DFS:postorder dla drzewa binarnegoWejście
Wyjście:przetworzenie wszystkich węzłów drzewa.
Lista kroków:
Algorytm stosowy DFS:postorder dla drzewa binarnegoAlgorytm wykorzystuje stos oraz dwa wskaźniki: pp
– wskazanie poprzedniego węzła i cp – wskazanie bieżącego
węzła. Są one używane do określenia, czy oba poddrzewa danego węzła
zostały przebyte.
Wejście
Wyjście:przetworzenie wszystkich węzłów drzewa.
Elementy pomocnicze:
Lista kroków:
Podsumowanie
|
I Liceum Ogólnokształcące |
Pytania proszę przesyłać na adres email: i-lo@eduinf.waw.pl
W artykułach serwisu są używane cookies. Jeśli nie chcesz ich otrzymywać,
zablokuj je w swojej przeglądarce.
Informacje dodatkowe