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 na listach

SPIS TREŚCI
Tematy pomocnicze

Rozwiązanie

Do przechowywania elementów zbioru zostanie użyta lista jednokierunkowa. Na liście elementy są umieszczone w dowolnej kolejności. Każdy element może pojawić się na liście tylko jeden raz. Reprezentacja listowa oszczędza pamięć, jednak jest bardzo nieefektywna. Podajemy ją jedynie dla celów dydaktycznych.

Algorytmy operacji dla zbiorów reprezentowanych listami jednokierunkowymi

s_isin(A, x) – zwraca true, jeśli element o wartości x znajduje się na liście A. Inaczej zwraca false.

Algorytm przegląda listę A i jeśli znajdzie na niej element o wartości x, zwraca true. W przeciwnym razie zwraca false

Wejście:

A : wskaźnik początku listy jednokierunkowej.
x : wartość poszukiwanego elementu.

Wyjście:

true : element x jest na liście A.
false : elementu x nie ma na liście A.

Elementy pomocnicze:

p : wskaźnik elementów listy jednokierunkowej.

Lista kroków:

K01 pA
K02 Dopóki p ≠ nil, ; przeglądamy listę A
    wykonuj kroki K03…K04
K03:   Jeśli pdata = x, ; jeśli trafimy na element o wartości x,
       to zakończ z wynikiem true ; kończymy
K04:   ppnext ; następny element listy A
K05: Zakończ z wynikiem false ; lista nie zawiera elementu o wartości x

s_add(A, x) – dodaje element x do listy A, jeśli jeszcze jego tam nie ma.

Algorytm najpierw sprawdza, czy lista A zawiera element x. Jeśli tak, to kończy działanie. Jeśli nie, to wstawia nowy element o wartości x na początku listy.

Wejście:

A : referencja do wskaźnika początku listy jednokierunkowej.
x : wartość dodawanego elementu.

Wyjście:

Lista A z elementem o wartości x na początku, jeśli wcześniej elementu o takiej wartości na liście A nie było. W przeciwnym razie lista A nie jest modyfikowana.

Elementy pomocnicze:

p : wskaźnik elementów listy jednokierunkowej.
s_isin(Z, x) : funkcja zwraca true, jeśli lista Z zawiera element o wartości x, inaczej zwraca false.

Lista kroków:

K01: Jeśli s_isin(A, x) = true, ; sprawdzamy, czy lista A zawiera x.
     to zakończ ; Jeśli tak, kończymy
K02: Utwórz nowy element listy ; dodajemy element na początek listy A
K03: p ← adres nowego elementu
K04: pdatax
K05: pnextA
K06: Ap
K07: Zakończ

s_union(A, B, C) – zwraca listę zawierającą elementy list A i B. Elementy na liście wynikowej nie są dublowane.

Algorytm najpierw kopiuje do listy C wszystkie elementy listy A. Następnie przegląda kolejno elementy listy B i sprawdza, czy znajdują się one na liście A. Jeśli nie, to kopiuje te elementy do listy C. W efekcie lista C będzie zawierała wszystkie elementy A oraz wszystkie elementy B, które nie są równe elementom z A.

Wejście:

A, B : wskaźniki początków list jednokierunkowych.
C : referencja do wskaźnika początku listy jednokierunkowej. Wskaźnik C nie może wskazywać żadnej listy.

Wyjście:

Lista C zawiera elementy list A i B.

Elementy pomocnicze:

p : wskaźnik elementów listy jednokierunkowej.
s_isin(Z, x) : funkcja zwraca true, jeśli lista Z zawiera element o wartości x, inaczej zwraca false.
s_add(Z, x) : dodaje element x do listy Z, jeśli lista Z jeszcze nie zawiera elementu o wartości x.

Lista kroków:

K01: C ← nil ; tworzymy pustą listę wynikową
K02: pA
K03: Dopóki p ≠ nil, ; kopiujemy listę A do C
     wykonuj kroki K04…K05
K04:   s_add(C, pdata) ; kopiujemy element z A do C
K05:   ppnext ; następny element listy A
K06: pB ; teraz zajmiemy się listą B
K07: Dopóki p ≠ nil, 
     wykonuj kroki K08…K09
K08:   Jeśli s_isin(A, pdata) = false, ; jeśli lista A
       to s_add(C, pdata) ; nie zawiera elementu z B,
       ; to element z B kopiujemy do C
K09:   ppnext ; następny element listy B
K10: Zakończ

s_intersection(A, B, C) – zwraca listę zawierającą elementy, które znajdują się jednocześnie na liście A i na liście B.

Algorytm przegląda kolejne elementy listy A i sprawdza, czy znajdują się one na liście B. Jeśli tak, to elementy są kopiowane do listy C. W efekcie lista C będzie zawierała wszystkie elementy listy A, które są równe elementom listy B.

Wejście:

A, B : wskaźniki początków list jednokierunkowych.
C : referencja do wskaźnika początku listy jednokierunkowej. Wskaźnik C nie może wskazywać żadnej listy.

Wyjście:

Lista C zawiera te elementy listy A, które są jednocześnie elementami listy B.

Elementy pomocnicze:

p : wskaźnik elementów listy jednokierunkowej.
s_isin(Z, x) : funkcja zwraca true, jeśli lista Z zawiera element o wartości x, inaczej zwraca false.
s_add(Z, x) : dodaje element x do listy Z, jeśli lista Z jeszcze nie zawiera elementu o wartości x.

Lista kroków:

K01: C ← nil ; tworzymy pustą listę wynikową
K02: pA
K03: Dopóki p ≠ nil, ; przeglądamy listę A
     wykonuj kroki K04…K05
K04:   Jeśli s_isin(B, pdata) = true, ; sprawdzamy, czy lista B
       to s_add(C, pdata) ; zawiera element z A.
       ; Jeśli tak, kopiujemy
K05:   ppnext ; następny element listy A
K06: Zakończ

s_difference(A, B, C) – zwraca listę zawierającą wszystkie elementy listy A, które nie są równe elementom listy B.

Algorytm przegląda kolejne elementy listy A i sprawdza, czy znajdują się one na liście B. Jeśli nie, to elementy są kopiowane do listy C. W efekcie lista C będzie zawierała wszystkie elementy listy A, które są różne od elementów listy B.

Wejście:

A, B : wskaźniki początków list jednokierunkowych.
C : referencja do wskaźnika początku listy jednokierunkowej. Wskaźnik C nie może wskazywać żadnej listy.

Wyjście:

Lista C zawierająca elementy listy A, które nie są elementami listy B.

Elementy pomocnicze:

p : wskaźnik elementów listy jednokierunkowej.
s_isin(Z, x) : funkcja zwraca true, jeśli lista Z zawiera element o wartości x, inaczej zwraca false.
s_add(Z, x) : dodaje element x do listy Z, jeśli lista Z jeszcze nie zawiera elementu o wartości x.

Lista kroków:

K01: C ← nil ; tworzymy pustą listę wynikową
K02: pA
K03: Dopóki p ≠ nil, ; przeglądamy listę A
     wykonuj kroki K04…K05
K04:   Jeśli s_isin(B, pdata) = false, ; jeśli lista B nie zawiera
       to s_add(C, pdata) ; elementu z A, kopiujemy
K05:   ppnext ; następny element listy A
K06: Zakończ z wynikiem C

s_subset(A, B) – zwraca true, jeśli lista B zawiera wszystkie elementy listy A, inaczej zwraca false.

Algorytm przegląda kolejne elementy listy A i sprawdza, czy znajdują się one na liście B. Jeśli nie, to zwraca wartość false. W przeciwnym razie zwraca true.

Wejście:

A, B : wskaźniki początków list jednokierunkowych.

Wyjście:

true : lista B posiada wszystkie elementy listy A.
false : lista B nie posiada wszystkich elementów listy A.

Elementy pomocnicze:

p : wskaźnik elementów listy jednokierunkowej.
s_isin(Z, x) : funkcja zwraca true, jeśli lista Z zawiera element o wartości x, inaczej zwraca false.

Lista kroków:

K01: pA ; będziemy przeglądać listę A
K02: Dopóki p ≠ nil, 
     wykonuj kroki K03…K04
K03:   Jeśli s_isin(B, pdata) = false, ; sprawdzamy, czy lista B zawiera element z A.
       to zakończ z wynikiem false ; Jeśli nie, kończymy
K04:   ppnext ; następny element z listy A
K05: Zakończ z wynikiem true

s_size(A) – zwraca liczbę elementów na liście A

Algorytm przechodzi przez listę A zliczając kolejne elementy.

Wejście:

A : wskaźnik początku listy jednokierunkowej.

Wyjście:

Liczba elementów na liście A.

Elementy pomocnicze:

p : wskaźnik elementów listy jednokierunkowej.
c : licznik elementów.

Lista kroków:

K01: pA ; będziemy przeglądać listę A
K02: c ← 0 ; zerujemy licznik
K03: Dopóki p ≠ nil, 
     wykonuj kroki K03…K06
K04:   cc + 1 ; zwiększamy licznik
K05:   ppnext ; następny element listy A
K06: Zakończ z wynikiem c

s_remove(A, x) – usuwa element x z listy A, jeśli się tam znajduje

Algorytm sprawdza, czy lista jest pusta. Jeśli tak, to kończy. W przeciwnym razie sprawdza, czy poszukiwany element jest na początku listy. Jeśli tak, to go usuwa i modyfikuje odpowiednio wskazanie A. W przeciwnym razie szuka elementu na liście, utrzymując zawsze adres elementu poprzedzającego. Gdy znajdzie element, usuwa go z listy przez zmodyfikowanie elementu poprzedzającego, a następnie element usuwa z pamięci.

Wejście:

A : referencja do wskaźnika początku listy jednokierunkowej.
x : wartość usuwanego elementu.

Wyjście:

Lista A z usuniętym elementem o wartości x.

Elementy pomocnicze:

p, r : wskaźniki elementów listy jednokierunkowej.

Lista kroków:

K01: Jeśli A = nil, ; lista jest pusta, kończymy
     to zakończ
K02: p ← A ; zapamiętujemy adres początku listy
K03: Jeśli pdatax, ; sprawdzamy, czy usuwany element
     to idź do kroku K07 ; jest pierwszym na liście
K04: Apnext ; element usuwamy z listy
K05: Usuń element wskazywany przez p ; i z pamięci
K06: Zakończ
K07: Dopóki pnext ≠ nil obrazek pnextdatax:
     wykonuj: ppnext ; szukamy na liście A
     ; następnika równego x
