Serwis Edukacyjny
w I-LO w Tarnowie
obrazek

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

Reprezentacja zbiorów w drzewach binarnych

SPIS TREŚCI
Tematy pomocnicze

Rozwiązanie

Zbiory o dowolnym zakresie wartości elementów można efektywnie realizować za pomocą drzew poszukiwań binarnych BST. Zaletą tych drzew jest szybkość wyszukiwania elementu (O(log n)). Musimy jednakże pamiętać, że zwykłe drzewa BST mogą się degenerować do list liniowych (O(n)). Rozwiązaniem jest stosowanie algorytmu równoważącego drzewo binarne (np. algorytm DSW) lub wybranie innego rodzaju drzew, np. AVL, Splay lub czerwono-czarnych, które automatycznie się równoważą.

W podanych niżej algorytmach nie określamy rodzaju drzew binarnych. Może on być dowolny (BST, AVL, Splay czerwono-czarne lub inne), jednakże każdy węzeł drzewa musi posiadać następujące pola danych:

up : wskaźnik węzła nadrzędnego.
left : wskaźnik lewego potomka.
right : wskaźnik prawego potomka.
key : wartość elementu zbioru, key ∈ typ_danych.

Wartość elementu może należeć do dowolnego zakresu liczbowego (liczby naturalne, całkowite, rzeczywiste). Również zakres tej wartości jest dowolny.

Oprócz wymienionych pól w strukturze węzła drzewa binarnego mogą się znaleźć pola specyficzne dla danej implementacji. Np. dla drzew czerwono-czarnych pojawi się pole color, które przechowuje informację o kolorze węzła.

Pascal
type
  PBTnode = ^BTnode;
  BTnode =  record
    up    : PRBTnode;
    left  : PRBTnode;
    right : PRBTnode;
    key   : typ_danych;
    …
  end;
C++
struct BTnode
{
  BTnode *up, *left, *right;
  typ_danych key;
  …
};
Basic
Type BTnode
  up As BTnode Ptr
  left As BTnode Ptr
  right As BTnode Ptr
  key As typ_danych
  …
End Type
Python (dodatek)
class BTnode:


    def __init__(self)
        self.up    = None
        self.left  = None
        self.right = None
        self.key   = 0
        …

Zbiór będzie reprezentowany przez zmienną, która przechowuje adres korzenia drzewa binarnego. Zmienna ta będzie przekazywana przez referencję do procedur obsługujących strukturę zbioru.

Algorytmy operacji dla zbiorów reprezentowanych drzewami binarnymi

s_isin(A, x) – zwraca wskazanie do węzła o wartości x, jeśli taki węzeł jest w zbiorze A, inaczej zwraca wskazanie puste nil

Algorytm przemieszcza się w dół drzewa binarnego, poczynając od korzenia. Gdy natrafi na element o wartości x, zwraca jego adres. Jeśli dotrze do liścia różnego od x, zwraca nil.

Wejście:

A : adres korzenia drzewa binarnego.
x : element badany na obecność w zbiorze, x ∈ C.

Wyjście:

Wskazanie elementu o wartości x, jeśli znajduje się w zbiorze. Inaczej wskazanie puste.

Lista kroków:

K01: Dopóki A wskazuje węzeł drzewa, ; ta operacja jest zależna od
     wykonuj kroki K02…K03           ; przyjętej struktury drzewa
K02: Jeśli (Akey) = x, ; element znaleziony
     to zakończ z wynikiem A
K03: Jeśli x < (Akey),
     to A ← (Aleft) ; szukamy dalej w lewej gałęzi drzewa
     Inaczej A ← (Aright) ; lub w prawej w zależności od x
K04: Zakończ z wynikiem nil ; element nie został znaleziony

s_add(A, x) – dodaje element x do zbioru A.

Jeśli elementu o wartości x nie ma w zbiorze A, to zostaje on dodany. Jeśli element x jest już w zbiorze A, to nie jest dodawany ponownie.

Wejście:

A : referencja do wskaźnika korzenia drzewa binarnego.
x : element do dodania do zbioru, x ∈ C.

Wyjście:

Zbiór A z dodanym elementem x.

Elementy pomocnicze:

s_isin(Z, v) : zwraca adres węzła o kluczu v w drzewie Z.

Lista kroków:

K01: Jeśli s_isin(A, x) = nil,    ; ta operacja jest zależna od
     to dodaj węzeł x do drzewa A ; przyjętej struktury drzewa
K02: Zakończ

s_remove(A, x) – usuwa element x ze zbioru A

Jeśli element o wartości x jest w zbiorze A, to zostanie on usunięty.

Wejście:

A : referencja do wskaźnika korzenia drzewa binarnego.
x : element do usunięcia ze zbioru, x ∈ C.

Wyjście:

Zbiór A z usuniętym elementem x.

Elementy pomocnicze:

s_isin(Z, v) : zwraca adres węzła o kluczu v w drzewie Z.
p : wskaźnik do węzła drzewa binarnego.

Lista kroków:

K01: ps_isin(A, x) ; pobieramy adres węzła o wartości x
K02: Jeśli p ≠ nil, ; ta operacja jest zależna od przyjętej struktury drzewa
     to usuń z drzewa A węzeł wskazywany przez p
K03: Zakończ

s_clear(A) – usuwa wszystkie elementy ze zbioru A. Zbiór A staje się zbiorem pustym.

Algorytm rekurencyjnie usuwa elementy z drzewa A aż do otrzymania drzewa pustego.

Wejście:

A : referencja do wskaźnika korzenia drzewa binarnego.

Wyjście:

Pusty zbiór A.

Lista kroków:

K01: Jeśli A nie wskazuje węzła, ; ta operacja jest zależna od przyjętej struktury drzewa
     to zakończ
K02: s_clear(Aleft) ; usuwamy rekurencyjnie lewą gałąź
K03: s_clear(Aright) ; usuwamy rekurencyjnie prawą gałąź
K04: Usuń węzeł wskazywany przez A
K05: A ← węzeł pusty ; ta operacja jest zależna od przyjętej struktury drzewa
K06: Zakończ

s_copy(A, C)

Algorytm pomocniczy kopiuje wszystkie elementy z drzewa A do C.

Wejście:

A : wskaźnik korzenia drzewa A.
C : referencja do wskaźnika korzenia drzewa C.

Wyjście:

Zbiór C zawiera wszystkie elementy z A.

Elementy pomocnicze:

s_add(Z, x) : dodaje węzeł x do drzewa Z.

Lista kroków:

K01: Jeśli A nie wskazuje węzła, ; ta operacja jest zależna od przyjętej struktury drzewa
     to zakończ
K02: s_add(C, Akey) ; do C wstawiamy węzeł bieżący
K03: s_copy(Aleft, C) ; rekurencyjnie kopiujemy lewe poddrzewo
K04: s_copy(Aright, C) ; rekurencyjnie kopiujemy prawe poddrzewo
K05: Zakończ

s_union(A, B, C) – zwraca sumę zbiorów A i B

Algorytm kopiuje wszystkie elementy z drzewa A do C, a następnie B do C.

Wejście:

A, B : wskaźniki korzeni drzew A i B.
C : referencja do wskaźnika korzenia drzewa C.

Wyjście:

Zbiór C zawiera sumę zbiorów A i B.

Elementy pomocnicze:

s_clear(Z) : usuwa ze zbioru Z wszystkie elementy.
s_copy
(Y, Z) : kopiuje elementy z Y do Z.

Lista kroków:

K01: s_clear(C) ; dla pewności usuwamy wszystkie węzły z C
K02: s_copy(A, C) ; kopiujemy A do C
K03: s_copy(B, C) ; kopiujemy B do C
K04: Zakończ

s_icopy(A, B, C)

Algorytm pomocniczy kopiuje do C elementy drzewa A, jeśli ich wartości znajdują się również w drzewie B.

Wejście:

A, B : wskaźniki korzeni drzew A i B.
C : referencja do wskaźnika korzenia drzewa C.

Wyjście:

Zbiór C zawiera część wspólną zbiorów A i B.

Elementy pomocnicze:

s_isin(Z, x) : zwraca adres węzła o wartości x w drzewie Z.
s_add(Z, x) : dodaje węzeł o wartości x do drzewa Z.

Lista kroków:

K01: Jeśli A nie wskazuje węzła, ; ta operacja jest zależna od przyjętej struktury drzewa
     to zakończ
K02: Jeśli s_isin(B, Akey) ≠ nil, ; do C wstawiamy element z A, jeśli jest on również w B
     to s_add(C, Akey)
K03: s_icopy(Aleft, B, C) ; rekurencyjnie przetwarzamy lewe poddrzewo
K04: s_icopy(Aright, B, C) ; rekurencyjnie przetwarzamy prawe poddrzewo
K05: Zakończ

s_intersection(A, B, C) – zwraca iloczyn zbiorów A i B

Algorytm tworzy w drzewie C iloczyn zbiorów A i B.

Wejście:

A, B : wskaźniki korzeni drzew A i B.
C : referencja do wskaźnika korzenia drzewa C.

Wyjście:

Zbiór C zawiera iloczyn zbiorów A i B.

Elementy pomocnicze:

s_clear(Z) : usuwa ze zbioru Z wszystkie elementy.
s_icopy(X, Y, Z) : umieszcza w Z iloczyn zbiorów X i Y.

Lista kroków:

K01: s_clear(C) ; czyścimy drzewo C
K02: s_icopy(A, B, C) ; tworzymy w C iloczyn A i B
K03: Zakończ

s_dcopy(A, B, C)

Algorytm pomocniczy kopiuje do C elementy drzewa A, jeśli ich wartości nie występują w drzewie B.

Wejście:

A, B : wskaźniki korzeni drzew A i B.
C : referencja do wskaźnika korzenia drzewa C.

