|
Serwis Edukacyjny w I-LO w Tarnowie
Materiały dla uczniów liceum |
Wyjście Spis treści Wstecz Dalej
Autor artykułu: mgr Jerzy Wałaszek |
©2026 mgr Jerzy Wałaszek
|
Drzewo poszukiwań binarnych (ang. Binary Search Tree) jest drzewem binarnym, w którym każdy węzeł spełnia poniższe reguły:
Innymi słowy, przejście typu in-order tego drzewa daje ciąg wartości niemalejących.
![]() Drzewo BST in-order: 1 2 2 3 5 8 9 |
![]() Drzewo nie BST in-order: 1 2 2 3 2 8 9 |
Powyżej mamy przykład drzewa BST oraz drzewa nie będącego drzewem BST – zaznaczony liść 2 należy do prawego poddrzewa korzenia 3 i jest od niego mniejszy, a w prawym poddrzewie muszą być tylko węzły równe lub większe od korzenia.
Węzły w drzewie BST zawierają trzy wskaźniki, klucz oraz dane:
Pascaltype
PBSTnode = ^BSTnode;
BSTnode = record
up : PBSTnode;
left : PBSTnode;
right : PBSTnode;
key : integer;
Data: typ_danych;
end; |
struct BSTnode
{
BSTnode * up;
BSTnode * left;
BSTnode * right;
int key;
typ_danych data;
}; |
BasicType BSTnode up As BSTnode Ptr left As BSTnode Ptr right As BSTnode Ptr key As Integer data As typ_danych End Type |
| Python (dodatek) |
# węzeł BST
#----------
class BSTnode:
def __init__(self):
self.up = None
self.left = None
self.right = None
self.key = 0
self.data = dane
|
| up | : | wskazanie ojca węzła |
| left | : | wskazanie lewego syna |
| right | : | wskazanie prawego syna |
| key | : | klucz, wg którego węzły są uporządkowane w drzewie BST |
| data | : | dowolne dane węzła |
Dla niektórych drzew BST klucz może być daną, wtedy nie występuje pole data lub jest ono bezpośrednio kluczem.
Drzewa BST pozwalają wyszukiwać zawarte w nich elementy z klasą
złożoności obliczeniowej
| Stan | Opis |
|---|---|
![]() |
Wyszukiwanie rozpoczynamy od korzenia drzewa. Porównujemy wartość węzła z wartością poszukiwaną. Ponieważ jest ona większa od wartości korzenia, idziemy wzdłuż prawej krawędzi do prawego syna (jeśli węzeł nie miałby prawego syna, to oznaczałoby to, że poszukiwanej wartości nie ma w drzewie BST). |
![]() |
W węźle 21 ponownie dokonujemy porównania. Ponieważ poszukiwany węzeł jest mniejszy od 21, wybieramy gałąź lewą i przechodzimy do lewego syna 15. |
![]() |
Porównujemy węzeł 15 z poszukiwanym
19. Ponieważ 19 jest większe, idziemy prawą krawędzią do prawego syna 19. |
![]() |
Porównujemy węzeł 19 z poszukiwanym. Są równe. Wyszukiwanie zakończone. |
Z przedstawionego powyżej schematu wynikają dwa proste wnioski:
![]() Element najmniejszy w drzewie znajdziemy, idąc lewymi gałęziami aż do elementu, który nie posiada już lewego syna |
![]() Element największy w drzewie znajdziemy, idąc prawymi gałęziami aż do elementu, który nie posiada już prawego syna. |
W obu przypadkach nie musimy nawet porównywać węzłów. Min i Max wyznacza sama struktura drzewa BST.
K01: Dopóki (p ≠ nil)(p→key ≠ k), ; przeszukujemy drzewo BST wykonuj krok K02
K02: Jeśli k < p→key, ; decydujemy, którą drogą pójść: to p ← p→left ; w lewo inaczej p ← p→right ; czy w prawo K03: Zakończ z wynikiem p
K01: Jeśli p = nil, to idź do kroku K03 K02: Dopóki p→left ≠ nil, ; szukamy węzła bez lewego syna wykonuj p ← p→left K03: Zakończ z wynikiem p
K01: Jeśli p = nil, to idź do kroku K03 K02: Dopóki p→right ≠ nil, ; szukamy węzła bez prawego syna wykonuj p ← p→right K03: Zakończ z wynikiem p
|
Uwaga: Zanim uruchomisz program, przeczytaj wstęp do tego artykułu, w którym wyjaśniamy funkcje tych programów oraz sposób korzystania z nich. |
| Program wczytuje definicję drzewa
binarnego, którego klucze są liczbami całkowitymi. Wyznacza
klucz
minimalny i maksymalny, a następnie idąc kolejno przez wartości
kluczy od min do max wyświetla informacje o znalezionym węźle. Sposób wprowadzania drzew binarnych opisaliśmy w rozdziale o badaniu drzew binarnych. Tutaj krótko przypomnijmy, że węzły drzewa są numerowane od strony lewej do prawej na kolejnych poziomach. Pierwszą liczbą jest ilość wierzchołków n. Kolejne n wierszy zawiera 3 liczby określające kolejne wierzchołki. Pierwsza liczba w trójce określa klucz węzła. Pozostałe dwie liczby określają kolejno numer węzła będącego lewym i prawym synem. Jeśli węzeł nie ma któregoś z synów, to numer syna przyjmuje wartość zero. W strukturach węzłów nie będziemy wykorzystywać pola up, które tutaj nie będzie nam potrzebne, ponieważ będziemy poruszać się tylko w dół drzewa. |
|
Dane przykładowe (przekopiuj do schowka i
wklej do okna konsoli):
|
Pascal// Wyszukiwanie w drzewie BST
// Data: 24.04.2013
// (C)2013 mgr Jerzy Wałaszek
//---------------------------
program bst;
// Typ węzłów drzewa BST
type
PBSTnode = ^BSTnode;
BSTnode = record
left : PBSTnode;
right : PBSTnode;
key : integer;
end;
// Funkcja wczytuje drzewo BST
// ze standardowego wejścia
// i zwraca wskazanie korzenia
//----------------------------
function read_bst : PBSTnode;
var
// Tablica wskazań węzłów
vp : array of PBSTnode;
key, l, r, i, n : integer;
begin
// Odczytujemy liczbę
// węzłów drzewa
readln(n);
// Tworzymy dynamiczną
// tablicę wskazań węzłów
SetLength(vp, n);
// Tablicę dynamiczną wypełniamy
// wskazaniami węzłów, które
// również tworzymy dynamicznie
for i := 0 to n-1 do
new(vp[i]);
// Teraz wczytujemy definicję
// drzewa i tworzymy jego
// strukturę w pamięci wypełniając
// odpowiednie pola węzłów.
for i := 0 to n-1 do
begin
// Czytamy klucz, numer lewego
// i prawego syna
readln(key, l, r);
// Ustawiamy klucz
vp[i]^.key := key;
// Ustawiamy lewego syna
if l > 0 then
vp[i]^.left := vp[l]
else
vp[i]^.left := nil;
// Ustawiamy prawego syna
if r > 0 then
vp[i]^.right := vp[r]
else
vp[i]^.right := nil;
end;
// Zapamiętujemy korzeń
read_bst := vp[0];
// Usuwamy tablicę dynamiczną
SetLength(vp, 0);
end;
// Funkcja szuka w drzewie BST
// węzła o zadanym kluczu.
// Jeśli go znajdzie, zwraca jego
// wskazanie. Jeżeli nie, to zwraca
// wskazanie puste.
// Parametrami są:
// p-wskazanie korzenia drzewa BST
// k-klucz poszukiwanego węzła
//---------------------------------
function find_bst(p : PBSTnode;
k : integer)
: PBSTnode;
begin
while(p <> nil) and
(p^.key <> k) do
if k < p^.key then
p := p^.left
else
p := p^.right;
find_bst := p;
end;
// Funkcja zwraca wskazanie węzła
// o najmniejszym kluczu. Parametrem
// jest wskazanie korzenia drzewa BST
//-----------------------------------
function min_bst(p : PBSTnode)
: PBSTnode;
begin
if p <> nil then
while p^.left <> nil do
p := p^.left;
min_bst := p;
end;
// Funkcja zwraca wskazanie węzła
// o największym kluczu. Parametrem
// jest wskazanie korzenia drzewa BST
//-----------------------------------
function max_bst(p : PBSTnode)
: PBSTnode;
begin
if p <> nil then
while p^.right <> nil do
p := p^.right;
max_bst := p;
end;
// Procedura DFS:postorder
// usuwająca drzewo
//------------------------
procedure dfs_release(v : PBSTnode);
begin
if v <> nil then
begin
// usuwamy lewe poddrzewo
dfs_release(v^.left);
// usuwamy prawe poddrzewo
dfs_release (v^.right);
// usuwamy sam węzeł
dispose(v);
end;
end;
// **********************
// *** PROGRAM GŁÓWNY ***
// **********************
var
root, p : PBSTnode;
k, mink, maxk : integer;
begin
// Odczytujemy drzewo BST
root := read_bst;
if root <> nil then
begin
// Odczytujemy klucz minimalny
mink := min_bst(root)^.key;
// Odczytujemy klucz maksymalny
maxk := max_bst(root)^.key;
// Przechodzimy przez kolejne
// wartości kluczy
for k := mink to maxk do
begin
// szukamy węzła o kluczu k
p := find_bst(root, k);
write('KEY = ', k:3, ' : ');
if p <> nil then
begin
if(p^.left = nil) and
(p^.right = nil) then
writeln('LEAF')
else
writeln('INNER NODE');
end
else writeln('NONE');
end;
end
else writeln('BST is empty!!!');
// usuwamy drzewo z pamięci
dfs_release(root);
end.
|
// Wyszukiwanie w drzewie BST
// Data: 24.04.2013
// (C)2013 mgr Jerzy Wałaszek
//------------------------------
#include <iostream>
#include <iomanip>
using namespace std;
// Typ węzłów drzewa BST
struct BSTnode
{
BSTnode * left;
BSTnode * right;
int key;
};
// Funkcja wczytuje drzewo BST
// ze standardowego wejścia
// i zwraca wskazanie korzenia
//----------------------------
BSTnode * read_bst()
{
// Tablica wskazań węzłów
BSTnode ** vp;
int key, l, r, i, n;
// Odczytujemy liczbę węzłów drzewa
cin >> n;
// Tworzymy dynamiczną tablicę
// wskazań węzłów
vp = new BSTnode * [n];
// Tablicę dynamiczną wypełniamy
// wskazaniami węzłów, które również
// tworzymy dynamicznie
for(i = 0; i < n; i++)
vp[i] = new BSTnode;
// Teraz wczytujemy definicję drzewa
// i tworzymy jego strukturę w pamięci
// wypełniając odpowiednie pola węzłów.
for(i = 0; i < n; i++)
{
cin >> key >> l >> r;
// Ustawiamy klucz
vp[i]->key = key;
// Ustawiamy lewego syna
vp[i]->left = l ? vp[l] : NULL;
// Ustawiamy prawego syna
vp[i]->right = r ? vp[r] : NULL;
}
// Zapamiętujemy korzeń
BSTnode * p = vp[0];
// Usuwamy tablicę dynamiczną
delete [] vp;
return p;
}
// Funkcja szuka w drzewie BST węzła
// o zadanym kluczu. Jeśli go znajdzie,
// zwraca jego wskazanie. Jeżeli nie,
// to zwraca wskazanie puste.
// Parametrami są:
// p-wskazanie korzenia drzewa BST
// k-klucz poszukiwanego węzła
//-------------------------------------
BSTnode * find_bst(BSTnode * p, int k)
{
while(p && p->key != k)
p = (k < p->key) ? p->left: p->right;
return p;
}
// Funkcja zwraca wskazanie węzła
// o najmniejszym kluczu.
// Parametrem jest wskazanie korzenia
// drzewa BST.
//-----------------------------------
BSTnode * min_bst(BSTnode * p)
{
if(p)
while(p->left)
p = p->left;
return p;
}
// Funkcja zwraca wskazanie węzła
// o największym kluczu. Parametrem
// jest wskazanie korzenia drzewa BST
//-----------------------------------
BSTnode * max_bst(BSTnode * p)
{
if(p)
while(p->right)
p = p->right;
return p;
}
// Procedura DFS:postorder
// usuwająca drzewo
//------------------------
void dfs_release(BSTnode * v)
{
if(v)
{
// usuwamy lewe poddrzewo
dfs_release(v->left);
// usuwamy prawe poddrzewo
dfs_release(v->right);
// usuwamy sam węzeł
delete v;
}
}
// **********************
// *** PROGRAM GŁÓWNY ***
// **********************
int main()
{
BSTnode * root, * p;
int k, mink, maxk;
// Odczytujemy drzewo BST
root = read_bst();
if(root)
{
// Odczytujemy klucz minimalny
mink = min_bst(root)->key;
// Odczytujemy klucz maksymalny
maxk = max_bst(root)->key;
// Przechodzimy przez kolejne
// wartości kluczy
for(k = mink; k <= maxk; k++)
{
// szukamy węzła o kluczu k
p = find_bst(root, k);
cout << "KEY = " << setw(3)
<< k << ": ";
if(p)
{
if(!p->left && !p->right)
cout << "LEAF";
else
cout << "INNER NODE";
}
else cout << "NONE";
cout << endl;
}
}
else
cout << "BST is empty!!!" << endl;
// usuwamy drzewo z pamięci
dfs_release(root);
return 0;
}
|
Basic' Wyszukiwanie w drzewie BST
' Data: 24.04.2013
' (C)2013 mgr Jerzy Wałaszek
'---------------------------
' Typ węzłów drzewa BST
Type BSTnode
left As BSTnode Ptr
right As BSTnode Ptr
key As Integer
End Type
' Funkcja wczytuje drzewo BST
' ze standardowego wejścia
' i zwraca wskazanie korzenia
'----------------------------
Function read_bst() As BSTnode Ptr
' Tablica wskazań węzłów
Dim As BSTnode Ptr Ptr vp
Dim As Integer key, l, r, i, n
Open Cons For Input As #1
' Odczytujemy liczbę
' węzłów drzewa
Input #1, n
' Tworzymy dynamiczną tablicę
' wskazań węzłów
vp = new BSTnode Ptr [n]
' Tablicę dynamiczną wypełniamy
' wskazaniami węzłów, które
' również tworzymy dynamicznie
For i = 0 To n-1
vp[i] = new BSTnode
Next
' Teraz wczytujemy definicję
' drzewa i tworzymy jego strukturę
' w pamięci wypełniając
' odpowiednie pola węzłów.
For i = 0 To n-1
' Czytamy klucz, numer lewego
' i prawego syna
Input #1, key, l, r
' Ustawiamy klucz
vp[i]->key = key
' Ustawiamy lewego syna
If l > 0 Then
vp[i]->left = vp[l]
Else
vp[i]->left = 0
End If
' Ustawiamy prawego syna
If r > 0 Then
vp[i]->right = vp[r]
Else
vp[i]->right = 0
End If
Next
Close #1
' Zapamiętujemy korzeń
read_bst = vp [0]
' Usuwamy tablicę dynamiczną
delete [] vp
End Function
' Funkcja szuka w drzewie BST
' węzła o zadanym kluczu. Jeśli go
' znajdzie, zwraca jego wskazanie.
' Jeżeli nie, to zwraca wskazanie
' puste.
' Parametrami są:
' p-wskazanie korzenia drzewa BST
' k-klucz poszukiwanego węzła
'--------------------------------
Function find_bst(p As BSTnode Ptr, _
k As Integer) _
As BSTnode Ptr
while(p <> 0) AndAlso _
(p->key <> k)
If k < p->key Then
p = p->Left
Else
p = p->Right
End If
Wend
Return p
End Function
' Funkcja zwraca wskazanie węzła
' o najmniejszym kluczu. Parametrem
' jest wskazanie korzenia drzewa BST
'-----------------------------------
Function min_bst(p As BSTnode Ptr) _
As BSTnode Ptr
If p Then
While p->Left
p = p->Left
Wend
End If
Return p
End Function
' Funkcja zwraca wskazanie węzła
' o największym kluczu. Parametrem
' jest wskazanie korzenia drzewa BST
'-----------------------------------
Function max_bst(p As BSTnode Ptr) _
As BSTnode Ptr
If p Then
While p->Right
p = p->Right
Wend
End If
Return p
End Function
' Procedura DFS:postorder
' usuwająca drzewo
'------------------------
Sub dfs_release(v As BSTnode Ptr)
If v Then
' usuwamy lewe poddrzewo
dfs_release(v->left)
' usuwamy prawe poddrzewo
dfs_release(v->right)
' usuwamy sam węzeł
delete v
End If
End Sub
' **********************
' *** PROGRAM GŁÓWNY ***
' **********************
Dim As BSTnode Ptr root, p
Dim As Integer k, mink, maxk
' Odczytujemy drzewo BST
root = read_bst()
If root Then
' Odczytujemy klucz minimalny
mink = min_bst(root)->key
' Odczytujemy klucz maksymalny
maxk = max_bst(root)->key
' Przechodzimy przez kolejne
' wartości kluczy
For k = mink To maxk
' szukamy węzła o kluczu k
p = find_bst(root, k)
Print Using "KEY = ### : ";k;
If p Then
if(p->Left = 0) AndAlso _
(p->Right = 0) Then
Print "LEAF"
Else
Print "INNER NODE"
End If
Else
Print "NONE"
End If
Next
Else
Print "BST is empty!!!"
End If
' usuwamy drzewo z pamięci
dfs_release(root)
End
|
| Python (dodatek) |
# Wyszukiwanie w drzewie BST
# Data: 12.07.2024
# (C)2024 mgr Jerzy Wałaszek
# ---------------------------
# klasa węzłów drzewa BST
class BSTnode:
def __init__(self):
self.left = None
self.right = None
self.key = 0
# Funkcja wczytuje drzewo BST
# ze standardowego wejścia
# i zwraca wskazanie korzenia
def read_bst():
# Tablica wskazań węzłów
vp = []
# Odczytujemy liczbę
# węzłów drzewa
n = int(input())
# Tworzymy dynamiczną tablicę
# wskazań węzłów
for i in range(n):
vp.append(BSTnode())
# Teraz wczytujemy definicję
# drzewa i tworzymy jego strukturę
# w pamięci wypełniając
# odpowiednie pola węzłów.
for i in range(n):
# Czytamy klucz, numer lewego
# i prawego syna węzła
arr = input().split()
k = int(arr[0])
l = int(arr[1])
r = int(arr[2])
# Ustawiamy klucz
vp[i].key = k
# Ustawiamy lewego syna
if l:
vp[i].left = vp[l]
else:
vp[i].left = None
# Ustawiamy prawego syna
if r:
vp[i].right = vp[r]
else:
vp[i].right = None
# Zapamiętujemy korzeń
r = vp[0]
return r
# Funkcja szuka w drzewie BST
# węzła o zadanym kluczu. Jeśli go
# znajdzie, zwraca jego wskazanie.
# Jeżeli nie, to zwraca wskazanie
# puste.
# Parametrami są:
# R - korzeń drzewa BST
# k - klucz poszukiwanego węzła
def find_bst(r, k):
while r and (r.key != k):
if k < r.key:
r = r.left
else:
r = r.right
return r
# Funkcja zwraca wskazanie węzła
# o najmniejszym kluczu.
# R - korzeń
def min_bst(r):
if r:
while r.left:
r = r.left
return r
# Funkcja zwraca wskazanie węzła
# o największym kluczu.
# R - korzeń
def max_bst(r):
if r:
while r.right:
r = r.right
return r
# Procedura DFS:postorder
# usuwająca drzewo
def dfs_release(v):
if v:
# usuwamy lewe poddrzewo
dfs_release(v.left)
# usuwamy prawe poddrzewo
dfs_release(v.right)
# usuwamy odwołania
v.left = None
v.right = None
# **********************
# *** PROGRAM GŁÓWNY ***
# **********************
# Odczytujemy drzewo BST
root = read_bst()
if root:
# Odczytujemy klucz minimalny
mink = min_bst(root).key
# Odczytujemy klucz maksymalny
maxk = max_bst(root).key
# Przechodzimy przez kolejne
# wartości kluczy
for k in range(mink, maxk + 1):
# szukamy węzła o kluczu k
p = find_bst(root, k)
print("KEY = %3d : " % k, end="")
if p:
if (not p.left) and (not p.right):
print("LEAF")
else:
print("INNER NODE")
else:
print("NONE")
else:
print("BST is empty!!!")
# usuwamy drzewo z pamięci
dfs_release(root)
|
| Wynik: |
12 9 1 2 5 3 4 15 5 6 4 7 0 7 8 9 10 0 10 18 0 11 1 0 0 6 0 0 8 0 0 12 0 0 19 0 0 KEY = 1 : LEAF KEY = 2 : NONE KEY = 3 : NONE KEY = 4 : INNER NODE KEY = 5 : INNER NODE KEY = 6 : LEAF KEY = 7 : INNER NODE KEY = 8 : LEAF KEY = 9 : INNER NODE KEY = 10 : INNER NODE KEY = 11 : NONE KEY = 12 : LEAF KEY = 13 : NONE KEY = 14 : NONE KEY = 15 : INNER NODE KEY = 16 : NONE KEY = 17 : NONE KEY = 18 : INNER NODE KEY = 19 : LEAF |
Na początku rozdziału powiedzieliśmy, że kolejność węzłów w drzewie BST jest taka, iż w wyniku przejścia tego drzewa algorytmem in-order otrzymamy niemalejący ciąg kluczy. Przyjrzyjmy się dokładniej temu przejściu:

Zauważ, że znalezienie następnika wcale nie wymaga porównywania węzłów. Mogą wystąpić trzy przypadki:
![]() |
Przypadek 1: Węzeł x posiada prawego syna – następnikiem jest wtedy węzeł o minimalnym kluczu w poddrzewie, którego korzeniem jest prawy syn. Wykorzystujemy tutaj algorytm wyszukiwania węzła o najmniejszym kluczu w prawym poddrzewie. |
![]() |
Przypadek 2: Węzeł x nie posiada prawego syna. W takim przypadku, idąc w górę drzewa, musimy znaleźć pierwszego ojca, dla którego nasz węzeł leży w lewym poddrzewie. Tutaj również nie musimy porównywać węzłów. Po prostu idziemy w górę drzewa i w węźle nadrzędnym sprawdzamy, czy przyszliśmy od strony lewego syna. Jeśli tak, to węzeł ten jest następnikiem. Jeśli nie, to kontynuujemy marsz w górę drzewa. Wymaga to zapamiętywania adresów kolejno mijanych węzłów. |
![]() |
Przypadek 3: Węzeł x nie posiada prawego syna. Idąc w górę drzewa, dochodzimy do korzenia, a następnie do adresu nil, który wskazuje pole up korzenia drzewa BST. W takim przypadku węzeł x jest węzłem o największym kluczu i nie posiada następnika. |
Ponieważ będziemy musieli poruszać się w górę drzewa, węzły muszą posiadać pole up prowadzące do ojca.
K01: Jeśli p = nil, ; jeśli drzewo jest puste, to zakończ z wynikiem p ; kończymy K02: Jeśli p→right ≠ nil, ; Przypadek 1 to zakończ z wynikiem min_bst(p→right) K03: r ← p→up ; r wskazuje ojca p K04: Dopóki (r ≠ nil)(p = r→right), wykonuj kroki K05…K06 ; Przypadki 2 i 3 K05: p ← r ; przemieszczamy się w górę drzewa, ; aż trafimy na węzeł, K06: r ← r→up ; dla którego p leży w lewej gałęzi K07: Zakończ z wynikiem r ; zwracamy znaleziony węzeł ; lub nil, jeśli następnika nie ma
Algorytm znajdowania poprzednika jest lustrzanym odbiciem algorytmu znajdowania następnika (dlaczego?):
K01: Jeśli p = nil, ; jeśli drzewo jest puste, kończymy to zakończ z wynikiem p K02: Jeśli p→left ≠ nil, ; Przypadek 1 to zakończ z wynikiem max_bst(p→left) K03: r ← p→up ; r wskazuje ojca p K04: Dopóki (r ≠ nil)(p = r→left), ; Przypadki 2 i 3 wykonuj kroki K05…K06 K05: p ← r ; przemieszczamy się w górę drzewa, ; aż trafimy na węzeł, K06: r ← r→up ; dla którego p leży w prawej gałęzi K07: Zakończ z wynikiem r ; zwracamy znaleziony węzeł ; lub nil, jeśli poprzednika nie ma
|
Uwaga: Zanim uruchomisz program, przeczytaj wstęp do tego artykułu, w którym wyjaśniamy funkcje tych programów oraz sposób korzystania z nich. |
| Program wczytuje definicję drzewa
binarnego, którego klucze są liczbami całkowitymi. Dane dla drzewa
wyglądają następująco: Pierwsza liczba n określa – ilość węzłów w drzewie. Kolejne n wierszy zawiera po cztery liczby: klucz, numer ojca (dla korzenia wartość 0), numer lewego syna, numer prawego syna. Program wyznacza kolejne następniki i poprzedniki korzenia. |
|
Dane przykładowe (przekopiuj do
schowka i wklej do okna konsoli):
|
Pascal// Następnik i poprzednik w drzewie BST
// Data: 27.04.2013
// (C)2013 mgr Jerzy Wałaszek
//-------------------------------------
program sp_bst;
// Typ węzłów drzewa BST
type
PBSTnode = ^BSTnode;
BSTnode = record
up : PBSTnode;
left : PBSTnode;
right : PBSTnode;
key : integer;
end;
// Funkcja wczytuje drzewo BST ze
// standardowego wejścia i zwraca
// wskazanie korzenia.
//-------------------------------
function read_bst : PBSTnode;
var
// Tablica wskazań węzłów
vp : array of PBSTnode;
key, u, l, r, i, n : integer;
begin
// Odczytujemy liczbę węzłów drzewa
readln(n);
// Tworzymy dynamiczną tablicę
// wskazań węzłów
SetLength(vp, n);
// Tablicę dynamiczną wypełniamy
// wskazaniami węzłów, które również
// tworzymy dynamicznie
for i := 0 to n-1 do new(vp[i]);
// Teraz wczytujemy definicję drzewa
// i tworzymy jego strukturę w pamięci
// wypełniając odpowiednie pola węzłów.
for i := 0 to n-1 do
begin
// Czytamy klucz, numery ojca,
// lewego i prawego syna
readln(key, u, l, r);
// Ustawiamy klucz
vp[i]^.key := key;
// Ustawiamy ojca
vp[i]^.up := vp[u];
// Ustawiamy lewego syna
if l > 0 then
vp[i]^.left := vp[l]
else
vp[i]^.left := nil;
// Ustawiamy prawego syna
if r > 0 then
vp[i]^.right := vp[r]
else
vp[i]^.right := nil;
end;
// Korzeń nie posiada ojca
vp[0]^.up := nil;
// Zapamiętujemy korzeń
read_bst := vp[0];
// Usuwamy tablicę dynamiczną
SetLength(vp, 0);
end;
// Funkcja zwraca wskazanie węzła
// o najmniejszym kluczu. Parametrem
// jest wskazanie korzenia drzewa BST
//-----------------------------------
function min_bst(p : PBSTnode)
: PBSTnode;
begin
if p <> nil then
while p^.left <> nil do
p := p^.left;
min_bst := p;
end;
// Funkcja zwraca wskazanie węzła
// o największym kluczu. Parametrem
// jest wskazanie korzenia drzewa BST
//-----------------------------------
function max_bst(p : PBSTnode)
: PBSTnode;
begin
if p <> nil then
while p^.right <> nil do
p := p^.right;
max_bst := p;
end;
// Funkcja znajduje następnik węzła p
//-----------------------------------
function succ_bst(p : PBSTnode)
: PBSTnode;
var
r : PBSTnode;
begin
succ_bst := nil;
if p <> nil then
begin
if p^.right <> nil then
succ_bst := min_bst(p^.right)
else
begin
r := p^.up;
while (r <> nil) and
(p = r^.right) do
begin
p := r;
r := r^.up;
end;
succ_bst := r;
end;
end;
end;
// Funkcja znajduje poprzednik węzła p
//------------------------------------
function pred_bst(p : PBSTnode)
: PBSTnode;
var
r : PBSTnode;
begin
predBST := nil;
if p <> nil then
begin
if p^.left <> nil then
predBST := max_bst(p^.left)
else
begin
r := p^.up;
while (r <> nil) and
(p = r^.left) do
begin
p := r;
r := r^.up;
end;
predBST := r;
end;
end;
end;
// Procedura DFS:postorder usuwająca drzewo
//-----------------------------------------
procedure dfs_release(v : PBSTnode);
begin
if v <> nil then
begin
// usuwamy lewe poddrzewo
dfs_release(v^.left);
// usuwamy prawe poddrzewo
dfs_release(v^.right);
// usuwamy sam węzeł
dispose(v);
end;
end;
// **********************
// *** PROGRAM GŁÓWNY ***
// **********************
var
root, p : PBSTnode;
begin
// Odczytujemy drzewo BST
root := read_bst;
if root <> nil then
begin
write('SUCCESORS :');
p := root;
while p <> nil do
begin
write(p^.key:3);
p := succ_bst(p);
end;
writeln;
write ('PREDECCESORS :');
p := root;
while p <> nil do
begin
write(p^.key:3);
p := pred_bst(p);
end;
writeln;
end
else writeln('BST is empty!!!');
// usuwamy drzewo z pamięci
dfs_release(root);
end.
|
// Następnik i poprzednik w drzewie BST
// Data: 27.04.2013
// (C)2013 mgr Jerzy Wałaszek
//-------------------------------------
#include <iostream>
#include <iomanip>
using namespace std;
// Typ węzłów drzewa BST
struct BSTnode
{
BSTnode *up, *left, *right;
int key;
};
// Funkcja wczytuje drzewo BST
// ze standardowego wejścia
// i zwraca wskazanie korzenia
//----------------------------
BSTnode * read_bst()
{
// Tablica wskazań węzłów
BSTnode ** vp;
int key, u, l, r, i, n;
// Odczytujemy liczbę węzłów drzewa
cin >> n;
// Tworzymy dynamiczną tablicę
// wskazań węzłów
vp = new BSTnode * [n];
// Tablicę dynamiczną wypełniamy
// wskazaniami węzłów, które również
// tworzymy dynamicznie
for(i = 0; i < n; i++)
vp[i] = new BSTnode;
// Teraz wczytujemy definicję drzewa
// i tworzymy jego strukturę w pamięci
// wypełniając odpowiednie pola węzłów.
for(i = 0; i < n; i++)
{
// Czytamy klucz, numery ojca,
// lewego i prawego syna
cin >> key >> u >> l >> r;
// Ustawiamy klucz
vp[i]->key = key;
// Ustawiamy ojca
vp[i]->up = vp[u];
// Ustawiamy lewego syna
vp[i]->left = l ? vp[l] : NULL;
// Ustawiamy prawego syna
vp[i]->right = r ? vp[r] : NULL;
}
// Korzeń nie posiada ojca
vp[0]->up = NULL;
// Zapamiętujemy korzeń
BSTnode * p = vp[0];
// Usuwamy tablicę dynamiczną
delete [] vp;
return p;
}
// Funkcja zwraca wskazanie węzła
// o najmniejszym kluczu. Parametrem
// jest wskazanie korzenia drzewa BST
//-----------------------------------
BSTnode * min_bst(BSTnode * p)
{
if(p)
while(p->left)
p = p->left;
return p;
}
// Funkcja zwraca wskazanie węzła
// o największym kluczu. Parametrem
// jest wskazanie korzenia drzewa BST
//-----------------------------------
BSTnode * max_bst(BSTnode * p)
{
if(p)
while(p->right)
p = p->right;
return p;
}
// Funkcja znajduje następnik węzła p
//-----------------------------------
BSTnode * succ_bst(BSTnode * p)
{
BSTnode * r;
if(p)
{
if(p->right)
return min_bst(p->right);
else
{
r = p->up;
while(r && (p == r->right))
{
p = r;
r = r->up;
}
return r;
}
}
return p;
}
// Funkcja znajduje poprzednik węzła p
//------------------------------------
BSTnode * pred_bst(BSTnode * p)
{
BSTnode * r;
if(p)
{
if(p->left)
return max_bst(p->left);
else
{
r = p->up;
while(r && (p == r->left))
{
p = r;
r = r->up;
}
return r;
}
}
return p;
}
// Procedura DFS:postorder
// usuwająca drzewo
//------------------------
void dfs_release(BSTnode * v)
{
if(v)
{
// usuwamy lewe poddrzewo
dfs_release(v->left);
// usuwamy prawe poddrzewo
dfs_release(v->right);
// usuwamy sam węzeł
delete v;
}
}
// **********************
// *** PROGRAM GŁÓWNY ***
// **********************
int main()
{
BSTnode *root, *p;
// Odczytujemy drzewo BST
root = read_bst();
if(root)
{
cout << "SUCCESORS :";
for(p = root; p; p = succ_bst(p))
cout << setw(3) << p->key;
cout << endl << "PREDECCESORS :";
for(p = root; p; p = pred_bst(p))
cout << setw (3) << p->key;
cout << endl;
}
else
cout << "BST is empty!!!" << endl;
// usuwamy drzewo z pamięci
dfs_release(root);
return 0;
}
|
Basic' Następnik i poprzednik w drzewie BST
' Data: 27.04.2013
' (C)2013 mgr Jerzy Wałaszek
'-------------------------------------
' Typ węzłów drzewa BST
Type BSTnode
up As BSTnode Ptr
left As BSTnode Ptr
right As BSTnode Ptr
key As Integer
End Type
' Funkcja wczytuje drzewo BST
' ze standardowego wejścia
' i zwraca wskazanie korzenia
'----------------------------
Function read_bst() As BSTnode Ptr
' Tablica wskazań węzłów
Dim As BSTnode Ptr Ptr vp
Dim As Integer key, u, l, r, i, n
Open Cons For Input As #1
' Odczytujemy liczbę węzłów drzewa
Input #1, n
' Tworzymy dynamiczną tablicę
' wskazań węzłów
vp = new BSTnode Ptr [n]
' Tablicę dynamiczną wypełniamy
' wskazaniami węzłów, które również
' tworzymy dynamicznie
For i = 0 To n-1
vp[i] = new BSTnode
Next
' Teraz wczytujemy definicję drzewa
' i tworzymy jego strukturę w pamięci
' wypełniając odpowiednie pola węzłów.
For i = 0 To n-1
' Czytamy klucz, numery ojca,
' lewego i prawego syna
Input #1, key, u, l, r
' Ustawiamy klucz
vp[i]->key = key
' Ustawiamy ojca
vp[i]->up = vp[u]
' Ustawiamy lewego syna
If l > 0 Then
vp[i]->left = vp[l]
Else
vp[i]->left = 0
End If
' Ustawiamy prawego syna
If r > 0 Then
vp[i]->right = vp[r]
Else
vp[i]->right = 0
End If
Next
Close #1
' Korzeń nie posiada ojca
vp[0]->up = 0
' Zapamiętujemy korzeń
read_bst = vp[0]
' Usuwamy tablicę dynamiczną
delete [] vp
End Function
' Funkcja zwraca wskazanie węzła
' o najmniejszym kluczu. Parametrem
' jest wskazanie korzenia drzewa BST
'-----------------------------------
Function min_bst(p As BSTnode Ptr) _
As BSTnode Ptr
If p Then
While p->Left
p = p->Left
Wend
End If
Return p
End Function
' Funkcja zwraca wskazanie węzła
' o największym kluczu. Parametrem
' jest wskazanie korzenia drzewa BST
'-----------------------------------
Function max_bst(p As BSTnode Ptr) _
As BSTnode Ptr
If p Then
While p->Right
p = p->Right
Wend
End If
Return p
End Function
' Funkcja znajduje następnik węzła p
'-----------------------------------
Function succ_bst(ByVal p As BSTnode Ptr) _
As BSTnode Ptr
Dim As BSTnode Ptr r
If p Then
If p->Right Then
Return min_bst(p->right)
Else
r = p->up
while (r <> 0) AndAlso _
(p = r->right)
p = r
r = r->up
Wend
Return r
End If
End If
Return p
End Function
' Funkcja znajduje poprzednik węzła p
'------------------------------------
Function pred_bst(ByVal p As BSTnode Ptr) _
As BSTnode Ptr
Dim As BSTnode Ptr r
If p Then
If p->Left Then
Return max_bst(p->Left)
Else
r = p->up
while(r <> 0) AndAlso _
(p = r->Left)
p = r
r = r->up
Wend
Return r
End If
End If
Return p
End Function
' Procedura DFS:postorder usuwająca drzewo
'-----------------------------------------
Sub dfs_release (v As BSTnode Ptr)
If v Then
' usuwamy lewe poddrzewo
dfs_release(v->left)
' usuwamy prawe poddrzewo
dfs_release(v->right)
' usuwamy sam węzeł
delete v
End If
End Sub
' **********************
' *** PROGRAM GŁÓWNY ***
' **********************
Dim As BSTnode Ptr root, p
' Odczytujemy drzewo BST
root = read_bst()
If root Then
Print "SUCCESORS :";
p = root
While p
Print Using "###";p->key;
p = succ_bst(p)
Wend
Print
Print "PREDECCESORS :";
p = root
While p
Print Using "###";p->key;
p = pred_bst(p)
Wend
Print
Else
Print "BST is empty!!!"
End If
' usuwamy drzewo z pamięci
dfs_release(root)
End
|
| Python (dodatek) |
# Następnik i poprzednik w drzewie BST
# Data: 13.07.2024
# (C)2024 mgr Jerzy Wałaszek
#-------------------------------------
# klasa węzłów drzewa BST
class BSTnode:
def __init__(self, k):
self.up = None
self.left = None
self.right = None
self.key = k
# Funkcja wczytuje drzewo BST
# ze standardowego wejścia
# i zwraca wskazanie korzenia
def read_bst():
# Tablica wskazań węzłów
vp = []
# Odczytujemy liczbę
# węzłów drzewa
n = int(input())
# Tworzymy dynamiczną tablicę
# wskazań węzłów
for i in range(n):
vp.append(BSTnode(0))
# Teraz wczytujemy definicję
# drzewa i tworzymy jego strukturę
# w pamięci wypełniając
# odpowiednie pola węzłów.
for i in range(n):
# Czytamy klucz, numer lewego
# i prawego syna węzła
arr = input().split()
k = int(arr[0])
u = int(arr[1])
l = int(arr[2])
r = int(arr[3])
# Ustawiamy klucz
vp[i].key = k
# Ustawiamy ojca
vp[i].up = vp[u]
# Ustawiamy lewego syna
if l:
vp[i].left = vp[l]
else:
vp[i].left = None
# Ustawiamy prawego syna
if r:
vp[i].right = vp[r]
else:
vp[i].right = None
# Korzeń nie posiada ojca
vp[0].up = None
# Zapamiętujemy korzeń
r = vp[0]
return r
# Funkcja zwraca wskazanie węzła
# o najmniejszym kluczu.
# r - korzeń
def min_bst(r):
if r:
while r.left:
r = r.left
return r
# Funkcja zwraca wskazanie węzła
# o największym kluczu.
# r - korzeń
def max_bst(r):
if r:
while r.right:
r = r.right
return r
# Funkcja znajduje następnik węzła p
#-----------------------------------
def succ_bst(p):
if p:
if p.right:
return min_bst(p.right)
else:
r = p.up
while r and (p is r.right):
p = r
r = r.up
return r
return p
# Funkcja znajduje poprzednik węzła p
#------------------------------------
def pred_bst(p):
if p:
if p.left:
return max_bst(p.left)
else:
r = p.up
while r and (p is r.left):
p = r
r = r.up
return r
return p
# Procedura DFS:postorder
# usuwająca drzewo
#------------------------
def dfs_release(v):
if v:
# usuwamy lewe poddrzewo
dfs_release(v.left)
# usuwamy prawe poddrzewo
dfs_release(v.right)
# usuwamy odwołania
v.left = None
v.right = None
# **********************
# *** PROGRAM GŁÓWNY ***
# **********************
# Odczytujemy drzewo BST
root = read_bst()
if root:
print("SUCCESORS :", end="")
p = root
while p:
print("%3d" % p.key, end="")
p = succ_bst(p)
print()
print("PREDECCESORS :", end="")
p = root
while p:
print("%3d" % p.key, end="")
p = pred_bst(p)
print()
else:
print("BST is empty!!!")
# usuwamy drzewo z pamięci
dfs_release(root)
|
| Wynik: |
12 9 0 1 2 5 0 3 4 15 0 5 6 4 1 7 0 7 1 8 9 10 2 0 10 18 2 0 11 1 3 0 0 6 4 0 0 8 4 0 0 12 5 0 0 19 6 0 0 SUCCESORS : 9 10 12 15 18 19 PREDECCESORS : 9 8 7 6 5 4 1 |
![]() |
Zespół Przedmiotowy Chemii-Fizyki-Informatyki w I Liceum Ogólnokształcącym im. Kazimierza Brodzińskiego w Tarnowie ul. Piłsudskiego 4 ©2026 mgr Jerzy Wałaszek |
Materiały tylko do użytku dydaktycznego. Ich kopiowanie i powielanie jest dozwolone pod warunkiem podania źródła oraz niepobierania za to pieniędzy.
Pytania proszę przesyłać na adres email:
Serwis wykorzystuje pliki cookies. Jeśli nie chcesz ich otrzymywać, zablokuj je w swojej przeglądarce.
Informacje dodatkowe.