K08: Jeśli pnext = nil, ; nie ma następnika równego x,
     to zakończ ; kończymy
K09: rpnext ; zapamiętujemy adres następnika
K10: pnext ← rnext ; następnik usuwamy z listy
K11: Usuń element wskazywany przez r ; i z pamięci
K12: Zakończ

s_clear(A) – usuwa wszystkie elementy z listy A.

Algorytm usuwa kolejne elementy listy, aż lista stanie się pusta.

Wejście:

A : referencja do wskaźnika początku listy jednokierunkowej.

Wyjście:

Pusta lista A.

Elementy pomocnicze:

p, r : wskaźniki elementów listy jednokierunkowej.

Lista kroków:

K01: pA ; ustawiamy p na początek listy A
K02: Dopóki p ≠ nil, ; przechodzimy przez kolejne elementy listy
     wykonuj kroki K03…K05
K03:   rp ; zapamiętujemy adres elementu
K04:   ppnext ; w p ustawiamy adres następnika
K05:   Usuń element wskazywany przez r
K06: A ← nil ; lista A staje się pusta
K07: Zakończ

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 listach jednokierunkowych. Wyjaśnienie wykonywanych operacji znajduje się w komentarzach wewnątrz programu.
Pascal
// Zbiory zaimplementowane
// na listach jednokierunkowych
// Data: 20.06.2014
// (C)2014 mgr Jerzy Wałaszek
//------------------------------

program sets;

// Definicja elementu
// listy jednokierunkowej
type
  PSLel = ^SLel;
  SLel = record
    // Następny element listy
    next : PSLel;
    // Wartość elementu listy
    Data: integer;
  end;

// Definicje funkcji obsługi
// list jako zbiorów
//--------------------------

// Funkcja sprawdza, czy x
// jest elementem zbioru A
// true  - jest
// false - nie jest
//------------------------
function s_isin(p : PSLel;
                x : integer)
                  : boolean;
begin
  // Przeglądamy kolejne elementy A
  while p <> nil do
  begin
    if p^.data = x then
      Exit(true);
    p := p^.next;
  end;
  s_isin := false;
end;

// Procedura dodaje na początek
// zbioru A element x, jeśli zbiór A
// nie zawiera jeszcze takiego elementu
//-------------------------------------
procedure s_add(var A : PSLel;
                    x : integer);
var
  p : PSLel;
begin
  // Jeśli elementu x nie ma w zbiorze A,
  // to go tam wstawiamy
  if not s_isin(A, x) then
  begin
    // Tworzymy nowy element listy
    new(p);
    // Wprowadzamy do niego dane
    p^.Data:= x;
    // Umieszczamy go na początku zbioru
    p^.next := A;
    A := p;
  end;
end;

// Procedura dokonuje połączenia
// zbiorów A i B.
// Wynik jest umieszczany w C
//------------------------------
procedure s_union(A, B : PSLel;
                 var C : PSLel);
var
  p : PSLel;
begin
  // Zerujemy zbiór wyjściowy
  C := nil;
  // Zbiór A kopiujemy do C
  p := A;
  while p <> nil do
  begin
    // Kopiujemy element z A do C
    s_add(C, p^.data);
    // Następny element z A
    p := p^.next;
  end;
  p := B;
  while p <> nil do
  begin
    // Teraz będziemy kopiować do C
    // te elementy z B, których nie ma
    // w A, aby ich nie zdublować
    if not s_isin(A, p^.data) then
      s_add(C, p^.data);
    // Następny element z B
    p := p^.next;
  end;
end;

// Procedura wyznacza część wspólną
// zbiorów A i B. Wynik w C
//---------------------------------
procedure s_intersection(p, B : PSLel;
                        var C : PSLel);
begin
  // Zerujemy zbiór C
  C := nil;
  // Przeglądamy kolejne elementy zbioru A
  while p <> nil do
  begin
    // Jeśli element jest w B, kopiujemy
    if s_isin(B, p^.data) then
      s_add(C, p^.data);
    // Następny element z A
    p := p^.next;
  end;
end;

// Procedura wyznacza różnicę
// zbiorów A i B. Wynik w C
//---------------------------
procedure s_difference(p, B : PSLel;
                      var C : PSLel);
begin
  // Zerujemy zbiór C
  C := nil;
  // Przeglądamy kolejne elementy zbioru A
  while p <> nil do
  begin
    // Jeśli elementu nie ma w B, kopiujemy
    if not s_isin(B, p^.data) then
      s_add(C, p^.data);
    // Następny element z A
    p := p^.next;
  end;
end;

// Funkcja sprawdza, czy zbiór
// B zawiera podzbiór A
// true  - tak
// false - nie
//----------------------------
function s_subset(p, B : PSLel)
                       : boolean;
begin
  // Przeglądamy zbiór A
  while p <> nil do
  begin
    // Jeśli elementu z A nie ma w B, kończymy
    if not s_isin(B, p^.data) then
      Exit(false);
    // Następny element z A
    p := p^.next;
  end;
  // Wszystkie elementy A są w B
  s_subset := true;
end;

// Funkcja oblicza liczebność zbioru
//----------------------------------
function s_size(p : PSLel) : integer;
var
  c : integer;