Wyjście:

Zbiór C zawiera wszystkie część wspólną zbiorów A i B.

Elementy pomocnicze:

s_isin(Z, x) : zwraca adres węzła o wartości x w drzewie Z.
s_add(Z, x) : dodaje węzeł o wartości x do drzewa Z.

Lista kroków:

K01: Jeśli A nie wskazuje węzła, ; ta operacja jest zależna od przyjętej struktury drzewa
     to zakończ
K02: Jeśli s_isin(B, Akey) = nil, ; do C wstawiamy element z A, jeśli nie ma go w B
     to s_add(C, (Akey))
K03: s_dcopy(Aleft, C) ; rekurencyjnie przetwarzamy lewe poddrzewo
K04: s_dcopy(Aright, C) ; rekurencyjnie przetwarzamy prawe poddrzewo
K05: Zakończ

s_difference(A, B, C) – zwraca różnicę zbiorów A i B

Algorytm tworzy w drzewie C różnicę zbiorów A i B.

Wejście:

A, B : wskaźniki korzeni drzew A i B.
C : referencja do wskaźnika korzenia drzewa C.

Wyjście:

Zbiór C zawiera iloczyn zbiorów A i B.

Elementy pomocnicze:

s_clear(Z) : usuwa ze zbioru Z wszystkie elementy.
s_icopy(X, Y, Z) : umieszcza w Z iloczyn zbiorów X i Y.

Lista kroków:

K01: s_clear(C) ; czyścimy drzewo C
K02: s_dcopy(A, B, C) ; tworzymy w C różnicę A i B
K03: Zakończ

s_subset(A, B) – zwraca true, jeśli zbiór A jest podzbiorem zbioru B, inaczej zwraca false.

Algorytm sprawdza, czy wszystkie elementy drzewa A posiadają swoje odpowiedniki w drzewie B.

Wejście:

A, B : wskaźniki korzeni drzew A i B.

Wyjście:

true : zbiór A jest podzbiorem zbioru B.
false : zbiór A nie jest podzbiorem zbioru B.

Elementy pomocnicze:

s_isin(Z, x) : zwraca adres węzła o wartości x w drzewie Z.

Lista kroków:

K01: Jeśli A nie wskazuje węzła, ; ta operacja jest zależna od przyjętej struktury drzewa
     to zakończ z wynikiem true
K02: Jeśli s_isin(B, Akey) = nil, ; element z A nie występuje w B
     to zakończ z wynikiem false
K03: Zakończ z wynikiem:
     s_subset(Aleft, B)obrazeks_subset(Aright, B)
     ; przetwarzamy rekurencyjnie węzły potomne

s_cnt(A, cnt)

Algorytm pomocniczy zlicza rekurencyjnie węzły w drzewie A.

Wejście:

A : wskaźnik korzenia drzewa A.
cnt : referencja do zmiennej licznika.

Wyjście:

cnt zawiera liczbę węzłów.

Lista kroków:

K01: Jeśli A nie wskazuje węzła, ; ta operacja jest zależna od przyjętej struktury drzewa
     to zakończ
K02: cntcnt+1 ; mamy węzeł, zwiększamy licznik
K03: s_cnt(Aleft, cnt) ; zliczamy węzły w lewym poddrzewie
K04: s_cnt(Aright, cnt) ; zliczamy węzły w prawym poddrzewie
K05: Zakończ

s_size(A) – zwraca liczbę elementów zawartych w zbiorze A

Algorytm zlicza węzły w drzewie A i zwraca ich liczbę.

Wejście:

A : wskaźnik korzenia drzewa A.

Wyjście:

Liczba elementów w A.

Elementy pomocnicze:

cnt : licznik węzłów, cnt ∈ C.
s_cnt(Z, c) : zwraca liczbę węzłów w c.

Lista kroków:

K01: cnt ← 0 ; zerujemy licznik
K02: s_cnt(A, cnt) ; zliczamy węzły
K03: Zakończ z wynikiem cnt

s_empty(A) – zwraca true, jeśli zbiór A jest pusty, inaczej zwraca false

Algorytm zwraca true, jeśli korzeń drzewa jest pustym węzłem.

Wejście:

A : wskaźnik korzenia drzewa A.

Wyjście:

true : zbiór A jest pusty.
false : zbiór A nie jest pusty.

Lista kroków:

K01: Jeśli A nie wskazuje węzła, 
     to zakończ z wynikiem true
     Inaczej zakończ z wynikiem false
     ; ta operacja jest zależna od przyjętej struktury drzewa

Przykładowe programy

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 testuje wszystkie funkcje obsługi zbiorów opartych na drzewach binarnych. Wyjaśnienie wykonywanych operacji znajduje się w komentarzach wewnątrz programu. Za drzewo binarne przyjęliśmy model drzew czerwono-czarnych.
Pascal
// Zbiory zaimplementowane
// w drzewach czerwono-czarnych
// Data: 9.07.2014
// (C)2014 mgr Jerzy Wałaszek
//-----------------------------

program sets;

// Definicja węzła drzewa
// czerwono-czarnego
type
  PRBTnode = ^RBTnode;
  RBTnode  = record
    up    : PRBTnode;
    left  : PRBTnode;
    right : PRBTnode;
    key   : integer;
    color : char;
  end;

// Zmienne globalne

var
  // Węzeł strażnika
  S : RBTnode = (up:@S;
                 left:@S;
                 right:@S;
                 key:0;
                 color:'B');

// Procedury obsługi drzew
// czerwono-czarnych

// Wykonuje rotację
// w lewo względem A
//------------------
procedure rot_L(var root : PRBTnode;
                       A : PRBTnode);
var
  B, p : PRBTnode;
begin
  B := A^.right;
  if B <> @S then
  begin
    p := A^.up;
    A^.right := B^.left;
    if A^.right <> @S then
      A^.right^.up := A;
    B^.left := A;
    B^.up := p;
    A^.up := B;
    if p <> @S then
    begin
      if p^.left = A then
        p^.left := B
      else
        p^.right := B;
    end
    else root := B;
  end;
end;

// Wykonuje rotację
// w prawo względem A
//-------------------
procedure rot_R(var root : PRBTnode;
                       A : PRBTnode);
var
  B, p : PRBTnode;
begin
  B := A^.left;
  if B <> @S then
  begin
    p := A^.up;
    A^.left := B^.right;
    if A^.left <> @S then
      A^.left^.up := A;
    B^.right := A;
    B^.up := p;
    A^.up := B;
    if p <> @S then
    begin
      if p^.left = A then
        p^.left := B
      else
        p^.right := B;
    end
    else root := B;
  end;
end;

// Wstawia do drzewa węzeł
// o kluczu k
//------------------------
procedure insert_rbt(var root : PRBTnode;
                            k : integer);
var
  X, Y : PRBTnode;
begin
  // Tworzymy nowy węzeł
  new(X);
  // Inicjujemy pola
  X^.left  := @S;
  X^.right := @S;
  X^.up    := root;
  X^.key   := k;
  // X staje się korzeniem
  if X^.up = @S then
    root := X
  else
    // Szukamy liścia do zastąpienia przez X
    while true do
    begin
      if k < X^.up^.key then
      begin
        if X^.up^.left = @S then
        begin
          // X zastępuje lewy liść
          X^.up^.left := X;
          break;
        end;
        X^.up := X^.up^.left;
      end
      else
      begin
        if X^.up^.right = @S then
        begin
          // X zastępuje prawy liść
          X^.up^.right := X;
          break;
        end;
        X^.up := X^.up^.right;
      end;
    end;
  // Węzeł kolorujemy na czerwono
  X^.color := 'R';
  while (X <> root) and
        (X^.up^.color = 'R') do
  begin
    if X^.up = X^.up^.up^.left then
    begin
      // Y -> wujek X
      Y := X^.up^.up^.right;
      // Przypadek 1
      if Y^.color = 'R' then
      begin
        X^.up^.color := 'B';
        Y^.color := 'B';
        X^.up^.up^.color := 'R';
        X := X^.up^.up;
        continue;
      end;
      // Przypadek 2
      if X = X^.up^.right then
      begin
        X := X^.up;
        rot_L(root, X);
      end;
      // Przypadek 3
      X^.up^.color := 'B';
      X^.up^.up^.color := 'R';
      rot_R(root, X^.up^.up);
      break;
    end
    else
    begin // Przypadki lustrzane
      Y := X^.up^.up^.left;
      // Przypadek 1
      if Y^.color = 'R' then
      begin
        X^.up^.color := 'B';
        Y^.color := 'B';
        X^.up^.up^.color := 'R';
        X := X^.up^.up;
        continue;
      end;
      // Przypadek 2
      if X = X^.up^.left then
      begin
        X := X^.up;
        rot_R(root, X);
      end;
      // Przypadek 3
      X^.up^.color := 'B';
      X^.up^.up^.color := 'R';
      rot_L(root, X^.up^.up);
      break;
    end;
  end;
  root^.color := 'B';
end;

// Wyszukuje najmniejszy węzeł
// w poddrzewie o korzeniu p
//----------------------------
function  min_rbt(p : PRBTnode)
                    : PRBTnode;
begin
  if p <> @S then
    while p^.left <> @S do
      p := p^.left;
  min_rbt := p;
end;

// Zwraca następnik p
//-------------------
function succ_rbt(p : PRBTnode)
                    : PRBTnode;
var
  r : PRBTnode;
begin
  succ_rbt := @S;
  if p <> @S then
  begin
    if p^.right <> @S then
      succ_rbt := min_rbt(p^.right)
    else
    begin
      r := p^.up;
      while (r <> @S) and
            (p = r^.right) do
      begin
        p := r;
        r := r^.up;
      end;
      succ_rbt := r;
    end;
  end;
