|
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
|
W dotychczas omawianych przez nas drzewach nie interesowały nas zależności pomiędzy danymi zawartymi w węzłach, a jedynie struktura samego drzewa. W tym i następnych rozdziałach będziemy omawiać drzewa binarne, których węzły są powiązane ze sobą nie tylko krawędziami, lecz dodatkowymi warunkami. Pierwszą taką strukturą będzie kopiec (ang. heap).
Kopiec binarny (ang. binary heap) jest kompletnym drzewem binarnym, co oznacza, że posada zapełnione wszystkie poziomy za wyjątkiem ostatniego, a ostatni poziom jest zapełniany bez przerw, poczynając od strony lewej do prawej.
![]() |
To drzewo nadaje się na kopiec, ponieważ jest kompletne. Ostatni poziom węzły wypełniają bez przerw od strony lewej do prawej. |
![]() |
To drzewo nie nadaje się na kopiec. Na ostatnim poziomie brakuje pierwszego węzła od lewej strony. |
![]() |
To drzewo również nie nadaje się na kopiec. Na ostatnim poziomie mamy przerwę w ciągu węzłów. |
Oprócz wymogu strukturalnego (drzewo binarne musi być kompletne) kopiec posiada dodatkowy warunek: żaden z synów węzła nie jest od niego większy, czyli nie przechowuje w swoim polu data wartości większej od zawartości pola data swojego ojca.
![]() |
To jest kopiec, ponieważ drzewo jest drzewem kompletnym, a żaden z synów nie ma wartości większej od swojego ojca. |
![]() |
To nie jest kopiec, ponieważ zaznaczone na czerwono węzły nie spełniają warunku kopca. Przechowują wartości większe od wartości przechowywanych w ich ojcach. |
Ponieważ kopiec jest drzewem kompletnym, to daje się łatwo zrealizować w tablicy:

Zwróć uwagę, że w tablicy odkładamy kolejne poziomy drzewa. Na poziomie 0 mamy tylko korzeń, czyli
Powiązania pomiędzy węzłami określają proste wzory. Niech n będzie liczbą węzłów w drzewie, a k numerem węzła. Wtedy:
numer lewego syna = 2k+1 numer prawego syna = 2k+2 numer ojca = [(k-1)/2], dla k > 0 lewy syn istnieje, jeśli 2k+1 < n prawy syn istnieje, jeśli 2k+2 < n węzeł k jest liściem, jeśli 2k+2 > n
Wzory te pozwalają poruszać się po strukturze kopca w górę i w dół.
Dla kopca istnieją dwie operacje standardowe: push – wstawianie nowego elementu do kopca oraz pop – usuwanie korzenia kopca. Opisujemy je poniżej.
Dodawany element wstawiamy jako ostatni liść kopca. Następnie sprawdzamy kolejno, czy jest on mniejszy lub równy swojemu ojcu. Jeśli nie, to zamieniamy wstawiony element z jego ojcem. Operację kontynuujemy, aż znajdziemy ojca większego lub równego elementowi lub dojdziemy do korzenia drzewa. Prześledź poniższą tabelkę:
![]() |
Nowy element wstawiamy jako ostatni liść kopca. Następnie sprawdzamy, czy jest on niewiększy od swojego ojca. Ponieważ warunek kopca nie jest spełniony, wymieniamy ze sobą węzeł wstawiony z jego ojcem. |
![]() |
Na wyższym poziomie znów sprawdzamy warunek kopca – czy syn nie jest większy od ojca. Warunek nie jest wciąż spełniony, zatem wymieniamy ojca ze wstawionym węzłem i przechodzimy na kolejny poziom drzewa. |
![]() |
Tutaj znów warunek kopca nie jest spełniony, wymieniamy zatem ojca ze wstawionym węzłem i przechodzimy na kolejny poziom drzewa. |
![]() |
Tu kończymy, ponieważ doszliśmy do korzenia drzewa, który nie ma już ojca. Element został wstawiony do kopca. |
K01: i ← n ; ustawiamy indeks i na pozycję wstawianego elementu K02: n ← n+1 ; kopiec będzie zawierał o 1 element więcej K03: j ← (i-1) div 2 ; obliczamy indeks ojca K04: Dopóki i > 0T[j] < v, ; sprawdzamy warunek kopca wykonuj kroki K05…K07 K05: T[i] ← T[j] ; umieszczamy ojca na miejscu syna K06: i ← j ; przenosimy się na pozycję ojca K07: j ← (i-1) div 2 ; obliczamy indeks ojca K08: T[i] ← v ; wstawiamy element do kopca K09: Zakończ
Operacja dodawania nowego elementu do kopca posiada klasę złożoności
obliczeniowej
|
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 generuje 15 liczb pseudolosowych z zakresu od 0 do 99. Następnie tworzy kopiec wprowadzając do niego kolejno wygenerowane liczby. Na końcu wyświetla zawartość kopca w postaci drzewa binarnego, wykorzystując zmodyfikowany nieco algorytm z poprzedniego rozdziału. |
Pascal// Tworzenie kopca w tablicy
// Data: 27.02.2013
// (C)2013 mgr Jerzy Wałaszek
//------------------------------
program create_heap;
// Zmienne globalne
var
// łańcuchy do znaków ramek
cr, cl, cp : string;
// kopiec
T : array [0..14] of integer;
// liczba węzłów
n : integer;
// Procedura wypisuje drzewo
//--------------------------
procedure print_bt(sp, sn : string;
v : integer);
var
s : string;
i : integer;
begin
if v < n then
begin
s := sp;
if sn = cr then
s[length(s)-1] := ' ';
print_bt(s+cp, cr, 2*v+2);
s := Copy(sp, 1, length(sp)-2);
for i := 1 to length(s) do
write(char(ord(s[i])));
for i := 1 to length(sn) do
write(char(ord(sn[i])));
writeln(T[v]);
s := sp;
if sn = cl then
s[length(s)-1] := ' ';
print_bt(s+cp, cl, 2*v+1);
end;
end;
// procedura wstawia v do kopca
//-----------------------------
procedure heap_push(v : integer);
var
i, j : integer;
begin
i := n;
inc(n);
j := (i-1) div 2;
while(i > 0) and (T[j] < v) do
begin
T[i] := T[j];
i := j;
j := (i-1) div 2;
end;
T[i] := v;
end;
// **********************
// *** PROGRAM GŁÓWNY ***
// **********************
var
i, v : integer;
begin
// ustawiamy łańcuchy znakowe,
// ponieważ nie wszystkie edytory
// pozwalają wstawiać znaki konsoli
// do tworzenia ramek.
// cr = +--
// |
// cl = |
// +--
// cp = |
// |
cr := #218#196;
cl := #192#196;
cp := #179#32;
randomize;
n := 0;
for i := 1 to 15 do
begin
v := random(100);
write(v, ' ');
heap_push(v);
end;
writeln;
writeln;
print_bt('', '', 0);
end.
|
// Tworzenie kopca w tablicy
// Data: 27.02.2013
// (C)2013 mgr Jerzy Wałaszek
//------------------------------
#include <iostream>
#include <string>
#include <ctime>
#include <cstdlib>
using namespace std;
// Zmienne globalne
// łańcuchy do znaków ramek
string cr, cl, cp;
// tablica na kopiec
int T [15];
// liczba elementów w kopcu
int n = 0;
// Procedura wypisuje drzewo
//--------------------------
void print_bt(string sp,
string sn,
int v)
{
string s;
if(v < n)
{
s = sp;
if(sn == cr)
s[s.length()-2] = ' ';
print_bt(s+cp, cr, 2*v+2);
s = s.substr(0, sp.length()-2);
cout << s << sn << T[v]
<< endl;
s = sp;
if(sn == cl)
s[s.length()-2] = ' ';
print_bt(s+cp, cl, 2*v+1);
}
}
// procedura wstawia v do kopca
//-----------------------------
void heap_push(int v)
{
int i, j;
i = n++;
j = (i-1)/2;
while(i > 0 && T[j] < v)
{
T[i] = T[j];
i = j;
j = (i-1)/2;
}
T[i] = v;
}
// **********************
// *** PROGRAM GŁÓWNY ***
// **********************
int main()
{
int i, v;
srand(time(NULL));
// ustawiamy łańcuchy znakowe,
// ponieważ nie wszystkie edytory
// pozwalają wstawiać znaki konsoli
// do tworzenia ramek.
// cr = +--
// |
// cl = |
// +--
// cp = |
// |
cr = cl = cp = " ";
cr[0] = 218; cr[1] = 196;
cl[0] = 192; cl[1] = 196;
cp[0] = 179;
for(i = 0; i < 15; i++)
{
v = rand() % 100;
cout << v << " ";
heap_push(v);
}
cout << endl << endl;
print_bt("", "", 0);
return 0;
}
|
Basic' Tworzenie kopca w tablicy
' Data: 27.02.2013
' (C)2013 mgr Jerzy Wałaszek
'------------------------------
Dim Shared As Integer T(0 To 14)
Dim Shared As Integer n = 0
Dim Shared As String * 2 crx, clx, cpx
' Procedura wypisuje drzewo
'--------------------------
Sub print_bt(sp As String, _
sn As String, _
v As Integer)
Dim As String s
If v < n Then
s = sp
If sn = crx Then _
Mid(s, Len(s)-1, 1) = " "
print_bt(s+cpx, crx, 2*v+2)
s = Mid(s, 1, Len(sp)-2)
Print Using "&&&";s;sn;T(v)
s = sp
If sn = clx Then _
Mid(s, Len(s)-1, 1) = " "
print_bt(s+cpx, clx, 2*v+1)
End If
End Sub
' procedura wstawia v do kopca
'-----------------------------
Sub heap_push(v As Integer)
Dim As Integer i, j
i = n
n += 1
j = (i-1)\2
While i > 0 AndAlso T(j) < v
T(i) = T(j)
i = j
j = (i-1)\2
Wend
T(i) = v
End Sub
' **********************
' *** PROGRAM GŁÓWNY ***
' **********************
Dim As Integer i, v
Randomize
' ustawiamy łańcuchy znakowe,
' ponieważ nie wszystkie edytory
' pozwalają wstawiać znaki konsoli
' do tworzenia ramek.
' crx = +--
' |
' clx = |
' +--
' cpx = |
' |
crx = Chr(218)+Chr(196)
clx = Chr(192)+Chr(196)
cpx = Chr(179)+" "
For i = 1 To 15
v = Int(Rnd()*100)
print v;
heap_push(v)
Next
Print
Print
print_bt("", "", 0)
End
|
| Python (dodatek) |
# Tworzenie kopca w tablicy
# Data: 09.07.2024
# (C)2024 mgr Jerzy Wałaszek
# ---------------------------
import random
# zmienne globalne
# łańcuchy do znaków ramek
# łańcuchy do ramek
cr = "┌─"
cl = "└─"
cp = "│ "
# tablica na kopiec
t = [0] * 15
# liczba elementów w kopcu
n = 0
# Procedura wypisuje drzewo
# --------------------------
def print_bt(sp, sn, v):
global cr, cl, cp
if v < n:
s = sp
if sn == cr:
s = s[:-2] + ' ' + s[-1]
print_bt(s + cp, cr, 2 * v + 2)
s = s[:-2]
print(s, sn, t[v], sep="")
s = sp
if sn == cl:
s = s[:-2] + ' ' + s[-1]
print_bt(s + cp, cl, 2 * v + 1)
# procedura wstawia v do kopca
# -----------------------------
def heap_push(v):
global t, n
i = n
n += 1
j = (i - 1) // 2
while i and t[j] < v:
t[i] = t[j]
i = j
j = (i - 1) // 2
t[i] = v
# **********************
# *** PROGRAM GŁÓWNY ***
# **********************
for i in range(15):
v = random.randrange(100)
print(v, end=" ")
heap_push(v)
print()
print()
print_bt("", "", 0)
|
| Wynik: |
87 59 40 41 7 40 24 49 29 83 68 94 41 20 62
┌─24
┌─62
│ └─20
┌─87
│ │ ┌─40
│ └─41
│ └─40
94
│ ┌─59
│ ┌─68
│ │ └─7
└─83
│ ┌─29
└─49
└─41
|
Usuwamy korzeń drzewa, wstawiając na jego miejsce ostatni z liści. Następnie idziemy kolejnymi poziomami w dół drzewa, sprawdzając warunek kopca. Jeśli nie jest spełniony, to zamieniamy ojca z największym z synów. Operację kontynuujemy aż do momentu spełnienia warunku kopca lub osiągnięcia liścia. Prześledź poniższą tabelkę:
![]() |
Korzeń drzewa usuwamy, zastępując go przez ostatni liść. |
![]() |
Sprawdzamy warunek kopca. Nie jest spełniony, zatem wymieniamy miejscami ojca z największym synem i przechodzimy na niższy poziom drzewa. |
![]() |
Sprawdzamy warunek kopca. Nie jest spełniony, zatem wymieniamy ojca z największym synem i przechodzimy na niższy poziom drzewa. |
![]() |
Sprawdzamy warunek kopca. Nie jest spełniony, zatem wymieniamy ojca z największym synem i przechodzimy na niższy poziom drzewa. |
![]() |
Ponieważ element stał się liściem i nie ma
synów, kończymy. Kopiec został przywrócony |
Operacja usuwania elementu z kopca ma klasę złożoności obliczeniowej
równą
K01: Jeśli n = 0, ; gdy kopiec jest pusty, to zakończ ; nie ma co usuwać, kończymy K02: n ← n-1 ; kopiec będzie zawierał ; o 1 element mniej K03: v ← T[n] ; w v zapamiętujemy ostatni ; element kopca K04: i ← 0 ; przeszukiwanie drzewa rozpoczynamy ; od korzenia w dół kopca K05: j ← 1 ; j wskazuje lewego syna K06: Dopóki j < n, ; idziemy w dół kopca wykonuj kroki K07…K11 K07: Jeśli (j+1 < n)(T[j+1] > T[j]), ; szukamy to j ← j+1 ; większego syna
K08: Jeśli v ≥ T[j], ; jeśli warunek kopca to idź do kroku K12 ; spełniony, ; to wychodzimy z pętli K09: T[i] ← T[j] ; inaczej kopiujemy większego ; syna do ojca K10: i ← j ; przechodzimy na pozycję większego ; syna K11: j ← 2j+1 ; j wskazuje lewego syna K12: T[i] ← v ; umieszczamy v w kopcu K13: Zakończ
Operacja usuwania elementu z kopca posiada klasę złożoności obliczeniowej
|
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 tworzy kopiec z 200 liczb
pseudolosowych od -99 do 99. Następnie kolejno pobiera elementy ze szczytu kopca, aż kopiec będzie pusty. Pobierane elementy są wyświetlane w oknie konsoli. Zwróć uwagę, że są one uporządkowane
malejąco (ponieważ na szczycie kopca zawsze jest
aktualnie największy element). Własność ta pozwala wykorzystać kopiec do szybkiego
sortowania w czasie
|
Pascal// Usuwanie elementu z kopca
// Data: 5.03.2013
// (C)2013 mgr Jerzy Wałaszek
//---------------------------
program heapsort;
var
// kopiec
T : array [0..199] of integer;
// liczba węzłów w kopcu
n : integer;
// Procedura wstawia v do kopca
//-----------------------------
procedure heap_push(v : integer);
var
i, j : integer;
begin
i := n;
inc(n);
j := (i-1) div 2;
while(i > 0) and (T[j] < v) do
begin
T[i] := T[j];
i := j;
j := (i-1) div 2;
end;
T[i] := v;
end;
// Procedura usuwa korzeń z kopca
//-------------------------------
procedure heap_pop;
var
i, j, v : integer;
begin
if n > 0 then
begin
dec(n);
v := T[n];
i := 0;
j := 1;
while j < n do
begin
if(j+1 < n) and (T[j+1] > T[j]) then
inc(j);
if v >= T[j] then break;
T[i] := T[j];
i := j;
j := 2*j+1;
end;
T[i] := v;
end;
end;
// **********************
// *** PROGRAM GŁÓWNY ***
// **********************
var
i, v : integer;
begin
randomize;
n := 0;
// Tworzymy kopiec
for i := 1 to 200 do
begin
v := random(199)-99;
write(v:4);
heap_push(v);
end;
writeln;
writeln;
// Rozbieramy kopiec
while n > 0 do
begin
write(T[0]:4);
heap_pop;
end;
writeln;
writeln;
end.
|
// Usuwanie elementu z kopca
// Data: 5.03.2013
// (C)2013 mgr Jerzy Wałaszek
//------------------------------
#include <iostream>
#include <iomanip>
#include <ctime>
#include <cstdlib>
using namespace std;
int T[200]; // kopiec
int n = 0; // liczba węzłów
// Procedura wstawia v do kopca
//-----------------------------
void heap_push(int v)
{
int i, j;
i = n++;
j = (i-1) / 2;
while(i > 0 && T[j] < v)
{
T[i] = T[j];
i = j;
j = (i-1)/2;
}
T[i] = v;
}
// Procedura usuwa korzeń z kopca
//------------------------------
void heap_pop()
{
int i, j, v;
if(n--)
{
v = T[n];
i = 0;
j = 1;
while(j < n)
{
if(j+1 < n && T[j+1] > T[j])
j++;
if(v >= T[j]) break;
T[i] = T[j];
i = j;
j = 2*j+1;
}
T[i] = v;
}
}
// **********************
// *** PROGRAM GŁÓWNY ***
// **********************
int main()
{
int i, v;
srand(time(NULL));
// Tworzymy kopiec
for(i = 0; i < 200; i++)
{
v = (rand()%199)-99;
cout << setw(4) << v;
heap_push(v);
}
cout << endl << endl;
// Rozbieramy kopiec
while(n)
{
cout << setw(4) << T[0];
heap_pop();
}
cout << endl << endl;
return 0;
}
|
Basic' Usuwanie elementu z kopca
' Data: 5.03.2013
' (C)2013 mgr Jerzy Wałaszek
'---------------------------
' kopiec
Dim Shared As integer T(0 To 199)
' liczba węzłów
Dim Shared As Integer n = 0
' Procedura wstawia v do kopca
'-----------------------------
Sub heap_push(ByVal v As Integer)
Dim As Integer i, j
i = n
n += 1
j = (i-1)\2
While(i > 0) AndAlso (T(j) < v)
T(i) = T(j)
i = j
j = (i-1)\2
Wend
T(i) = v
End Sub
' Procedura usuwa korzeń z kopca
'------------------------------
Sub heap_pop()
Dim As Integer i, j, v
If n > 0 Then
n -= 1
v = T(n)
i = 0
j = 1
While j < n
if(j+1 < n) AndAlso _
(T(j+1) > T(j)) Then _
j += 1
If v >= T (j) Then _
Exit While
T(i) = T(j)
i = j
j = 2*j+1
Wend
T(i) = v
End If
End Sub
' **********************
' *** PROGRAM GŁÓWNY ***
' **********************
Dim As Integer i, v
Randomize
' Tworzymy kopiec
For i = 1 To 200
v = Int(Rnd()*199)-99
Print Using "####";v;
heap_push(v)
Next
Print
Print
' Rozbieramy kopiec
While n > 0
Print Using "####";T(0);
heap_pop()
Wend
Print
Print
End
|
| Python (dodatek) |
# Usuwanie elementu z kopca
# Data: 10.07.2024
# (C)2024 mgr Jerzy Wałaszek
#---------------------------
import random
# kopiec
t = [0] * 200
# liczba węzłów
n = 0
# Procedura wstawia v do kopca
#-----------------------------
def heap_push(v):
global n, t
i = n
n += 1
j = (i-1)//2
while i and t[j] < v:
t[i] = t[j]
i = j
j = (i-1)//2
t[i] = v
# Procedura usuwa korzeń z kopca
#-------------------------------
def heap_pop():
global n, t
if n:
n -= 1
v = t[n]
i = 0
j = 1
while j < n:
if (j+1 < n) and \
(t[j+1] > t[j]):
j += 1
if v >= t[j]: break
t[i] = t[j]
i = j
j = 2*j+1
t[i] = v
# **********************
# *** PROGRAM GŁÓWNY ***
# **********************
# Tworzymy kopiec
for i in range(200):
v = random.randrange(-99, 100)
print("%4d" % v, end="")
heap_push(v)
print()
print()
# Rozbieramy kopiec
while n:
print("%4d" % t[0], end="")
heap_pop()
print()
print()
|
| Wynik: |
93 32 -5 74 -63 6 -81 -18 -88 -74 57 71 -9 -38 84 15 -48 72 88 -41 -77 -76 92 -68 -51 12 -85 9 86 -12 61 74 -32 96 88 -94 -89 -4 20 -47 -3 6 54 -71 22 63 -58 32 68 -19 43 -48 -62 56 11 17 -14 83 -65 -81 68 7 -66 35 -70 -5 78 85 45 50 -88 60 97 -63 -40 -33 72 86 -79 -45 -91 -28 -75 30 -91 -27 -92 90 94 -70 -1 -79 -39 -87 -40 -22 62 70 -32 -78 98 7 96 -10 -95 -49 53 23 73 55 35 -17 -48 -9 27 -6 -50 80 -95 72 65 -69 23 86 -22 -71 17 -84 -25 7 -77 -26 -89 96 -6 17 -3 -33 38 -55 -61 41 -96 40 88 45 -55 -64 -36 -65 0 -24 29 17 -31 66 76 -16 8 -54 16 -86 30 -7 97 83 -99 25 78 -35 33 58 79 19 -89 -27 48 89 -73 -26 7 -75 -36 -86 -50 20 -68 -21 69 27 -59 80 41 40 29 -77 -38 -3 20 97 98 97 97 97 96 96 96 94 93 92 90 89 88 88 88 86 86 86 85 84 83 83 80 80 79 78 78 76 74 74 73 72 72 72 71 70 69 68 68 66 65 63 62 61 60 58 57 56 55 54 53 50 48 45 45 43 41 41 40 40 38 35 35 33 32 32 30 30 29 29 27 27 25 23 23 22 20 20 20 19 17 17 17 17 16 15 12 11 9 8 7 7 7 7 6 6 0 -1 -3 -3 -3 -4 -5 -5 -6 -6 -7 -9 -9 -10 -12 -14 -16 -17 -18 -19 -21 -22 -22 -24 -25 -26 -26 -27 -27 -28 -31 -32 -32 -33 -33 -35 -36 -36 -38 -38 -39 -40 -40 -41 -45 -47 -48 -48 -48 -49 -50 -50 -51 -54 -55 -55 -58 -59 -61 -62 -63 -63 -64 -65 -65 -66 -68 -68 -69 -70 -70 -71 -71 -73 -74 -75 -75 -76 -77 -77 -77 -78 -79 -79 -81 -81 -84 -85 -86 -86 -87 -88 -88 -89 -89 -89 -91 -91 -92 -94 -95 -95 -96 -99 |
Kopiec szczególnie dobrze nadaje się do realizacji kolejki priorytetowej. Poniżej przedstawiamy prosty przykład programu obiektowego, który tworzy taką kolejkę i wykorzystuje ją. Program jest modyfikacją programu przedstawionego w rozdziale o kolejkach priorytetowych.
Program tworzy obiekt kolejki priorytetowej o rozmiarze 10 elementów. Generuje dziesięć razy liczbę losową od 0 do 99 oraz odpowiadający jej priorytet od 0 do 9. Liczbę z priorytetem umieszcza w kolejce. Następnie pobiera z kolejki kolejne elementy i wyświetla w oknie konsoli. Zwróć uwagę, że liczby zostają z kolejki pobrane zgodnie z malejącą kolejnością ich priorytetów.
Uwaga, program nie sprawdza, czy dane mieszczą się w kolejce.
Pascal// Kolejka priorytetowa z kopcem
// Data: 5.03.2013
// (C)2013 mgr Jerzy Wałaszek
//------------------------------
program heap_queue;
// Definicja typu obiektowego queue
//---------------------------------
type
Qel = record
prio : integer;
Data: integer;
end;
TQel = array of Qel;
Queue = object
private
// kopiec dynamiczny
T : TQel;
// liczba elementów
n : integer;
public
constructor init(max_n : integer);
destructor destroy;
function q_empty : boolean;
function q_front : integer;
function q_frontprio: integer;
procedure push(prio, v : integer);
procedure q_pop;
end;
//----------------------
// Metody obiektu Queue
//----------------------
// Konstruktor-rezerwuje pamięć na kopiec
//---------------------------------------
constructor Queue.init(max_n : integer);
begin
// tworzymy tablicę dynamiczną
SetLength(T, max_n);
n := 0; // kopiec jest pusty
end;
// Destruktor-usuwa tablicę z pamięci
//-----------------------------------
destructor Queue.destroy;
begin
SetLength(T, 0);
end;
// Sprawdza, czy kolejka jest pusta
//---------------------------------
function Queue.q_empty : boolean;
begin
q_empty := (n = 0);
end;
// Zwraca początek kolejki.
// Wartość specjalna to -MAXINT
//-----------------------------
function Queue.q_front : integer;
begin
if n = 0 then q_front := -MAXINT
else q_front := T[0].data;
end;
// Zwraca priorytet pierwszego elementu
//-------------------------------------
function Queue.q_frontprio : integer;
begin
if n = 0 then q_frontprio := -MAXINT
else q_frontprio := T[0].prio;
end;
// Zapisuje do kolejki wg priorytetu
//----------------------------------
procedure Queue.push(prio, v : integer);
var
i, j : integer;
begin
i := n;
inc(n);
j := (i-1) div 2;
while(i > 0) and (T[j].prio < prio) do
begin
T[i] := T[j];
i := j;
j := (i-1) div 2;
end;
T[i].prio := prio;
T[i].Data:= v;
end;
// Usuwa z kolejki
//----------------
procedure Queue.q_pop;
var
i, j, v, p : integer;
begin
if n > 0 then
begin
dec(n);
p := T[n].prio;
v := T[n].data;
i := 0;
j := 1;
while j < n do
begin
if(j+1 < n) and
(T[j+1].prio > T[j].prio) then
inc(j);
if p >= T[j].prio then break;
T[i] := T[j];
i := j;
j := 2*j+1;
end;
T[i].prio := p;
T[i].Data:= v;
end;
end;
//---------------
// Program główny
//---------------
var
// kolejka 10-cio elementowa
Q : Queue;
i, p, v : integer;
begin
Randomize;
Q.init(10);
for i := 1 to 10 do
begin
v := random(100);
p := random(10);
writeln(v:2, ':', p);
Q.push(p, v);
end;
writeln('----');
while not Q.q_empty do
begin
writeln(Q.q_front:2, ':', Q.q_frontprio);
Q.q_pop;
end;
Q.destroy;
end.
|
// Kolejka priorytetowa z kopcem
// Data: 5.03.2013
// (C)2013 mgr Jerzy Wałaszek
//------------------------------
#include <iostream>
#include <iomanip>
#include <ctime>
#include <cstdlib>
using namespace std;
const int MAXINT = -2147483647;
// Definicja typu obiektowego Queue
//----------------------------------
struct Qel
{
int prio, data;
};
class Queue
{
private:
// kopiec dynamiczny
Qel * T;
// liczba elementów
int n;
public:
Queue(int max_n);
~Queue();
bool empty();
int front();
int frontprio();
void push(int prio, int v);
void pop();
};
//----------------------
// Metody obiektu Queue
//----------------------
// Konstruktor-rezerwuje pamięć na kopiec
//---------------------------------------
Queue::Queue(int max_n)
{
// tworzymy tablicę dynamiczną
T = new Qel[max_n];
n = 0; // kopiec jest pusty
}
// Destruktor-usuwa tablicę z pamięci
//-----------------------------------
Queue::~Queue()
{
delete [] T;
}
// Sprawdza, czy kolejka jest pusta
//---------------------------------
bool Queue::empty()
{
return !n;
}
// Zwraca początek kolejki.
// Wartość specjalna to MAXINT
//----------------------------
int Queue::front()
{
return n ? T[0].Data: MAXINT;
}
// Zwraca priorytet pierwszego elementu
//-------------------------------------
int Queue::frontprio()
{
return n ? T[0].prio : MAXINT;
}
// Zapisuje do kolejki wg priorytetu
//----------------------------------
void Queue::push(int prio, int v)
{
int i, j;
i = n++;
j = (i-1)/2;
while(i > 0 && T[j].prio < prio)
{
T[i] = T[j];
i = j;
j = (i-1)/2;
}
T[i].prio = prio;
T[i].data = v;
}
// Usuwa z kolejki
//----------------
void Queue::pop()
{
int i, j, v, p;
if(n--)
{
p = T[n].prio;
v = T[n].data;
i = 0;
j = 1;
while(j < n)
{
if(j+1 < n &&
T[j+1].prio > T[j].prio)
j++;
if(p >= T[j].prio) break;
T[i] = T[j];
i = j;
j = 2*j+1;
}
T[i].prio = p;
T[i].data = v;
}
}
//---------------
// Program główny
//---------------
int main()
{
// kolejka 10-cio elementowa
Queue Q(10);
int i, p, v;
srand(time(NULL));
for(i = 0; i < 10; i++)
{
v = rand()%100;
p = rand()%10;
cout << setw(2) << v << ":" << p
<< endl;
Q.push(p, v);
}
cout << "----\n";
while(!Q.empty())
{
cout << setw(2) << Q.front()
<< ":" << Q.frontprio()
<< endl;
Q.pop();
}
return 0;
}
|
Basic' Kolejka priorytetowa z kopcem
' Data: 5.03.2013
' (C)2020 mgr Jerzy Wałaszek
'------------------------------
Const MAXINT = 2147483647
' Definicja typu obiektowego Queue
'----------------------------------
Type Qel
prio As Integer
Data As Integer
End Type
Type Queue
Private:
T As Qel Ptr
n As Integer
Public:
Declare Constructor(max_n As integer)
Declare Destructor
Declare Function q_empty As Integer
Declare Function q_front As Integer
Declare Function q_frontprio As Integer
Declare Sub push(ByVal prio As Integer, _
ByVal v As Integer)
Declare Sub q_pop
End Type
'---------------
' Program główny
'---------------
' kolejka 10-cio elementowa
Dim Q As Queue = 10
Dim As Integer i, p, v
Randomize
For i = 1 To 10
v = Int(Rnd*100)
p = Int(Rnd*10)
Print Using "##:#";v;p
Q.push(p, v)
Next
Print "----"
While Q.q_empty = 0
Print Using "##:#";Q.q_front;Q.q_frontprio
Q.q_pop
Wend
End
'----------------------
' Metody obiektu Queue
'----------------------
' Konstruktor-tworzy pustą listę
'---------------------------------
Constructor Queue(max_n As Integer)
T = New Qel[max_n]
n = 0
End Constructor
' Destruktor-usuwa listę z pamięci
'-----------------------------------
Destructor Queue
Delete [] T
End Destructor
' Sprawdza, czy kolejka jest pusta
'---------------------------------
Function Queue.q_empty As Integer
If n = 0 Then Return 1
Return 0
End Function
' Zwraca początek kolejki.
' Wartość specjalna to -MAXINT
'-----------------------------
Function Queue.q_front As Integer
If n = 0 then
q_front = -MAXINT
Else
q_front = T[0].data
End If
End Function
' Zwraca priorytet pierwszego elementu
'-------------------------------------
Function Queue.q_frontprio As Integer
If n = 0 then
q_frontprio = -MAXINT
Else
q_frontprio = T[0].prio
End If
End Function
' Zapisuje do kolejki
'--------------------
Sub Queue.push(ByVal prio As Integer, _
ByVal v As Integer)
Dim As Integer i, j
i = n
n += 1
j = (i-1)\2
While i > 0 AndAlso T[j].prio < prio
T[i] = T[j]
i = j
j = (i-1)\2
Wend
T[i].prio = prio
T[i].data = v
End Sub
' Usuwa z kolejki
'----------------
Sub Queue.q_pop
Dim As Integer i, j, v, p
If n > 0 Then
n -= 1
p = T[n].prio
v = T[n].data
i = 0
j = 1
While j < n
if(j+1 < n) AndAlso _
(T[j+1].prio > T[j].prio) Then _
j += 1
If p >= T[j].prio Then Exit While
T[i] = T[j]
i = j
j = 2*j+1
Wend
T[i].prio = p
T[i].data = v
End If
End Sub
|
| Python (dodatek) |
# Kolejka priorytetowa z kopcem
# Data: 11.07.2024
# (C)2024 mgr Jerzy Wałaszek
#------------------------------
import random
# wartość specjalna
MAXINT = 2147483647
# Element tablicy
#----------------
class Qel:
def __init__(self):
self.prio = 0
self.data = 0
# Definicja typu obiektowego Queue
#----------------------------------
class Queue:
# Konstruktor
def __init__(self, max_n):
self.t = []
self.n = 0
for i in range(max_n):
self.t.append(Qel())
# destruktor
def __del__(self):
self.t = None
# kolejka jest pusta?
def empty(self):
return not self.n
# zwraca początek kolejki
# wartość specjalna to -MAXINT
def front(self):
if self.n:
return self.t[0].data
else:
return -MAXINT
# priorytet pierwszego elementu
def frontprio(self):
if self.n:
return self.t[0].prio
else:
return -MAXINT
# zapis do kolejki wg priorytetu
def push(self, p, v):
i = self.n
self.n += 1
j = (i-1)//2
while i and (self.t[j].prio < p):
self.t[i].prio = self.t[j].prio
self.t[i].data = self.t[j].data
i = j
j = (i-1)//2
self.t[i].prio = p
self.t[i].data = v
# Usuwa z kolejki
def pop(self):
if self.n:
self.n -= 1
p = self.t[self.n].prio
v = self.t[self.n].data
i, j = 0, 1
while j < self.n:
if (j+1 < self.n) and \
(self.t[j+1].prio > self.t[j].prio):
j += 1
if p >= self.t[j].prio: break
self.t[i].prio = self.t[j].prio
self.t[i].data = self.t[j].data
i = j
j = 2*j+1
self.t[i].prio = p
self.t[i].data = v
#---------------
# Program główny
#---------------
# kolejka 10-cio elementowa
q = Queue(10)
for i in range(10):
v = random.randrange(100)
p = random.randrange(10)
print("%2d:%d" %(v, p))
q.push(p, v)
print("----")
while not q.empty():
print("%2d:%d" %(q.front(),
q.frontprio()))
q.pop()
|
| Wynik: |
3:1 61:6 82:8 77:1 5:7 60:4 99:2 53:7 91:0 12:9 ---- 12:9 82:8 53:7 5:7 61:6 60:4 99:2 3:1 77:1 91:0 |
![]() |
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.