begin
  // Zerujemy licznik
  c := 0;
  // Przechodzimy przez elementy zbioru p
  while p <> nil do
  begin
    // Elementy zliczamy w c
    inc(c);
    // Następny element z p
    p := p^.next;
  end;
  s_size := c;
end;

// Procedura usuwa element x ze zbioru
//------------------------------------
procedure s_remove(var A : PSLel;
                       x : integer);
var
  p, r : PSLel;
begin
  // Zbiór nie może być pusty
  if A <> nil then
  begin
    // Zapamiętujemy adres początku zbioru
    p := A;
    // Jeśli usuwany element jest na początku,
    if p^.data = x then
    begin
      // to go usuwamy z listy
      A := p^.next;
      // oraz z pamięci
      dispose(p);
    end
    else
    begin
      while (p^.next <> nil) and
            (p^.next^.data <> x) do
        // Szukamy elementu x
        p := p^.next;
      // Jeśli go znajdziemy, to
      if p^.next <> nil then
      begin
        // zapamiętujemy jego adres,
        r := p^.next;
        // usuwamy go z listy
        p^.next := r^.next;
        // oraz z pamięci
        dispose(r);
      end;
    end;
  end;
end;

// Procedura usuwa zawartość zbioru
//---------------------------------
procedure s_clear(var A : PSLel);
var
  p, r : PSLel;
begin
  // Przechodzimy przez kolejne
  // elementy zbioru A
  p := A;
  while p <> nil do
  begin
    // Zapamiętujemy adres
    // bieżącego elementu
    r := p;
    // p ustawiamy na następnik
    p := p^.next;
    // Element usuwamy z pamięci
    dispose(r);
  end;
  // Zbiór staje się pusty
  A := nil;
end;

// Procedura wyświetla zawartość zbioru
//-------------------------------------
procedure s_print(p : PSLel);
begin
  while p <> nil do
  begin
    write(p^.data:3);
    p := p^.next;
  end;
end;

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

var
  A, B, C : PSLel;
  i, x : integer;

begin
  randomize;
  // Zerujemy zbiory
  A := nil;
  B := nil;
  // Tworzymy dwa zbiory
  // o przypadkowych elementach
  for i := 1 to 10 do
    s_add(A, random(20));
  for i := 1 to 15 do
    s_add(B, random(20));
  // Wyświetlamy je
  write('A =');
  s_print(A);
  writeln;
  writeln('SIZE OF A IS ', s_size(A));
  writeln;
  write('B =');
  s_print(B);
  writeln;
  writeln('SIZE OF B IS ', s_size(B));
  // Suma zbiorów
  writeln;
  write('UNION OF A AND B IS');
  s_union(A, B, C);
  s_print(C);
  writeln;
  writeln('SIZE OF UNION IS ', s_size(c));
  s_clear(C);
  // Iloczyn zbiorów
  writeln;
  write('INTERSECTION OF A AND B IS');
  s_intersection(A, B, C);
  s_print(C);
  writeln;
  writeln('SIZE OF INTERSECTION IS ', s_size(C));
  s_clear(C);
  // Różnica zbiorów
  writeln;
  write('DIFFERENCE OF A AND B IS');
  s_difference(A, B, C);
  s_print(C);
  writeln;
  writeln('SIZE OF DIFFERENCE IS ', s_size(C));
  s_clear(C);
  // Podzbiór
  writeln;
  write('IS');
  s_print(A^.next^.next^.next);
  writeln(' SUBSET OF A?');
  writeln(s_subset(A^.next^.next^.next, A));
  writeln;
  write ('IS');
  s_print(A^.next^.next^.next);
  writeln(' SUBSET OF B?');
  writeln(s_subset(A^.next^.next^.next, B));
  // Usuwanie
  writeln;
  write('FROM A WE REMOVE');
  for i := 1 to 4 do
  begin
    x := random(20);
    write(x:3);
    s_remove(A, x);
  end;
  writeln;
  write('A = ');
  s_print(A);
  writeln;
  writeln('SIZE OF A IS ', s_size(A));
  writeln;
  // Usuwamy wszystkie zbiory
  s_clear(A);
  s_clear(B);
  s_clear(C);
  readln;
end.
C++
// Zbiory zaimplementowane
// na listach jednokierunkowych
// Data: 20.06.2014
// (C)2014 mgr Jerzy Wałaszek
//-----------------------------

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

using namespace std;

// Definicja elementu
// listy jednokierunkowej
struct SLel
{
  // Następny element listy
  SLel * next;
  // Wartość elementu listy
  int data;
};

// Definicje funkcji obsługi
// list jako zbiorów
//--------------------------

// Funkcja sprawdza, czy x
// jest elementem zbioru A
// true  - jest
// false - nie jest
//-------------------------
bool s_isin(SLel * p, int x)
{
  // Przeglądamy kolejne elementy A
  while(p)
  {
    if(p->data == x) return true;
    p = p->next;
  }
  return false;
};

// Procedura dodaje na początek
// zbioru A element x,
// jeśli zbiór A nie zawiera
// jeszcze takiego elementu.
//-----------------------------
void s_add(SLel * & A, int x)
{
  SLel * p;

  // Jeśli elementu x nie ma
  // w zbiorze A, to go tam wstawiamy
  if(!s_isin(A, x))
  {
    // Tworzymy nowy element listy
    p = new SLel;
    // Wprowadzamy do niego dane
    p->data = x;
    // Umieszczamy go na początku
    // zbioru
    p->next = A;
    A = p;
  }
}