end;

// Usuwa z drzewa węzeł X
//-----------------------
procedure remove_rbt(var root : PRBTnode;
                            X : PRBTnode);
var
  W, Y, Z : PRBTnode;
begin
  if (X^.left = @S) or
     (X^.right = @S) then
    Y := X
  else
    Y := succ_rbt(X);
  if Y^.left <> @S then
    Z := Y^.left
  else
    Z := Y^.right;
  Z^.up := Y^.up;
  if Y^.up = @S then
    root := Z
  else
    if Y = Y^.up^.left then
      Y^.up^.left  := Z
  else
    Y^.up^.right := Z;
  if Y <> X then
    X^.key := Y^.key;
  // Naprawa struktury drzewa
  // czerwono-czarnego
  if Y^.color = 'B' then
    while (Z <> root) and
          (Z^.color = 'B') do
      if Z = Z^.up^.left then
      begin
        W := Z^.up^.right;
        if W^.color = 'R' then
        begin // Przypadek 1
          W^.color := 'B';
          Z^.up^.color := 'R';
          rot_L(root, Z^.up);
          W := Z^.up^.right;
        end;
        if (W^.left^.color = 'B') and
           (W^.right^.color = 'B') then
        begin // Przypadek 2
          W^.color := 'R';
          Z := Z^.up;
          continue;
        end;
        if W^.right^.color = 'B' then
        begin // Przypadek 3
          W^.left^.color := 'B';
          W^.color := 'R';
          rot_R(root, W);
          W := Z^.up^.right;
        end;
        // Przypadek 4
        W^.color := Z^.up^.color;
        Z^.up^.color := 'B';
        W^.right^.color := 'B';
        rot_L(root, Z^.up);
        // To spowoduje zakończenie pętli
        Z := root;
      end
      else
      begin // Przypadki lustrzane
        W := Z^.up^.left;
        if W^.color = 'R' then
        begin // Przypadek 1
          W^.color := 'B';
          Z^.up^.color := 'R';
          rot_R(root, Z^.up);
          W := Z^.up^.left;
        end;
        if (W^.left^.color = 'B') and
           (W^.right^.color = 'B') then
        begin // Przypadek 2
          W^.color := 'R';
          Z := Z^.up;
          continue;
        end;
        if W^.left^.color = 'B' then
        begin // Przypadek 3
          W^.right^.color := 'B';
          W^.color := 'R';
          rot_L(root, W);
          W := Z^.up^.left;
        end;
        // Przypadek 4
        W^.color := Z^.up^.color;
        Z^.up^.color := 'B';
        W^.left^.color := 'B';
        rot_R(root, Z^.up);
        // To spowoduje zakończenie pętli
        Z := root;
      end;
  Z^.color := 'B';
  dispose(Y);
end;

// Procedury obsługi zbioru

// Szuka w drzewie węzła
// o danej wartości klucza x.
// Jeśli węzeł zostanie
// znaleziony, to zwraca jego adres.
// Inaczej zwraca wskazanie puste.
//----------------------------------
function s_isin(A : PRBTnode;
                x : integer)
                  : PRBTnode;
begin
  while A <> @S do
  begin
    // Węzeł znaleziony
    if A^.key = x then Exit(A);
    if x < A^.key then
      A := A^.left
    else
      A := A^.right;
  end;
  // Węzeł nieznaleziony
  s_isin := nil;
end;

// Dodaje do drzewa nowy węzeł,
// jeśli w drzewie takiego węzła
// jeszcze nie ma
//------------------------------
procedure s_add(var A : PRBTnode;
                    x : integer);
begin
  if s_isin(A, x) = nil then
    insert_rbt(A, x);
end;

// Wyszukuje w drzewie węzeł
// o kluczu x i usuwa go
//--------------------------
procedure s_remove(var A : PRBTnode;
                       x : integer);
var
  p : PRBTnode;
begin
  // Szukamy węzła o kluczu x
  p := s_isin(A, x);
  if p <> nil then
    remove_rbt(A, p);
end;

// Usuwa wszystkie węzły z drzewa
//-------------------------------
procedure s_clear(var A : PRBTnode);
begin
  if A <> @S then
  begin
    // Rekurencyjnie usuwamy
    // lewe poddrzewo
    s_clear(A^.left);
    // Rekurencyjnie usuwamy
    // prawe poddrzewo
    s_clear(A^.right);
    // Usuwamy węzeł
    dispose(A);
    A := @S;
  end;
end;

// Procedura kopiuje elementy
// z drzewa A do C
//---------------------------
procedure s_copy(A : PRBTnode;
             var C : PRBTnode);
begin
  if A <> @S then
  begin
    // Dodajemy do C klucz
    // bieżącego węzła
    s_add(C, A^.key);
    // Rekurencyjnie dodajemy
    // do C lewe poddrzewo
    s_copy(A^.left, C);
    // Rekurencyjnie dodajemy
    // do C prawe poddrzewo
    s_copy(A^.right, C);
  end;
end;

// Procedura tworzy sumę
// zbiorów A i B w C
//----------------------
procedure s_union(A, B : PRBTnode;
                 var C : PRBTnode);
begin
  // Czyścimy C
  s_clear(C);
  // W C umieszczamy A
  s_copy(A, C);
  // Dodajemy B do C
  s_copy(B, C);
end;

// Procedura kopiuje do C
// te elementy A, które
// również są w B
//-----------------------
procedure s_icopy(A, B : PRBTnode;
                 var C : PRBTnode);
begin
  if A <> @S then
  begin
    if s_isin(B, A^.key) <> nil then
      s_add(C, A^.key);
    s_icopy(A^.left, B, C);
    s_icopy(A^.right, B, C);
  end;
end;

// Procedura tworzy w C
// iloczyn zbiorów A i B
//----------------------
procedure s_intersection(A, B : PRBTnode;
                        var C : PRBTnode);
begin
  // Czyścimy C
  s_clear(C);
  // Tworzymy iloczyn zbiorów
  s_icopy(A, B, C);
end;

// Procedura kopiuje do C
// te elementy A, których
// nie ma w B
//-----------------------
procedure s_dcopy(A, B : PRBTnode;
                 var C : PRBTnode);
begin
  if A <> @S then
  begin
    if s_isin(B, A^.key) = nil then
      s_add(C, A^.key);
    s_dcopy(A^.left, B, C);
    s_dcopy(A^.right, B, C);
  end;
end;

// Procedura tworzy w C
// różnicę zbiorów A i B
//----------------------
procedure s_difference(A, B : PRBTnode;
                      var C : PRBTnode);
begin
  // Czyścimy C
  s_clear(C);
  // Tworzymy różnicę zbiorów
  s_dcopy(A, B, C);
end;

// Funkcja zwraca true,
// jeśli zbiór A jest
// podzbiorem B
//---------------------
function s_subset(A, B : PRBTnode)
                       : boolean;
begin
  if A = @S then Exit(true);
  if s_isin(B, A^.key) = nil then
    Exit(false);
  s_subset := s_subset(A^.left, B) and
              s_subset(A^.right, B);
end;

// Procedura zlicza rekurencyjnie
// węzły w drzewie
//-------------------------------
procedure s_cnt(A : PRBTnode;
          var cnt : integer);
begin
  if A <> @S then
  begin
    // Zliczamy węzeł bieżący
    inc(cnt);
    // Rekurencyjnie liczymy węzły
    // w lewym poddrzewie
    s_cnt(A^.left, cnt);
    // Rekurencyjnie liczymy węzły
    // w prawym poddrzewie
    s_cnt(A^.right, cnt);
  end;
end;

// Funkcja oblicza liczbę
// węzłów w drzewie
//-----------------------
function s_size(A : PRBTnode)
                  : integer;
var
  // Licznik węzłów
  cnt : integer;
begin
  // Zerujemy licznik
  cnt := 0;
  // Zliczamy węzły
  s_cnt(A, cnt);
  // Zwracamy wynik
  s_size := cnt;
end;

// Funkcja zwraca true,
// jeśli zbiór jest pusty
//-----------------------
function s_empty(A : PRBTnode)
                   : boolean;
begin
  s_empty := A = @S;
end;

// Procedura rekurencyjnie
// wyświetla zawartość drzewa
//---------------------------
procedure s_print(A : PRBTnode);
begin
  if A <> @S then
  begin
    s_print(A^.left);
    write(A^.key, ' ');
    s_print(A^.right);
  end;
end;

// **********************
// *** PROGRAM GŁÓWNY ***
// **********************

var
  A, B, C, D : PRBTnode;
  i, x       : integer;

begin
  randomize;
  // Tworzymy puste zbiory
  A := @S;
  B := @S;
  C := @S;
  D := @S;
  // Do zbioru A dodajemy 10 losowych elementów
  for i := 1 to 10 do
    s_add(A, -20+random(41));
  // Do zbioru B dodajemy 15 losowych elementów
  for i := 1 to 15 do
    s_add(B, -20+random(41));
  // Wyświetlamy je
  writeln('A:');
  s_print(A); writeln;
  writeln('SIZE OF A IS ', s_size(A));
  writeln;
  writeln('B:');
  s_print (B); writeln;
  writeln('SIZE OF B IS ', s_size(B));
  // Suma zbiorów
  writeln;
  writeln('UNION OF A AND B:');
  s_union(A, B, C);
  s_print(C); writeln;
  writeln('SIZE OF UNION IS ', s_size(C));
  // Iloczyn zbiorów
  writeln;
  writeln('INTERSECTION OF A AND B:');
  s_intersection(A, B, C);
  s_print(C); writeln;
  writeln('SIZE OF INTERSECTION IS ', s_size(C));
  // Różnica zbiorów
  writeln;
  writeln('DIFFERENCE OF A AND B:');
  s_difference(A, B, C);
  s_print(C); writeln;
  writeln('SIZE OF DIFFERENCE IS ', s_size(C));
  // Podzbiór
  // Kopiujemy A do C
  s_union(A, A, C);
  // Usuwamy 7 elementów
  for i := 1 to 7 do
    s_remove(C, -20+random(41));
  writeln;
  writeln('IS:');
  s_print(C);
  writeln(' SUBSET OF A?');
  writeln(s_subset(C, A));
  s_difference(B, A, C);
  // Usuwamy 12 elementów
  for i := 1 to 12 do
    s_remove(C, -20+random(41));
  writeln;
  writeln('IS:');
  s_print(C);
  writeln(' SUBSET OF A?');
  writeln(s_subset(C, A));
  // Usuwanie
  writeln;
  write('FROM A WE REMOVE');
  for i := 1 to 5 do
  begin
    x := -20+random(41);
    write(x:4);
    s_remove(A, x);
  end;
  writeln;
  writeln('A:'); s_print(A); writeln;
  writeln('SIZE OF A IS ', s_size(A));
  writeln;
  // Sprawdzamy obecność wybranych
  // elementów w B
  for i := 1 to 10 do
  begin
    x := -20+random(41);
    write('IS ELEMENT', x:4, ' IN SET B? ');
    if s_isin(B, x) <> nil then
      writeln('YES')
    else
      writeln('NO');
  end;
  writeln;
  // Sprawdzenie testu na zbiór pusty
  writeln('IS SET A EMPTY?');
  writeln(s_empty(A));
  writeln;
  writeln('IS INTERSECTION OF A AND DIFFERENCE' +
          ' OF B AND A EMPTY?');
  s_difference(B, A, C);
  s_intersection(A, C, D);
  writeln(s_empty(D));
  writeln;
  // Usuwamy zbiory
  s_clear(A);
  s_clear(B);
  s_clear(C);
  s_clear(D);
end.
C++
// Zbiory zaimplementowane
// w drzewach czerwono-czarnych
// Data: 9.07.2014
// (C)2014 mgr Jerzy Wałaszek
//-----------------------------

#include <iostream>
#include <iomanip>
#include <cstdlib>
#include <ctime>

using namespace std;

// Definicja węzła drzewa
// czerwono-czarnego
struct RBTnode
{
  RBTnode * up;
  RBTnode * left;
  RBTnode * right;
  int key;
  char color;
};

// Zmienne globalne
RBTnode S = {&S, &S, &S, 0, 'B'};

// Procedury obsługi drzew czerwono-czarnych

// Wykonuje rotację w lewo
// względem A
//------------------------
void rot_L(RBTnode * & root,
           RBTnode * A)
{
  RBTnode * B, * p;

  B = A->right;
  if(B != &S)
  {
    p = A->up;
    A->right = B->left;
    if(A->right != &S)
      A->right->up = A;
    B->left = A;
    B->up = p;
    A->up = B;
    if(p != &S)
    {
      if(p->left == A)
        p->left = B;
      else
        p->right = B;
    }
    else root = B;
  }
}

// Wykonuje rotację w prawo
// względem A
//-------------------------
void rot_R(RBTnode * & root,
           RBTnode * A)
{
  RBTnode * B, * p;

  B = A->left;
  if(B != &S)
  {
    p = A->up;
    A->left = B->right;
    if(A->left != &S)
      A->left->up = A;
    B->right = A;
    B->up = p;
    A->up = B;
    if(p != &S)
    {
      if(p->left == A)
        p->left = B;
      else
        p->right = B;
    }
    else root = B;
  }
}

// Wstawia do drzewa węzeł
// o kluczu k
//------------------------
void insert_rbt(RBTnode * & root,
                int k)
{
  RBTnode * X, * Y;

  // Tworzymy nowy węzeł
  X = new RBTnode;
  // Inicjujemy pola
  X->left  = &S;
  X->right = &S;
  X->up    = root;
  X->key   = k;
  // X staje się korzeniem
  if(X->up == &S)
    root = X;
  else
    // Szukamy liścia do zastąpienia
    // przez X
    while(true)
    {
      if(k < X->up->key)
      {
        if(X->up->left == &S)
        {
          // X zastępuje lewy liść
          X->up->left = X;
          break;
        }
        X->up = X->up->left;
      }
      else
      {
        if(X->up->right == &S)
        {
          // X zastępuje prawy liść
          X->up->right = X;
          break;
        }
        X->up = X->up->right;
      }
    }
  // Węzeł kolorujemy na czerwono
  X->color = 'R';
  while((X != root) &&
        (X->up->color == 'R'))
  {
    if(X->up == X->up->up->left)
    {
      // Y -> wujek X
      Y = X->up->up->right;
      // Przypadek 1
      if(Y->color == 'R')
      {
        X->up->color = 'B';
        Y->color = 'B';
        X->up->up->color = 'R';
        X = X->up->up;
        continue;
      }
      // Przypadek 2
      if(X == X->up->right)
      {
        X = X->up;
        rot_L(root, X);
      }
      // Przypadek 3
      X->up->color = 'B';
      X->up->up->color = 'R';
      rot_R(root, X->up->up);
      break;
    }
    else
    { // Przypadki lustrzane
      Y = X->up->up->left;
      // Przypadek 1
      if(Y->color == 'R')
      {
        X->up->color = 'B';
        Y->color = 'B';
        X->up->up->color = 'R';
        X = X->up->up;
        continue;
      }
      // Przypadek 2
      if(X == X->up->left)
      {
        X = X->up;
        rot_R(root, X);
      }
      // Przypadek 3
      X->up->color = 'B';
      X->up->up->color = 'R';
      rot_L(root, X->up->up);
      break;
    }
  }
  root->color = 'B';
}

// Wyszukuje najmniejszy węzeł
// w poddrzewie o korzeniu p
//----------------------------
RBTnode * min_rbt(RBTnode * p)
{
  if(p != &S)
    while(p->left != &S)
      p = p->left;
  return p;
}

// Zwraca następnik p
//-------------------
RBTnode * succ_rbt(RBTnode * p)
{
  RBTnode * r;

  if(p != &S)
  {
    if(p->right != &S)
      return min_rbt(p->right);
    else
    {
      r = p->up;
      while((r != &S) &&
            (p == r->right))
      {
        p = r;
        r = r->up;
      }
      return r;
    }
  }
  return &S;
}

// Usuwa z drzewa węzeł X
//-----------------------
void remove_rbt(RBTnode * & root,
                RBTnode * X)
{
  RBTnode * W, * Y, * Z;

  if((X->left == &S) ||
     (X->right == &S))
    Y = X;
  else
    Y = succ_rbt(X);
  if(Y->left != &S)
    Z = Y->left;
  else
    Z = Y->right;
  Z->up = Y->up;
  if(Y->up == &S)
    root = Z;
  else
    if(Y == Y->up->left)
      Y->up->left  = Z;
    else
      Y->up->right = Z;
  if(Y != X)
    X->key = Y->key;
  // Naprawa struktury drzewa
  // czerwono-czarnego
  if(Y->color == 'B')
  {
    while((Z != root) &&
          (Z->color == 'B'))
      if(Z == Z->up->left)
      {
        W = Z->up->right;
        if(W->color == 'R')
        { // Przypadek 1
          W->color = 'B';
          Z->up->color = 'R';
          rot_L(root, Z->up);
          W = Z->up->right;
        }
        if((W->left->color == 'B') &&
           (W->right->color == 'B'))
        { // Przypadek 2
          W->color = 'R';
          Z = Z->up;
          continue;
        }
        if(W->right->color == 'B')
        { // Przypadek 3
          W->left->color = 'B';
          W->color = 'R';
          rot_R(root, W);
          W = Z->up->right;
        }
        // Przypadek 4
        W->color = Z->up->color;
        Z->up->color = 'B';
        W->right->color = 'B';
        rot_L(root, Z->up);
        // To spowoduje zakończenie pętli
        Z = root;
      }
      else
      { // Przypadki lustrzane
        W = Z->up->left;
        if(W->color == 'R')
        { // Przypadek 1
          W->color = 'B';
          Z->up->color = 'R';
          rot_R(root, Z->up);
          W = Z->up->left;
        }
        if((W->left->color == 'B') &&
           (W->right->color == 'B'))
        { // Przypadek 2
          W->color = 'R';
          Z = Z->up;
          continue;
        }
        if(W->left->color == 'B')
        { // Przypadek 3
          W->right->color = 'B';
          W->color = 'R';
          rot_L(root, W);
          W = Z->up->left;
        }
        // Przypadek 4
        W->color = Z->up->color;
        Z->up->color = 'B';
        W->left->color = 'B';
        rot_R(root, Z->up);
        // To spowoduje zakończenie pętli
        Z = root;
      }
  }
  Z->color = 'B';
  delete Y;
}

// Procedury obsługi zbioru

// Szuka w drzewie węzła
// o danej wartości klucza x.
// Jeśli węzeł zostanie znaleziony,
// to zwraca jego adres.
// Inaczej zwraca wskazanie puste.
//---------------------------------
RBTnode * s_isin(RBTnode * A,
                 int x)
{
  while(A != &S)
  {
    // Węzeł znaleziony
    if(A->key == x) return A;
    if(x < A->key)
      A = A->left;
    else
      A = A->right;
  }
  // Węzeł nieznaleziony
  return NULL;
}

// Dodaje do drzewa nowy węzeł,
// jeśli w drzewie takiego węzła
// jeszcze nie ma
//------------------------------
void s_add(RBTnode * & A,
           int x)
{
  if(!s_isin(A, x))
    insert_rbt(A, x);
}