// Procedura dokonuje połączenia
// zbiorów A i B. Wynik jest
// umieszczany w C
//------------------------------
void s_union(SLel * A,
             SLel * B,
             SLel * & C)
{
  SLel * p;

  // Zerujemy zbiór wyjściowy
  C = NULL;
  // Zbiór A kopiujemy do C
  for(p = A; p; p = p->next)
    // Kopiujemy element z A do C
    s_add(C, p->data);
  for(p = B; p; p = p->next)
    // Teraz będziemy kopiować
    // do C te elementy z B,
    // których nie ma w A,
    // aby ich nie zdublować
    if(! s_isin(A, p->data))
      s_add(C, p->data);
}

// Procedura wyznacza część wspólną
// zbiorów A i B. Wynik w C
//---------------------------------
void s_intersection(SLel * p,
                    SLel * B,
                    SLel * & C)
{
  // Zerujemy zbiór C
  C = NULL;
  // Przeglądamy kolejne
  // elementy zbioru A
  while(p)
  {
    // Jeśli element jest w B,
    // kopiujemy
    if(s_isin(B, p->data))
      s_add(C, p->data);
    // Następny element z A
    p = p->next;
  }
}

// Procedura wyznacza różnicę
// zbiorów A i B. Wynik w C
//---------------------------
void s_difference(SLel * p,
                  SLel * B,
                  SLel * & C)
{
  // Zerujemy zbiór C
  C = NULL;
  // Przeglądamy kolejne elementy
  // zbioru A
  while(p)
  {
    // Jeśli elementu nie ma w B,
    // kopiujemy
    if(!s_isin(B, p->data))
      s_add(C, p->data);
    // Następny element z A
    p = p->next;
  }
}

// Funkcja sprawdza, czy zbiór B
// zawiera podzbiór A
// true  - tak
// false - nie
//------------------------------
bool s_subset(SLel * p,
              SLel * B)
{
  // Przeglądamy zbiór A
  while(p)
  {
    // Jeśli elementu z A nie ma w B,
    // kończymy
    if(!s_isin(B, p->data))
      return false;
    // Następny element z A
    p = p->next;
  }
  // Wszystkie elementy A są w B
  return true;
}

// Funkcja oblicza liczebność zbioru
//----------------------------------
int s_size(SLel * p)
{
  // Zerujemy licznik
  int c = 0;
  // Przechodzimy przez
  // elementy zbioru A
  while(p)
  {
    // Elementy zliczamy w c
    c++;
    // Następny element z A
    p = p->next;
  }
  return c;
}

// Procedura usuwa
// element x ze zbioru
//--------------------
void s_remove(SLel * & A, int x)
{
  SLel * p, * r;

  // Zbiór nie może być pusty
  if(A)
  {
    // Zapamiętujemy adres
    // początku zbioru
    p = A;
    // Jeśli usuwany element jest
    // na początku,
    if(p->data == x)
    {
      // to go usuwamy z listy
      A = p->next;
      // oraz z pamięci
      delete p;
    }
    else
    {
      while(p->next &&
           (p->next->data != x))
        // Szukamy elementu x
        p = p->next;
      // Jeśli go znajdziemy, to
      if(p->next)
      {
        // zapamiętujemy jego adres,
        r = p->next;
        // usuwamy go z listy
        p->next = r->next;
        // oraz z pamięci
        delete r;
      }
    }
  }
}

// Procedura usuwa zawartość zbioru
//---------------------------------
void s_clear(SLel *  & A)
{
  SLel * p, *r;

  // Przechodzimy przez kolejne
  // elementy zbioru A
  p = A;
  while(p)
  {
    // Zapamiętujemy adres
    // bieżącego elementu
    r = p;
    // p ustawiamy na następnik
    p = p->next;
    // Element usuwamy z pamięci
    delete r;
  }
  // Zbiór staje się pusty
  A = NULL;
}