// Wyszukuje w drzewie węzeł o kluczu x i usuwa go
//------------------------------------------------
void s_remove(RBTnode * & A,
              int x)
{
  // Szukamy węzła o kluczu x
  RBTnode * p = s_isin(A, x);
  if(p) remove_rbt(A, p);
}

// Usuwa wszystkie węzły z drzewa
//-------------------------------
void s_clear(RBTnode * & A)
{
  if(A != &S)
  {
    // Rekurencyjnie usuwamy
    // lewe poddrzewo
    s_clear(A->left);
    // Rekurencyjnie usuwamy
    // prawe poddrzewo
    s_clear(A->right);
    // Usuwamy węzeł
    delete A;
    A = &S;
  }
}

// Procedura kopiuje elementy
// z drzewa A do C
//---------------------------
void s_copy(RBTnode * A,
            RBTnode * & C)
{
  if(A != &S)
  {
    // Dodajemy do C klucz
    // bieżącego węzła
    s_add(C, A->key);
    // Rekurencyjnie dodajemy do C
    // lewe poddrzewo
    s_copy(A->left, C);
    // Rekurencyjnie dodajemy do C
    // prawe poddrzewo
    s_copy(A->right, C);
  }
}

// Procedura tworzy sumę
// zbiorów A i B w C
//----------------------
void s_union(RBTnode * A,
             RBTnode * B,
             RBTnode * & C)
{
  // Czyścimy C
  s_clear (C);
  // W C umieszczamy A
  s_copy(A, C);
  // Dodajemy B do C
  s_copy(B, C);
}

// Procedura kopiuje do C
// te elementy A, które
// również są w B
//-----------------------
void s_icopy(RBTnode * A,
             RBTnode * B,
             RBTnode * & C)
{
  if(A != &S)
  {
    if(s_isin(B, A->key))
      s_add(C, A->key);
    s_icopy(A->left, B, C);
    s_icopy(A->right, B, C);
  }
}

// Procedura tworzy w C iloczyn
// zbiorów A i B
//-----------------------------
void s_intersection(RBTnode * A,
                    RBTnode * B,
                    RBTnode * & C)
{
  // Czyścimy C
  s_clear(C);
  // Tworzymy iloczyn zbiorów
  s_icopy(A, B, C);
}

// Procedura kopiuje do C te elementy A,
// których nie ma w B
//--------------------------------------
void s_dcopy(RBTnode * A,
             RBTnode * B,
             RBTnode * & C)
{
  if(A != &S)
  {
    if(!s_isin(B, A->key))
      s_add(C, A->key);
    s_dcopy(A->left, B, C);
    s_dcopy(A->right, B, C);
  }
}

// Procedura tworzy w C różnicę
// zbiorów A i B
//-----------------------------
void s_difference(RBTnode * A,
                  RBTnode * B,
                  RBTnode * & C)
{
  // Czyścimy C
  s_clear(C);
  // Tworzymy różnicę zbiorów
  s_dcopy(A, B, C);
}

// Funkcja zwraca true, jeśli zbiór A
// jest podzbiorem B
//-----------------------------------
bool s_subset(RBTnode * A,
              RBTnode * B)
{
  if(A == &S) return true;
  if(!s_isin(B, A->key)) return false;
  return s_subset(A->left, B) &&
         s_subset(A->right, B);
}

// Procedura zlicza rekurencyjnie
// węzły w drzewie
//-------------------------------
void s_cnt(RBTnode * A,
           int & cnt)
{
  if(A != &S)
  {
    // Zliczamy węzeł bieżący
    cnt++;
    // Rekurencyjnie liczymy węzły
    // w lewym poddrzewie
    s_cnt(A->left, cnt);
    // Rekurencyjnie liczymy węzły
    // w prawym poddrzewie
    s_cnt(A->right, cnt);
  }
}

// Funkcja oblicza liczbę
// węzłów w drzewie
//-----------------------
int s_size(RBTnode * A)
{
  // Zerujemy licznik
  int cnt = 0;
  // Zliczamy węzły
  s_cnt(A, cnt);
  // Zwracamy wynik
  return cnt;
}

// Funkcja zwraca true,
// jeśli zbiór jest pusty
//-----------------------
bool s_empty(RBTnode * A)
{
  return A == &S;
}

// Procedura rekurencyjnie wyświetla
// zawartość drzewa
//----------------------------------
void s_print(RBTnode * A)
{
  if(A != &S)
  {
    s_print(A->left);
    cout << A->key << " ";
    s_print(A->right);
  }
}

// **********************
// *** PROGRAM GŁÓWNY ***
// **********************

int main()
{
  RBTnode *A, *B, *C, *D;
  int i, x;

  srand(time(NULL));

  // Tworzymy puste zbiory
  A = B = C = D = &S;
  // Do zbioru A dodajemy 10
  // losowych elementów
  for(i = 0; i < 10; i++)
    s_add(A, -20+(rand() % 41));
  // Do zbioru B dodajemy 15
  // losowych elementów
  for(i = 0; i < 15; i++)
    s_add(B, -20+(rand() % 41));
  // Wyświetlamy je
  cout << "A:" << endl;
  s_print(A);
  cout << endl << "SIZE OF A IS "
       << s_size(A) << endl
       << endl << "B:" << endl;
  s_print (B);
  cout << endl << "SIZE OF B IS "
       << s_size(B) << endl << endl
  // Suma zbiorów
       << "UNION OF A AND B:" << endl;
  s_union(A, B, C);
  s_print(C);
  cout << endl << "SIZE OF UNION IS "
       << s_size(C) << endl << endl
  // Iloczyn zbiorów
       << "INTERSECTION OF A AND B:" << endl;
  s_intersection(A, B, C);
  s_print(C);
  cout << endl << "SIZE OF INTERSECTION IS "
       << s_size(C) << endl << endl
  // Różnica zbiorów
       << "DIFFERENCE OF A AND B:" << endl;
  s_difference(A, B, C);
  s_print(C);
  cout << endl << "SIZE OF DIFFERENCE IS "
       << s_size(C) << endl << endl;
  // Podzbiór
  // Kopiujemy A do C
  s_union(A, A, C);
  // Usuwamy 7 elementów
  for(i = 0; i < 7; i++)
    s_remove(C, -20+(rand() % 41));
  cout << "IS:" << endl;
  s_print(C);
  cout << " SUBSET OF A?" << endl
       << (s_subset(C, A) ? "YES": "NO")
       << endl << endl;
  s_difference(B, A, C);
  // Usuwamy 12 elementów
  for(i = 0; i < 12; i++)
    s_remove(C, -20+(rand() % 41));
  cout << "IS:" << endl;
  s_print(C);
  cout << " SUBSET OF A?" << endl
       << (s_subset(C, A) ? "YES": "NO")
       << endl << endl
  // Usuwanie
       << "FROM A WE REMOVE";
  for(i = 0; i < 5; i++)
  {
    x = -20+(rand() % 41);
    cout << setw(4) << x;
    s_remove(A, x);
  }
  cout << endl << "A:" << endl;
  s_print(A);
  cout << endl << "SIZE OF A IS "
       << s_size(A) << endl << endl;
  // Sprawdzamy obecność wybranych
  // elementów w B
  for(i = 0; i < 10; i++)
  {
    x = -20+(rand() % 41);
    cout << "IS ELEMENT" << setw(4)
         << x << " IN SET B? "
         << (s_isin(B, x) ? "YES": "NO")
         << endl;
  }
  // Sprawdzenie testu na zbiór pusty
  cout << endl << "IS SET A EMPTY?" << endl
       << (s_empty(A) ? "YES": "NO")
       << endl << endl
       << "IS INTERSECTION OF A AND DIFFERENCE"
          " OF B AND A EMPTY?" << endl;
  s_difference(B, A, C);
  s_intersection(A, C, D);
  cout << (s_empty(D) ? "YES": "NO")
       << endl << endl;
  // Usuwamy tablice dynamiczne w zbiorach
  s_clear(A);
  s_clear(B);
  s_clear(C);
  s_clear(D);
  return 0;
}
Basic
' Zbiory zaimplementowane
' w drzewach czerwono-czarnych
' Data: 9.07.2014
' (C)2014 mgr Jerzy Wałaszek
'-----------------------------

' Definicja węzła drzewa czerwono-czarnego
Type RBTnode
  up    As RBTnode Ptr
  left  As RBTnode Ptr
  right As RBTnode Ptr
  key   As Integer
  color As String * 1
End Type

' Zmienne globalne

Dim Shared As RBTnode S _
    => (@S, @S, @S, 0, "B")

' Procedury obsługi drzew czerwono-czarnych

' Wykonuje rotację w lewo względem A
'-----------------------------------
Sub rot_L(ByRef root As RBTnode Ptr, _
          ByVal A As RBTnode Ptr)

  Dim As RBTnode Ptr B, p

  B = A->Right
  If B <> @S Then
    p = A->up
    A->right = B->Left
    If A->right <> @S then _
      A->right->up = A
    B->left = A
    B->up = p
    A->up = B
    If p <> @S Then
      If p->left = A then
        p->left = B
      Else
        p->right = B
      End If
    Else
      root = B
    End If
  End If
End Sub

' Wykonuje rotację w prawo względem A
'------------------------------------
Sub rot_R(ByRef root As RBTnode Ptr, _
          ByVal A As RBTnode Ptr)

  Dim As RBTnode Ptr B, p

  B = A->Left
  If B <> @S Then
    p = A->up
    A->left = B->Right
    If A->left <> @S Then _
      A->left->up = A
    B->right = A
    B->up = p
    A->up = B
    If p <> @S Then
      If p->left = A Then
        p->left = B
      Else
        p->right = B
      End If
    Else
      root = B
    End If
  End If
End Sub