// Procedura wyświetla
// zawartość zbioru
//--------------------
void s_print(SLel * p)
{
  while(p)
  {
    cout << setw (3) << p->data;
    p = p->next;
  }
}

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

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

  srand (time(NULL));
  // Zerujemy zbiory
  A = B = NULL;
  // Tworzymy dwa zbiory
  // o przypadkowych elementach
  for(i = 0; i < 10; i++)
    s_add(A, rand() % 20);
  for(i = 0; i < 15; i++)
    s_add(B, rand() % 20);
  // Wyświetlamy je
  cout << "A =";
  s_print (A);
  cout << endl
       << "SIZE OF A IS "
       << s_size(A) << endl << endl
       << "B =";
  s_print(B);
  cout << endl
       << "SIZE OF B IS "
       << s_size(B) << endl << endl;
  // Suma zbiorów
  cout << "UNION OF A AND B IS";
  s_union(A, B, C);
  s_print(C);
  cout << endl
       << "SIZE OF UNION IS "
       << s_size(C) << endl << endl;
  s_clear(C);
  // Iloczyn zbiorów
  cout << "INTERSECTION OF A AND B IS";
  s_intersection(A, B, C);
  s_print(C);
  cout << endl
       << "SIZE OF INTERSECTION IS "
       << s_size(C) << endl << endl;
  s_clear(C);
  // Różnica zbiorów
  cout << "DIFFERENCE OF A AND B IS";
  s_difference(A, B, C);
  s_print(C);
  cout << endl
       << "SIZE OF DIFFERENCE IS "
       << s_size(C) << endl << endl;
  s_clear(C);
  // Podzbiór
  cout << "IS";
  s_print(A->next->next->next);
  cout << " SUBSET OF A?" << endl
       << (s_subset(A->next->next->next, A)
           ?"TRUE":"FALSE")
       << endl << endl;
  cout << "IS";
  s_print(A->next->next->next);
  cout << " SUBSET OF B?" << endl
       << (s_subset(A->next->next->next, B)
           ?"TRUE":"FALSE")
       << endl << endl;
  // Usuwanie
  cout << "FROM A WE REMOVE";
  for(i = 0; i < 4; i++)
  {
    x = rand() % 20;
    cout << setw (3) << x;
    s_remove(A, x);
  }
  cout << endl << "A =";
  s_print(A);
  cout << endl
       << "SIZE OF A IS " << s_size(A)
       << endl << endl;
  // Usuwamy wszystkie zbiory
  s_clear(A);
  s_clear(B);
  s_clear(C);
  return 0;
}
Basic
' Zbiory zaimplementowane
' na listach jednokierunkowych
' Data: 20.06.2014
' (C)2014 mgr Jerzy Wałaszek
'------------------------------

' Definicja elementu listy jednokierunkowej
Type SLel
  ' Następny element listy
  next As SLel Ptr
  ' Wartość elementu listy
  data As Integer
End Type

' Definicje funkcji obsługi
' list jako zbiorów
'--------------------------

' Funkcja sprawdza, czy x jest
' elementem zbioru A
' 1  - jest
' 0 - nie jest
'-----------------------------
Function s_isin(ByVal p As SLel Ptr, _
                ByVal x As integer) _
                        As Integer
  ' Przeglądamy kolejne elementy A
  While p
    If p->data = x Then Return 1
    p = p->Next
  Wend
  Return 0
End Function

' Procedura dodaje na początek
' zbioru A element x, 
' jeśli zbiór A nie zawiera
' jeszcze takiego elementu.
'-----------------------------
Sub s_add(byref A As SLel Ptr, _
          byval x As Integer)
  Dim As SLel Ptr p

  ' Jeśli elementu x nie ma w zbiorze A,
  ' to go wstawiamy do C
  If s_isin(A, x) = 0 Then
    ' Tworzymy nowy element listy
    p = new SLel
    ' Wprowadzamy do niego dane
    p->data = x
    ' Umieszczamy go na początku zbioru
    p->next = A
    A = p
  End If
End Sub

' Procedura dokonuje połączenia
' zbiorów A i B. Wynik jest umieszczany w C
'------------------------------------------
Sub s_union(ByVal A As SLel Ptr,_
            ByVal B As SLel Ptr,_
            ByRef C As SLel Ptr)
  Dim  As SLel Ptr p

  ' Zerujemy zbiór wyjściowy
  C = 0
  p = A
  While p
    ' Kopiujemy element z A do C
    s_add(C, p->data)
    ' Następny element z A
    p = p->next
  Wend
  p = B
  While p
    ' kopiujemy element,
    ' którego nie ma w A
    If s_isin(A, p->data) = 0 Then _
      s_add(C, p->data)
    ' Następny element z B
    p = p->next
  Wend
End Sub

' Procedura wyznacza część wspólną
' zbiorów A i B. Wynik w C
'---------------------------------
Sub s_intersection(ByVal p As SLel Ptr,_
                   ByVal B As SLel Ptr,_
                   ByRef C As SLel Ptr)
  ' Zerujemy zbiór C
  C = 0
  ' Przeglądamy kolejne elementy zbioru A
  While p
    ' Jeśli element jest w B, kopiujemy
    If s_isin(B, p->Data) = 1 Then _
      s_add(C, p->data)
    ' Następny element z A
    p = p->Next
  Wend
End Sub

' Procedura wyznacza różnicę
' zbiorów A i B. Wynik w C
'---------------------------
Sub s_difference(ByVal p As SLel Ptr,_
                 ByVal B As SLel Ptr,_
                 ByRef C As SLel Ptr)
  ' Zerujemy zbiór C
  C = 0
  ' Przeglądamy kolejne elementy zbioru A
  While p
    ' Jeśli elementu nie ma w B, kopiujemy
    If s_isin(B, p->data) = 0 Then  _
      s_add(C, p->data)
    ' Następny element z A
    p = p->next
  Wend
End Sub

' Funkcja sprawdza,
' czy zbiór B zawiera podzbiór A
' 1 - tak
' 0 - nie
'-------------------------------
Function s_subset(ByVal p As SLel Ptr,_
                  ByVal B As SLel Ptr) _
                          As Integer 
  ' Przeglądamy zbiór A
  While p
    ' Jeśli elementu z A nie ma w B,
    ' kończymy
    If s_isin(B, p->data) = 0 Then _
      Return 0
    ' Następny element z A
    p = p->next
  Wend
  ' Wszystkie elementy A są w B
  Return 1