' Wstawia do drzewa węzeł o kluczu k
'-----------------------------------
Sub insert_rbt(ByRef root As RBTnode Ptr, _
               ByVal k As Integer)

  Dim As RBTnode Ptr X, Y

  X = new RBTnode  ' Tworzymy nowy węzeł
  X->left  = @S    ' Inicjujemy pola
  X->right = @S
  X->up    = root
  X->key   = k
  If X->up = @S Then
  	  root = X ' X staje się korzeniem
  Else
    ' Szukamy liścia do zastąpienia przez X
    Do
      If k < X->up->key Then
        If X->up->left = @S Then
          ' X zastępuje lewy liść
          X->up->left = X
          Exit Do
        End If
        X->up = X->up->Left
      Else
        If X->up->right = @S Then
          ' X zastępuje prawy liść
          X->up->right = X
          Exit Do
        End If
        X->up = X->up->Right
      End If
    Loop
  End If
  ' Węzeł kolorujemy na czerwono
  X->color = "R"
   While (X <> root) AndAlso _
         (X->up->color = "R")
    If X->up = X->up->up->Left Then
      Y = X->up->up->Right ' Y -> wujek X
      If Y->color = "R" Then ' Przypadek 1
        X->up->color = "B"
        Y->color = "B"
        X->up->up->color = "R"
        X = X->up->up
        Continue While
      End If
      If X = X->up->Right Then ' Przypadek 2
        X = X->up
        rot_L(root, X)
      End If
      X->up->color = "B" ' Przypadek 3
      X->up->up->color = "R"
      rot_R(root, X->up->up)
      Exit While
    Else ' Przypadki lustrzane
      Y = X->up->up->Left
      If Y->color = "R" Then ' Przypadek 1
        X->up->color = "B"
        Y->color = "B"
        X->up->up->color = "R"
        X = X->up->up
        Continue While
      End If
      if X = X->up->Left Then ' Przypadek 2
        X = X->up
        rot_R(root, X)
      End If
      X->up->color = "B" ' Przypadek 3
      X->up->up->color = "R"
      rot_L(root, X->up->up)
      Exit While
    End If
  Wend
  root->color = "B"
End Sub

' Wyszukuje najmniejszy węzeł w poddrzewie
' o korzeniu p
'-----------------------------------------
Function min_rbt(ByVal p As RBTnode Ptr) _
                         As RBTnode Ptr
  If p <> @S Then
    While p->left <> @S
      p = p->Left
    Wend
  End If
  Return p
End Function

' Zwraca następnik p
'-------------------
Function succ_rbt(ByVal p As RBTnode Ptr) _
                          As RBTnode Ptr
  Dim As RBTnode Ptr r

  If p <> @S Then
    If p->right <> @S Then
      Return min_rbt(p->right)
    Else
      r = p->up
      while (r <> @S) AndAlso (p = r->right)
        p = r
        r = r->up
      Wend
      Return r
    End If
  End If
  Return @S
End Function

' Usuwa z drzewa węzeł X
'-----------------------
Sub remove_rbt(ByRef root As RBTnode Ptr, _
                  ByVal X As RBTnode Ptr)

  Dim As RBTnode Ptr W, Y, Z

  If (X->left = @S) OrElse _
     (X->right = @S) Then
    Y = X
  Else
    Y = succ_rbt(X)
  End If
  If Y->left <> @S Then
    Z = Y->Left
  Else
    Z = Y->Right
  End If
  Z->up = Y->up
  If Y->up = @S Then
    root = Z
  ElseIf Y = Y->up->Left Then
    Y->up->Left = Z
  Else
    Y->up->right = Z
  End If
  If Y <> X Then X->key = Y->key

  ' Naprawa struktury drzewa
  ' czerwono-czarnego
  If Y->color = "B" Then
    While (Z <> root) AndAlso _
          (Z->color = "B")
      If Z = Z->up->Left Then
        W = Z->up->Right
        ' Przypadek 1
        If W->color = "R" Then
          W->color = "B"
          Z->up->color = "R"
          rot_L(root, Z->up)
          W = Z->up->Right
        End If
        ' Przypadek 2
        If (W->left->color = "B") AndAlso _
           (W->right->color = "B") Then
          W->color = "R"
          Z = Z->up
          Continue While
        End If
        ' Przypadek 3
        If W->right->color = "B" Then
          W->left->color = "B"
          W->color = "R"
          rot_R(root, W)
          W = Z->up->Right
        End If
        ' Przypadek 4
        W->color = Z->up->Color
        Z->up->color = "B"
        W->right->color = "B"
        rot_L(root, Z->up)
        ' To spowoduje zakończenie pętli
        Z = root
      Else ' Przypadki lustrzane
        W = Z->up->Left
        ' Przypadek 1
        If W->color = "R" Then
          W->color = "B"
          Z->up->color = "R"
          rot_R(root, Z->up)
          W = Z->up->Left
        End If
        ' Przypadek 2
        If (W->left->color = "B") AndAlso _
           (W->right->color = "B") Then
          W->color = "R"
          Z = Z->up
          Continue While
        End If
        ' Przypadek 3
        If W->left->color = "B" Then
          W->right->color = "B"
          W->color = "R"
          rot_L(root, W)
          W = Z->up->Left
        End If
        ' Przypadek 4
        W->color = Z->up->Color
        Z->up->color = "B"
        W->left->color = "B"
        rot_R(root, Z->up)
        ' To spowoduje zakończenie pętli
        Z = root
      End If
    Wend
  End If
  Z->color = "B"
  Delete Y
End Sub

' Procedury obsługi zbioru

' Szuka w drzewie węzła o danej wartości
' klucza x. Jeśli węzeł zostanie znaleziony,
' to zwraca jego adres. Inaczej zwraca
' wskazanie puste.
'-------------------------------------------
Function s_isin(ByVal A As RBTnode Ptr, _
                ByVal x As Integer) _
                        As RBTnode Ptr
  While A <> @S
    ' Węzeł znaleziony
    If A->key = x Then Return A
    If x < A->key Then
      A = A->Left
    Else
      A = A->Right
    End If
  Wend
  Return 0 ' Węzeł nieznaleziony
End Function

' Dodaje do drzewa nowy węzeł,
' jesli w drzewie takiego węzła
' jeszcze nie ma
'------------------------------
Sub s_add(ByRef A As RBTnode Ptr, _
          ByVal x As Integer)
  If s_isin(A, x) = 0 Then insert_rbt(A, x)
End Sub

' Wyszukuje w drzewie węzeł o kluczu x
' i usuwa go
'-------------------------------------
Sub s_remove(ByRef A As RBTnode Ptr, _
             ByVal x As Integer)
  ' Szukamy węzła o kluczu x
  Dim As RBTnode Ptr p = s_isin (A, x)
  If p Then remove_rbt(A, p)
End Sub

' Usuwa wszystkie węzły z drzewa
'-------------------------------
Sub s_clear(ByRef A As RBTnode Ptr)
  If A <> @S Then
    ' Rekurencyjnie usuwamy lewe poddrzewo
    s_clear(A->left)
    ' Rekurencyjnie usuwamy prawe poddrzewo
    s_clear(A->right)
    Delete A ' Usuwamy węzeł
    A = @S
  End If
End Sub

' Procedura kopiuje elementy z drzewa A do C
'-------------------------------------------
Sub s_copy(Byval A As RBTnode Ptr, _
           ByRef C As RBTnode Ptr)
  If A <> @S Then
    ' Dodajemy do C klucz bieżącego węzła
    s_add(C, A->key)
    ' Rekurencyjnie dodajemy do C
    ' lewe poddrzewo
    s_copy(A->left, C)
    ' Rekurencyjnie dodajemy do C
    ' prawe poddrzewo
    s_copy(A->right, C)
  End If
End Sub

' Procedura tworzy sumę zbiorów A i B w C
'----------------------------------------
Sub s_union(ByVal A As RBTnode Ptr, _
            ByVal B As RBTnode Ptr, _
            ByRef C As RBTnode Ptr)
  s_clear(C) ' Czyścimy C
  s_copy(A, C) ' W C umieszczamy A
  s_copy(B, C) ' Dodajemy B do C
End Sub

' Procedura kopiuje do C te elementy A,
' które również są w B
'--------------------------------------
Sub s_icopy(ByVal A As RBTnode Ptr, _
            ByVal B As RBTnode Ptr, _
            ByRef C As RBTnode Ptr)
  If A <> @S Then
    If s_isin(B, A->key) Then _
      s_add(C, A->key)
    s_icopy(A->left, B, C)
    s_icopy(A->right, B, C)
  End If
End Sub

' Procedura tworzy w C iloczyn zbiorów A i B
'-------------------------------------------
Sub s_intersection(ByVal A As RBTnode Ptr, _
                   ByVal B As RBTnode Ptr, _
                   ByRef C As RBTnode Ptr)
  ' Czyścimy C
  s_clear(C)
  ' Tworzymy iloczyn zbiorów
  s_icopy(A, B, C)
End Sub

' Procedura kopiuje do C te elementy A,
' których nie ma w B
'--------------------------------------
Sub s_dcopy(ByVal A As RBTnode Ptr, _
            ByVal B As RBTnode Ptr, _
            ByRef C As RBTnode Ptr)
  If A <> @S Then
    If s_isin(B, A->key) = 0 Then _
      s_add(C, A->key)
    s_dcopy(A->left, B, C)
    s_dcopy(A->right, B, C)
  End If
End Sub

' Procedura tworzy w C różnicę zbiorów A i B
'-------------------------------------------
Sub s_difference(ByVal A As RBTnode Ptr, _
                 ByVal B As RBTnode Ptr, _
                 ByRef C As RBTnode Ptr)
  ' Czyścimy C
  s_clear(C)
  ' Tworzymy różnicę zbiorów
  s_dcopy(A, B, C)
End Sub