End Function

' Funkcja oblicza liczebność zbioru
'----------------------------------
Function s_size(ByVal p As SLel Ptr) _
                        As Integer

  ' Zerujemy licznik
  Dim As Integer c = 0

  ' Przechodzimy przez elementy zbioru A
  While p
    ' Elementy zliczamy w c
    c += 1
    ' Następny element z A
    p = p->next
  Wend 
  Return c
End Function

' Procedura usuwa element x ze zbioru
'------------------------------------
Sub s_remove(ByRef A As SLel Ptr,_
             ByVal x As integer)
  Dim As SLel Ptr p, r
  
  ' Zbiór nie może być pusty
  If A Then
    ' Zapamiętujemy adres początku zbioru
    p = A
    ' Jeśli usuwany element
    ' jest na początku, 
    If p->data = x Then
      ' to go usuwamy z listy
      A = p->next
      ' oraz z pamięci
      Delete p
    Else
      while (p->next <> 0) AndAlso _
            (p->next->data <> x)
        ' Szukamy elementu x
        p = p->next
      Wend
      ' Jeśli go znajdziemy, to
      If p->next Then
        ' zapamiętujemy jego adres, 
        r = p->next
        ' usuwamy go z listy
        p->next = r->next
        ' oraz z pamięci
        Delete r
      End If
    End If
  End If
End Sub

' Procedura usuwa zawartość zbioru
'---------------------------------
Sub s_clear(ByRef A As SLel Ptr)
  Dim As SLel Ptr p, r

  ' Przechodzimy przez kolejne
  ' elementy zbioru A
  p = A
  While p
    ' Zapamiętujemy adres bieżącego elementu
    r = p
    ' p ustawiamy na następnik
    p = p->next
    ' Element usuwamy z pamięci
    Delete r
  Wend
  ' Zbiór staje się pusty
  A = 0
End Sub

' Procedura wyświetla zawartość zbioru
'------------------------------------
Sub s_print(ByVal p As SLel Ptr)
  While p
    Print Using "###";p->data;
    p = p->next
  Wend
End Sub

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

Dim As SLel Ptr A, B, C
Dim As integer i, x

Randomize
' Zerujemy zbiory
A = 0
B = 0
' Tworzymy dwa zbiory o przypadkowych elementach
For i = 1 To 10
  s_add(A, Int(Rnd() * 20))
Next
For i = 1 To 15
  s_add(B, Int(Rnd() * 20))
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 IS";
s_union(A, B, C)
s_print(C)
Print
Print "SIZE OF UNION IS"; s_size(C)
Print
s_clear(C)
' Iloczyn zbiorów
Print "INTERSECTION OF A AND B IS";
s_intersection(A, B, C)
s_print(C)
Print
Print "SIZE OF INTERSECTION IS"; s_size(C)
Print
s_clear(C)
' Różnica zbiorów
Print "DIFFERENCE OF A AND B IS";
s_difference(A, B, C)
s_print(C)
Print
Print "SIZE OF DIFFERENCE IS"; s_size(C)
Print
s_clear(C)
' Podzbiór
Print "IS";
s_print(A->next->next->next)
Print " SUBSET OF A?"
If s_subset(A->next->next->next, A) = 1 Then
  Print "TRUE"
Else 
  Print "FALSE"
End If
Print
Print "IS";
s_print(A->next->next->next)
Print " SUBSET OF B?"
If s_subset(A->next->next->next, B) = 1 Then
  Print "TRUE"
Else
  Print "FALSE"
End If
Print
' Usuwanie
Print "FROM A WE REMOVE";
For i = 1 To 4
  x = Int(Rnd() * 20)
  Print Using "###";x;
  s_remove(A, x)
Next
Print
Print "A =";
s_print(A)
Print
Print "SIZE OF A IS"; s_size(A)
Print
' Usuwamy wszystkie zbiory
s_clear(A)
s_clear(B)
s_clear(C)
End
Python (dodatek)
# Zbiory zaimplementowane
# na listach jednokierunkowych
# Data: 20.06.2014
# (c)2014 mgr Jerzy Wałaszek
# ------------------------------

import random


# Klasa elementu listy jednokierunkowej
class SLel:


    def __init__(self, d):
        # Następny element listy
        self.next = None
        # Wartość elementu listy
        self.data = d


# Definicje funkcji obsługi
# list jako zbiorów
# --------------------------

# Funkcja sprawdza, czy x jest
# elementem zbioru A
# True  - jest
# False - nie jest
# -----------------------------
def s_isin(p, x):
    # Przeglądamy kolejne elementy A
    while p:
        if p.data == x: return True
        p = p.next
    return False


# Procedura dodaje na początek
# zbioru A element x,
# jeśli zbiór A nie zawiera
# jeszcze takiego elementu.
# -----------------------------
def s_add(a, x):
    # Jeśli elementu x nie ma w zbiorze a,
    # to go wstawiamy do A
    if not s_isin(a, x):
        # Tworzymy nowy element listy
        p = SLel(x)
        # Umieszczamy go na początku zbioru
        p.next = a
        a = p
    return a