' Funkcja zwraca true, jeśli zbiór A
' jest podzbiorem B
' Inaczej zwraca false
'-----------------------------------
Function s_subset(ByVal A As RBTnode Ptr, _
                  ByVal B As RBTnode Ptr) _
                          As Integer
  If A = @S Then Return -1
  If s_isin(B, A->key) = 0  Then Return 0
  Return s_subset(A->left, B) AndAlso _
         s_subset(A->right, B)
End Function

' Procedura zlicza rekurencyjnie węzły
' w drzewie
'-------------------------------------
Sub s_cnt(ByVal A As RBTnode Ptr, _
          ByRef cnt As Integer)
  If A <> @S Then
    ' Zliczamy węzeł bieżący
    cnt += 1
    ' Rekurencyjnie liczymy węzły
    ' w lewym poddrzewie
    s_cnt(A->left, cnt)
    ' Rekurencyjnie liczymy węzły
    ' w prawym poddrzewie
    s_cnt(A->right, cnt)
  End If
End Sub

' Funkcja oblicza liczbę węzłów w drzewie
'----------------------------------------
Function s_size(ByVal A As RBTnode Ptr) _
                        As Integer
  ' Zerujemy licznik
  Dim As Integer cnt = 0
  s_cnt(A, cnt) ' Zliczamy węzły
  Return cnt ' Zwracamy wynik
End Function

' Funkcja zwraca true,
' jeśli zbiór jest pusty
'-----------------------
Function s_empty(ByVal A As RBTnode Ptr) _
                         As Integer
  Return A = @S
End Function

' Procedura rekurencyjnie wyświetla
' zawartość drzewa
'----------------------------------
Sub s_print(byval A As RBTnode Ptr)
  If A <> @S Then
    s_print(A->left)
    Print Using "& ";A->key;
    s_print(A->right)
  End If
End Sub

' **********************
' *** PROGRAM GŁÓWNY ***
' **********************

Dim As RBTnode Ptr A, B, C, D
Dim As Integer i, x

Randomize
' Tworzymy puste zbiory
A = @S
B = @S
C = @S
D = @S
' Do zbioru A dodajemy
' 10 losowych elementów
For i = 1 To 10
  s_add(A, -20+Int(rnd()*41))
Next
' Do zbioru B dodajemy
' 15 losowych elementów
For i = 1 To 15
  s_add(B, -20+Int(Rnd()*41))
Next
' Wyświetlamy je
Print "A:"
s_print(A): Print
Print "SIZE OF A IS";s_size(A)
Print
Print "B:"
s_print(B): Print
Print "SIZE OF B IS";s_size(B)
Print
' Suma zbiorów
Print "UNION OF A AND B:"
s_union(A, B, C)
s_print(C): Print
Print "SIZE OF UNION IS";s_size(C)
Print
' Iloczyn zbiorów
Print "INTERSECTION OF A AND B:"
s_intersection(A, B, C)
s_print(C): Print
Print "SIZE OF INTERSECTION IS";s_size(C)
Print
' Różnica zbiorów
Print "DIFFERENCE OF A AND B:"
s_difference(A, B, C)
s_print(C): Print
Print "SIZE OF DIFFERENCE IS";s_size(C)
Print
' Podzbiór
' Kopiujemy A do C
s_union(A, A, C)
' Usuwamy 7 elementów
For i = 1 To 7
  s_remove(C, -20+Int(Rnd()*41))
Next
Print "IS:";
s_print(C)
Print " SUBSET OF A?"
If s_subset(C, A) Then
  Print "YES"
Else
  Print "NO"
End If
Print
s_difference(B, A, C)
' Usuwamy 12 elementów
For i = 1 To 12
  s_remove(C, -20+Int(Rnd()*41))
Next
Print "IS:"
s_print(C)
Print " SUBSET OF A?"
If s_subset(C, A) Then
  Print "YES"
Else
  Print "NO"
End If
Print
' Usuwanie
Print "FROM A WE REMOVE";
For i = 1 To 5
  x = -20+Int(Rnd()*41)
  Print Using "& ";x;
  s_remove(A, x)
Next
Print
Print "A:"
s_print(A): Print
Print "SIZE OF A IS";s_size(A)
Print
' Sprawdzamy obecność wybranych
' elementów w B
For i = 1 To 10
  x = -20+Int(Rnd()*41)
  Print Using "IS ELEMENT#### IN SET B? ";x;
  If s_isin(B, x) Then
  	 Print "YES"
  Else
  	 Print "NO"
  End If
Next
Print
' Sprawdzenie testu na zbiór pusty
Print "IS SET A EMPTY?"
If s_empty(A) Then
  Print "YES"
Else
  Print "NO"
End If
Print
Print "IS INTERSECTION OF A AND " + _
      "DIFFERENCE OF B AND A EMPTY?"
s_difference(B, A, C)
s_intersection(A, C, C)
If s_empty(C) Then
  Print "YES"
Else
  Print "NO"
End If
Print
' Usuwamy zbiory
s_clear(A)
s_clear(B)
s_clear(C)
s_clear(D)
End
Python (dodatek)
# Zbiory zaimplementowane
# w drzewach czerwono-czarnych
# Data 22.09.2024
# (C)2024 mgr Jerzy Wałaszek
#-----------------------------

import random

# klasa węzłów drzewa
class RBTnode:


    # Konstruktor
    def __init__(self, k, c):
        self.up = None
        self.left = None
        self.right = None
        self.key = k
        self.color = c