# Procedura dokonuje połączenia
# zbiorów A i B. Wynik jest umieszczany w C
# ------------------------------------------
def s_union(a, b):
    # Zerujemy zbiór wyjściowy
    c = None
    p = a
    while p:
        # Kopiujemy element z A do C
        c = s_add(c, p.data)
        # Następny element z A
        p = p.next
    p = b
    while p:
        # kopiujemy element,
        # którego nie ma w A
        if not s_isin(a, p.data):
            c = s_add(c, p.data)
        # Następny element z B
        p = p.next
    return c


# Procedura wyznacza część wspólną
# zbiorów A i B. Wynik w C
def s_intersection(p, b):
    # Zerujemy zbiór C
    c = None
    # Przeglądamy kolejne
    # elementy zbioru A
    while p:
        # Jeśli element jest w B,
        # kopiujemy
        if s_isin(b, p.data):
            c = s_add(c, p.data)
        # Następny element z A
        p = p.next
    return c


# Procedura wyznacza różnicę
# zbiorów A i B. Wynik w C
# ---------------------------
def s_difference(p, b):
    # Zerujemy zbiór C
    c = None
    # Przeglądamy kolejne elementy zbioru A
    while p:
        # Jeśli elementu nie ma w B,
        # kopiujemy
        if not s_isin(b, p.data):
            c = s_add(c, p.data)
        # Następny element z A
        p = p.next
    return c


# Funkcja sprawdza,
# czy zbiór B zawiera podzbiór A
# True  - tak
# False - nie
# -------------------------------
def s_subset(p, b):
    # Przeglądamy zbiór A
    while p:
        # Jeśli elementu z A nie ma w B,
        # kończymy
        if not s_isin(b, p.data):
            return False
        # Następny element z A
        p = p.next
    # Wszystkie elementy A są w B
    return True


# Funkcja oblicza liczebność zbioru
# ----------------------------------
def s_size(p):
    # Zerujemy licznik
    cnt = 0
    # Przechodzimy przez
    # elementy zbioru
    while p:
        # Elementy zliczamy w c
        cnt += 1
        # Następny element
        p = p.next
    return cnt


# Procedura usuwa element x ze zbioru
# ------------------------------------
def s_remove(a, x):
    # Zbiór nie może być pusty
    if a:
        # Zapamiętujemy adres
        # początku zbioru
        p = a
        # Jeśli usuwany element
        # jest na początku,
        if p.data == x:
            # to go usuwamy z listy
            a = p.next
        else:
            while p.next and \
                    p.next.data != x:
                # Szukamy elementu x
                p = p.next
            # Jeśli go znajdziemy, to
            if p.next:
                # zapamiętujemy jego adres,
                r = p.next
                # usuwamy go z listy
                p.next = r.next
    return a


# Procedura wyświetla zawartość zbioru
# ------------------------------------
def s_print(p):
    while p:
        print("%3d" % p.data, end="")
        p = p.next


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

# Tworzymy dwa zbiory o przypadkowych elementach
a = None
for i in range(10):
    a = s_add(a, random.randrange(20))
b = None
for i in range(15):
    b = s_add(b, random.randrange(20))
# Wyświetlamy je
print("A =", end="")
s_print(a)
print()
print("SIZE OF A IS", s_size(a))
print()
print("B =", end="")
s_print(b)
print()
print("SIZE OF B IS", s_size(b))
print()
# Suma zbiorów
print("UNION OF A AND B IS", end="")
c = s_union(a, b)
s_print(c)
print()
print("SIZE OF UNION IS", s_size(c))
print()
# Iloczyn zbiorów
print("INTERSECTION OF A AND B IS", end="")
c = s_intersection(a, b)
s_print(c)
print()
print("SIZE OF INTERSECTION IS", s_size(c))
print()
# Różnica zbiorów
print("DIFFERENCE OF A AND B IS", end="")
c = s_difference(a, b)
s_print(c)
print()
print("SIZE OF DIFFERENCE IS", s_size(c))
print()
# Podzbiór
print("IS", end="")
s_print(a.next.next.next)
print(" SUBSET OF A?")
if s_subset(a.next.next.next, a):
    print("TRUE")
else:
    print("FALSE")
print()
print("IS", end="")
s_print(a.next.next.next)
print(" SUBSET OF B?")
if s_subset(a.next.next.next, b):
    print("TRUE")
else:
    print("FALSE")
print()
# Usuwanie
print("FROM A WE REMOVE", end="")
for i in range(4):
    x = random.randrange(20)
    print("%3d" % x, end="")
    a = s_remove(a, x)
print()
print("A =", end="")
s_print(a)
print()
print("SIZE OF A IS", s_size(a))
print()
Wynik:
A = 1 10 8 13 6 12 7 16 17
SIZE OF A IS 9

B = 18 0 2 14 1 12 5 17 8 16
SIZE OF B IS 10

UNION OF A AND B IS 5 14 2 0 18 17 16 7 12 6 13 8 10 1
SIZE OF UNION IS 14

INTERSECTION OF A AND B IS 17 16 12 8 1
SIZE OF INTERSECTION IS 5

DIFFERENCE OF A AND B IS 7 6 13 10
SIZE OF DIFFERENCE IS 4

IS 13 6 12 7 16 17 SUBSET OF A?
TRUE

IS 13 6 12 7 16 17 SUBSET OF B?
FALSE

FROM A WE REMOVE 1 13 2 10
A = 8 6 12 7 16 17
SIZE OF A IS 6

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.