# klasa drzewa czerwono-czarnego
class RBtree:


    # Konstruktor
    def __init__(self):
        # Inicjujemy strażnika
        self.s = RBTnode(0, 'B')
        self.s.up = self.s
        self.s.left = self.s
        self.s.right = self.s
        # Korzeń wskazuje strażnika
        self.root = self.s


    # wykonuje rotację w lewo względem A
    def rot_l(self, a):
        b = a.right
        if b is not self.s:
            p = a.up
            a.right = b.left
            if a.right is not self.s:
                a.right.up = a
            b.left = a
            b.up = p
            a.up = b
            if p is not self.s:
                if p.left is a:
                    p.left = b
                else:
                    p.right = b
            else:
                self.root = b


    # wykonuje rotację w prawo względem A
    def rot_r(self, a):
        b = a.left
        if b is not self.s:
            p = a.up
            a.left = b.right
            if a.left is not self.s:
                a.left.up = a
            b.right = a
            b.up = p
            a.up = b
            if p is not self.s:
                if p.left is a:
                    p.left = b
                else:
                    p.right = b
            else:
                self.root = b


    # wstawia węzeł o kluczu k
    def insert_rbt(self, k):
        # Tworzymy nowy węzeł
        x = RBTnode(k, "")
        # Inicjujemy pola
        x.left = self.s
        x.right = self.s
        x.up = self.root
        if x.up is self.s:
            # X staje się korzeniem
            self.root = x
        else:
            # szukamy liścia
            # do zastąpienia przez X
            while True:
                if k < x.up.key:
                    if x.up.left is self.s:
                        # X zastępuje lewy liść
                        x.up.left = x
                        break
                    x.up = x.up.left
                else:
                    if x.up.right is self.s:
                        # X zastępuje prawy liść
                        x.up.right = x
                        break
                    x.up = x.up.right
        # węzeł kolorujemy na czerwono
        x.color = "R"
        while x is not self.root and \
                x.up.color == "R":
            if x.up is x.up.up.left:
                # Y -> wujek X
                y = x.up.up.right
                if y.color == "R":
                    # Przypadek 1
                    x.up.color = "B"
                    y.color = "B"
                    x.up.up.color = "R"
                    x = x.up.up
                    continue
                if x is x.up.right:
                    # Przypadek 2
                    x = x.up
                    self.rot_l(x)
                # Przypadek 3
                x.up.color = "B"
                x.up.up.color = "R"
                self.rot_r(x.up.up)
                break
            else:
                # Przypadki lustrzane
                y = x.up.up.left
                if y.color == "R":
                    # Przypadek 1
                    x.up.color = "B"
                    y.color = "B"
                    x.up.up.color = "R"
                    x = x.up.up
                    continue
                if x is x.up.left:
                    # Przypadek 2
                    x = x.up
                    self.rot_r(x)
                # Przypadek 3
                x.up.color = "B"
                x.up.up.color = "R"
                self.rot_l(x.up.up)
                break
        self.root.color = "B"

    # wyszukuje najmniejszy
    # węzeł w poddrzewie
    # o korzeniu p
    def min_rbt(self, p):
        if p is not self.s:
            while p.left is not self.s:
                p = p.left
        return p


    # zwraca następnik p
    def succ_rbt(self, p):
        if p is not self.s:
            if p.right is not self.s:
                return self.min_rbt(p.right)
            else:
                r = p.up
                while r is not self.s and \
                        p == r.right:
                    p = r
                    r = r.up
                return r
        return self.s


    # usuwa węzeł X
    def remove_rbt(self, x):
        if x.left is self.s or \
                x.right is self.s:
            y = x
        else:
            y = self.succ_rbt(x)
        if y.left is not self.s:
            z = y.left
        else:
            z = y.right
        z.up = y.up
        if y.up is self.s:
            self.root = z
        elif y is y.up.left:
            y.up.left = z
        else:
            y.up.right = z
        if y is not x:
            x.key = y.key
        if y.color == "B":
            # Naprawa struktury
            # drzewa czerwono-czarnego
            while z is not self.root and \
                    z.color == "B":
                if z is z.up.left:
                    w = z.up.right
                    if w.color == "R":
                        # Przypadek 1
                        w.color = "B"
                        z.up.color = "R"
                        self.rot_l(z.up)
                        w = z.up.right
                    if w.left.color == "B" and \
                            w.right.color == "B":
                        # Przypadek 2
                        w.color = "R"
                        z = z.up
                        continue
                    if w.right.color == "B":
                        # Przypadek 3
                        w.left.color = "B"
                        w.color = "R"
                        self.rot_r(w)
                        w = z.up.right
                    # Przypadek 4
                    w.color = z.up.color
                    z.up.color = "B"
                    w.right.color = "B"
                    self.rot_l(z.up)
                    # To spowoduje zakończenie pętli
                    z = self.root
                else:
                    # Przypadki lustrzane
                    w = z.up.left
                    if w.color == "R":
                        # Przypadek 1
                        w.color = "B"
                        z.up.color = "R"
                        self.rot_r(z.up)
                        w = z.up.left
                    if w.left.color == "B" and \
                            w.right.color == "B":
                        # Przypadek 2
                        w.color = "R"
                        z = z.up
                        continue
                    if w.left.color == "B":
                        # Przypadek 3
                        w.right.color = "B"
                        w.color = "R"
                        self.rot_l(w)
                        w = z.up.left
                    # Przypadek 4
                    w.color = z.up.color
                    z.up.color = "B"
                    w.left.color = "B"
                    self.rot_r(z.up)
                    # To spowoduje zakończenie pętli
                    z = self.root
        z.color = "B"


    # wyszukuje węzeł o kluczu k
    # jeśli węzeł nie zostanie
    # znaleziony, to zwraca
    # wskazanie puste None
    def s_isin(self, k):
        p = self.root
        while p is not self.s and \
                p.key != k:
            if k < p.key:
                p = p.left
            else:
                p = p.right
        if p is self.s:
            return None
        return p


    # dodaje do drzewa nowy węzeł,
    # jesli w drzewie takiego węzła
    # jeszcze nie ma
    def s_add(self, x):
        if not self.s_isin(x):
            self.insert_rbt(x)


    # wyszukuje w drzewie węzeł
    # o kluczu x i usuwa go
    def s_remove(self, x):
        # Szukamy węzła o kluczu x
        p = self.s_isin(x)
        if p:
            self.remove_rbt(p)


    # usuwa wszystkie węzły z drzewa
    def s_clear(self):
        self.root = self.s


    # kopiuje elementy z drzewa A
    def s_copy(self, a, x):
        if x is not a.s:
            # Dodajemy klucz bieżącego węzła
            self.s_add(x.key)
            # Rekurencyjnie dodajemy
            # lewe poddrzewo
            self.s_copy(a, x.left)
            # Rekurencyjnie dodajemy
            # prawe poddrzewo
            self.s_copy(a, x.right)


    # tworzy sumę zbiorów A i B
    def s_union(self, a, b):
        self.s_clear() # Czyścimy
        self.s_copy(a, a.root) # umieszczamy A
        self.s_copy(b, b.root) # dodajemy B


    # kopiuje elementy A,
    # które również są w B
    def s_icopy(self, a, x, b):
        if x is not a.s:
            if b.s_isin(x.key):
                self.s_add(x.key)
            self.s_icopy(a, x.left, b)
            self.s_icopy(a, x.right, b)


    # tworzy iloczyn zbiorów A i B
    def s_intersection(self, a, b):
        # Czyścimy
        self.s_clear()
        # Tworzymy iloczyn zbiorów
        self.s_icopy(a, a.root, b)


    # kopiuje te elementy A,
    # których nie ma w B
    def s_dcopy(self, a, x, b,):
        if x is not a.s:
            if not b.s_isin(x.key):
                self.s_add(x.key)
            self.s_dcopy(a, x.left, b)
            self.s_dcopy(a, x.right, b)


    # tworzy różnicę zbiorów A i B
    def s_difference(self, a, b):
        # Czyścimy
        self.s_clear()
        # Tworzymy różnicę zbiorów
        self.s_dcopy(a, a.root, b)


    # zwraca true, jeśli zbiór A
    # jest podzbiorem zbioru
    # Inaczej zwraca false
    def s_scopy(self, a, x):
        if x is a.s:
            return True
        if not self.s_isin(x.key):
            return False
        return self.s_scopy(a, x.left) and \
               self.s_scopy(a, x.right)


    # zwraca true, jeśli zbiór A
    # jest podzbiorem
    # Inaczej zwraca false
    def s_subset(self, a):
        return self.s_scopy(a, a.root)


    # zlicza rekurencyjnie węzły w drzewie
    def s_cnt(self, x, cnt):
        if x is not self.s:
            cnt += 1
            # Rekurencyjnie liczymy węzły
            # w lewym poddrzewie
            cnt = self.s_cnt(x.left, cnt)
            # Rekurencyjnie liczymy węzły
            # w prawym poddrzewie
            cnt = self.s_cnt(x.right, cnt)
        return cnt


    # oblicza liczbę węzłów w drzewie
    def s_size(self):
        # Zliczamy węzły i zwracamy
        return self.s_cnt(self.root, 0)


    # zwraca true, zbiór jest pusty
    def s_empty(self):
        return self.root is self.s


    # rekurencyjnie wyświetla
    # zawartość drzewa
    def s_print_rbt(self, x):
        if x is not self.s:
            self.s_print_rbt(x.left)
            print(x.key, end=" ")
            self.s_print_rbt(x.right)


    def s_print(self):
        self.s_print_rbt(self.root)

# **********************
# *** PROGRAM GŁÓWNY ***
# **********************

a = RBtree()
b = RBtree()
c = RBtree()
# Do zbioru A dodajemy 10 losowych elementów
for i in range(10):
    a.s_add(random.randrange(-20,21))
# Do zbioru B dodajemy 15 losowych elementów
for i in range(15):
    b.s_add(random.randrange(-20,21))
# Wyświetlamy je
print("A:")
a.s_print()
print()
print("SIZE OF A IS", a.s_size())
print()
print("B:")
b.s_print()
print()
print("SIZE OF B IS", b.s_size())
print()
# Suma zbiorów
print("UNION OF A AND B:")
c.s_union(a, b)
c.s_print()
print()
print("SIZE OF UNION IS", c.s_size())
print()
# Iloczyn zbiorów
print("INTERSECTION OF A AND B:")
c.s_intersection(a, b)
c.s_print()
print()
print("SIZE OF INTERSECTION IS", c.s_size())
print()
# Różnica zbiorów
print("DIFFERENCE OF A AND B:")
c.s_difference(a, b)
c.s_print()
print()
print("SIZE OF DIFFERENCE IS", c.s_size())
print()
# Podzbiór
# Kopiujemy A
c.s_union(a, a)
# Usuwamy 7 elementów
for i in range(7):
    c.s_remove(random.randrange(-20,21))
print("IS:", end=" ")
c.s_print()
print(" SUBSET OF A?")
if a.s_subset(c):
    print("YES")
else:
    print("NO")
print()
c.s_difference(b, a)
# Usuwamy 12 elementów
for i in range(12):
  c.s_remove(random.randrange(-20,21))
print("IS:", end=" ")
c.s_print()
print(" SUBSET OF A?")
if a.s_subset(c):
    print("YES")
else:
    print("NO")
print()
# Usuwanie
print("FROM A WE REMOVE", end=" ")
for i in range(5):
    x = random.randrange(-20,21)
    print(x, end=" ")
    a.s_remove(x)
print()
print("A:")
a.s_print()
print()
print("SIZE OF A IS", a.s_size())
print()
# Sprawdzamy obecność wybranych
# elementów w B
for i in range(10):
    x = random.randrange(-20, 21)
    print("IS ELEMENT%4d IN SET B? " % x, end="")
    if b.s_isin(x):
        print("YES")
    else:
        print("NO")
print()
# Sprawdzenie testu na zbiór pusty
print("IS SET A EMPTY?")
if a.s_empty():
    print("YES")
else:
    print("NO")
print()
print("IS INTERSECTION OF A AND " +
      "DIFFERENCE OF B AND A EMPTY?")
c.s_difference(b, a)
c.s_intersection(a, c)
if c.s_empty():
    print("YES")
else:
    print("NO")
print()
# Usuwamy zbiory
a.s_clear()
b.s_clear()
c.s_clear()
Wynik:
A:
-19 -13 -10 -1 5 6 9 11 14
SIZE OF A IS 9

B:
-19 -17 -11 -10 -8 0 2 6 7 15 17 18
SIZE OF B IS 12

UNION OF A AND B:
-19 -17 -13 -11 -10 -8 -1 0 2 5 6 7 9 11 14 15 17 18
SIZE OF UNION IS 18

INTERSECTION OF A AND B:
-19 -10 6
SIZE OF INTERSECTION IS 3

DIFFERENCE OF A AND B:
-13 -1 5 9 11 14
SIZE OF DIFFERENCE IS 6

IS:-19 -10 -1 5 6 9 SUBSET OF A?
YES

IS:
-11 2 7 15 17 18 SUBSET OF A?
NO

FROM A WE REMOVE-3 -11 11 6 6
A:
-19 -13 -10 -1 5 9 14
SIZE OF A IS 7

IS ELEMENT -2 IN SET B? NO
IS ELEMENT 10 IN SET B? NO
IS ELEMENT 19 IN SET B? NO
IS ELEMENT -20 IN SET B? NO
IS ELEMENT 9 IN SET B? NO
IS ELEMENT -5 IN SET B? NO
IS ELEMENT 18 IN SET B? YES
IS ELEMENT 4 IN SET B? NO
IS ELEMENT 3 IN SET B? NO
IS ELEMENT 2 IN SET B? YES

IS SET A EMPTY?
NO

IS INTERSECTION OF A AND DIFFERENCE OF B AND A EMPTY?
YES

do podrozdziału  do strony 

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: i-lo@eduinf.waw.pl
Serwis wykorzystuje pliki cookies. Jeśli nie chcesz ich otrzymywać, zablokuj je w swojej przeglądarce.

Informacje dodatkowe.