|
Serwis Edukacyjny w I-LO w Tarnowie
Materiały dla uczniów liceum |
Wyjście Spis treści Wstecz Dalej
Autor artykułu: mgr Jerzy Wałaszek |
©2026 mgr Jerzy Wałaszek
|
Mapa bitowa (ang. bitmap) jest ciągiem bitów. Poszczególne bity w mapie bitowej posiadają swoje numery. Umówmy się, że bity będziemy zawsze numerować od strony prawej do lewej. Numeracja rozpoczyna się od 0. Poniżej mamy mapę bitową zbudowaną z 26 bitów:
b25
|
b24
|
b23
|
b22
|
b21
|
b20
|
b19
|
b18
|
b17
|
b16
|
b15
|
b14
|
b13
|
b12
|
b11
|
b10
|
b9
|
b8
|
b7
|
b6
|
b5
|
b4
|
b3
|
b2
|
b1
|
b0
|
Każdy bit mapy może przyjąć wartość 0 lub 1.
Zbiór da się odwzorować mapą bitową. Stosujemy tutaj podobną umowę, jak przy tablicach:
b25
|
b24
|
b23
|
b22
|
b21
|
b20
|
b19
|
b18
|
b17
|
b16
|
b15
|
b14
|
b13
|
b12
|
b11
|
b10
|
b9
|
b8
|
b7
|
b6
|
b5
|
b4
|
b3
|
b2
|
b1
|
b0
|
0 |
0 |
0 |
0 |
0 |
1 |
1 |
0 |
0 |
0 |
0 |
1 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
0 |
0 |
0 |
0 |
1 |
Jeśli nasza mapa bitowa odwzorowuje zbiór elementów o wartościach od 0 do 25 (wartość elementu odpowiada numerowi bitu), to w zbiorze znajdują się elementy: 20, 19, 14, 5 i 0.
Z mapami bitowymi wiąże się pewien prosty problem. Otóż w tablicy mogliśmy się odwołać bezpośrednio do elementu zbioru za pomocą indeksu. Tutaj jest nieco gorzej (a może lepiej?), ponieważ bity mapy są przechowywane w komórkach pamięci grupami po 8:
| bajt nr 3 | bajt nr 2 | bajt nr 1 | bajt nr 0 | ||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
b31
|
b30
|
b29
|
b28
|
b27
|
b26
|
b25 |
b24 |
b23 |
b22 |
b21 |
b20 |
b19 |
b18 |
b17 |
b16 |
b15 |
b14 |
b13 |
b12 |
b11 |
b10 |
b9 |
b8 |
b7 |
b6 |
b5 |
b4 |
b3 |
b2 |
b1 |
b0 |
W bajcie nr 3 wykorzystujemy tylko dwa bity: b24 i b25. Pozostałe nie należą do mapy bitowej, jednak i tak muszą być zarezerwowane w pamięci.
Umówmy się, że najmniejszą jednostką przydziału pamięci dla mapy bitowej będzie 4 bajty, czyli 32 bity. Taka organizacja jest podyktowana większą szybkością pracy na danych 32 bitowych niż na 8 bitowych we współczesnych mikroprocesorach (w jednym rozkazie procesor może naraz przetworzyć 32 bity, czyli 32 elementy zbioru!). Również dostęp do danych 32 bitowych jest szybszy w procesorach Pentium od dostępu do danych 8 bitowych. Zatem mapę bitową będziemy przechowywali w tablicy, której elementy są 32 bitowe.
Do określenia mapy bitowej będziemy potrzebowali dwóch wielkości całkowitych:
Liczbę bitów obliczymy ze wzoru:
liczba_bitów = vmax-vmin+1
Liczbę komórek 32 bitowych obliczymy ze wzoru:
n = ((liczba_bitów-1) shr 5)+1
Ta ostatnia informacja będzie potrzebna dla operacji blokowych na zbiorach (suma, iloczyn, różnica, podzbiór).
Aby znaleźć bit odpowiadający elementowi o wartości v, wykonujemy następujące operacje:
Najpierw przekształcamy wartość v na numer bitu:
numer_bitu = v-vmin
Teraz wyznaczamy indeks komórki tablicy, która zawiera dany bit (dzielenie jest całkowitoliczbowe):
indeks = numer_bitu shr 5
Na koniec obliczamy numer bitu w komórce (wydzielając młodsze 5 bitów):
nb = numer_bitu and 31
Jeśli mamy indeks komórki tablicy mapy bitowej oraz numer bitu nb wewnątrz tej komórki, to wartość elementu zbioru skojarzonego z tym bitem obliczymy następująco:
Obliczamy numer bitu w mapie bitowej:
numer_bitu = (indeks shl 5) or nb
Obliczamy wartość elementu zbioru:
v = numer_bitu+vmin
Powyższe wzory pozwalają nam obsługiwać pojedyncze elementy zbioru. Mając wartość elementu, potrafimy określić numer reprezentującego go bitu, a dalej położenie tego bitu w tablicy mapy bitowej. Również na odwrót, mając położenie bitu w tablicy, potrafimy określić element, który ten bit reprezentuje w zbiorze.
Zbiór jest reprezentowany przez strukturę BSet zawierającą pola:
Pascaltype
BSet = record
vmin : integer;
nmax : integer;
T : array of cardinal;
end; |
struct BSet
{
int vmin, nmax;
unsigned int * T;
}; |
BasicType BSet vmin As Integer nmax As Integer T As UInteger Ptr End Type |
| Python (dodatek) |
class BSet:
def __init__(self)
self.vmin = 0
self.nmax = 0
self.t = []
|
Poniżej przedstawiamy algorytmy podstawowych operacji dla zbioru zaimplementowanego mapą bitową.
K01: b ← x-A→vmin ; obliczamy numer bitu K02: i ← b shr 5 ; obliczamy indeks K03: A→T[i] ← A→T[i] or (1 shl (b and 31)) ; ustawiamy bit na 1 K04: Zakończ
K01: b ← x - A→vmin ; obliczamy numer bitu K02: i ← b shr 5 ; obliczamy indeks K03: A→T[i] ← A→T[i] and not (1 shl (b and 31)) ; ustawiamy bit na 0 K04: Zakończ
K01: Dla i = 0, 1, …, A→nmax: ; zerujemy komórki tablicy wykonuj: A.T→[i] ← 0 K02: Zakończ
K01: A→vmin ← vmin ; wypełniamy strukturę BSet odpowiednimi wartościami K02: A→nmax ← (vmax-vmin) shr 5 ; obliczamy indeks ostatniego elementu tablicy K03: Utwórz obszar dla nmax = 1 komórek ; tworzymy tablicę dynamiczną K04: A→T ← adres utworzonego obszaru K05: s_clear(A) ; tworzymy pusty zbiór K06: Zakończ
K01: Dla i = 0, 1, …, A→nmax: wykonuj krok K02 K02: C→T[i] ← A→T[i] or B→T[i] ; łączymy zbiory A i B w zbiór C K03: Zakończ
K01: Dla i = 0, 1, …, A→nmax: wykonuj krok K02 K02: C→T[i] ← A→T[i] and B→T[i] ; wyznaczamy w C część wspólną A i B K03: Zakończ
K01: Dla i = 0, 1, …, A→nmax: wykonuj krok K02 K02: C→T[i] ← A→T[i] and not B→T[i] ; wyznaczamy w C różnicę A i B K03: Zakończ
K01: Dla i = 0, 1, …, A→nmax: wykonuj krok K02 K02: Jeśli (A→T[i] and B→T[i]) ≠ A→T[i], ; sprawdzamy, czy element z A jest w B. to zakończ z wynikiem false ; Jeśli nie, to kończymy z wynikiem false K03: Zakończ z wynikiem true
K01: c ← 0 ; zerujemy licznik K02: Dla i = 0, 1, …, A→nmax, ; zliczamy komórki z elementami wykonuj kroki K03…K06 K03: m ← A.T[i] ; zapamiętujemy w m bity komórki A→T[i] K04: Dopóki m > 0, ; pomijamy puste komórki wykonuj kroki K05…K06 K05: Jeśli (m and 1) = 1, ; zliczamy bity o wartości 1 to c ← c+1 K06: m ← m shr 1 ; przesuwamy bity o 1 pozycję w prawo K07: Zakończ z wynikiem c
K01: m ← A→T[0] ; ustawiamy bity w masce K02: Dla i = 1, 2, …, A→nmax: ; sumujemy bity wykonuj: m ← m or A→T[i] K03: Jeśli m = 0, to zakończ z wynikiem true inaczej zakończ z wynikiem false
K01:b ←x -A →vmin ; obliczamy numer bitu K02: Jeśli A→T[b shr 5] and (1 shl (b and 31)) > 0, to zakończ z wynikiem true Inaczej zakończ z wynikiem false
|
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 bitmapach. Wyjaśnienie wykonywanych operacji znajduje się w komentarzach wewnątrz programu. |
Pascal// Zbiory zaimplementowane
// w mapach bitowych
// Data: 30.06.2014
// (C)2014 mgr Jerzy Wałaszek
//---------------------------
program sets;
// Definicja struktury zbioru
type
BSet = record
vmin : integer;
nmax : integer;
T : array of cardinal;
end;
// Procedura dodaje element x
// do zbioru A
//---------------------------
procedure s_add(var A : BSet;
x : integer);
var
b, i : integer;
begin
// Obliczamy numer bitu
b := x-A.vmin;
// Obliczamy indeks
i := b shr 5;
// Ustawiamy bit na 1
A.T[i] := A.T[i] or (1 shl (b and 31));
end;
// Procedura usuwa element x
// ze zbioru
//--------------------------
procedure s_remove(var A : BSet;
x : integer);
var
b, i : integer;
begin
// Obliczamy numer bitu
b := x-A.vmin;
// Obliczamy indeks
i := b shr 5;
// Ustawiamy bit na 0
A.T[i] := A.T[i] and not (1 shl (b and 31));
end;
// Procedura usuwa wszystkie elementy
// ze zbioru
//-----------------------------------
procedure s_clear(var A : BSet);
var
i : integer;
begin
// Zerujemy tablicę
for i := 0 to A.nmax do A.T[i] := 0;
end;
// Procedura tworzy zbiór
//-----------------------
procedure s_create(var A : BSet;
vmin, vmax : integer);
begin
// Wypełniamy strukturę danymi
A.vmin := vmin;
// Indeks ostatniego elementu tablicy
A.nmax := (vmax-vmin) shr 5;
// Tworzymy dynamicznie
// tablicę mapy bitowej
SetLength(A.T, A.nmax+1);
// Tworzymy zbiór pusty
s_clear(A);
end;
// Procedura wyznacza w C sumę
// zbiorów A i B
//----------------------------
procedure s_union(var A, B, C : BSet);
var
i : integer;
begin
for i := 0 to A.nmax do
C.T[i] := A.T[i] or B.T[i];
end;
// Procedura wyznacza część wspólną
// zbiorów A i B
//---------------------------------
procedure s_intersection(var A, B, C : BSet);
var
i : integer;
begin
for i := 0 to A.nmax do
C.T[i] := A.T[i] and B.T[i];
end;
// Procedura wyznacza różnicę
// zbiorów A i B
//---------------------------
procedure s_difference(var A, B, C : BSet);
var
i : integer;
begin
for i := 0 to A.nmax do
C.T[i] := A.T[i] and not B.T[i];
end;
// Funkcja sprawdza, czy zbiór A
// jest podzbiorem zbioru B
// true - tak, jest
// false - nie, nie jest
//------------------------------
function s_subset(var A, B : BSet)
: boolean;
var
i : integer;
begin
// Przeglądamy kolejne elementy tablicy
for i := 0 to A.nmax do
if(A.T[i] and B.T[i]) <> A.T [i] then
// Jeśli elementu A nie ma w B,
// kończymy z false
Exit(false);
s_subset := true;
end;
// Funkcja oblicza liczbę elementów w A
//-------------------------------------
function s_size(var A : BSet) : integer;
var
i, c : integer;
m : cardinal;
begin
// Zerujemy licznik
c := 0;
// Przechodzimy przez kolejne komórki
for i := 0 to A.nmax do
begin
// Pobieramy bity do m
m := A.T[i];
// Zliczamy bity równe 1
while m > 0 do
begin
if(m and 1) = 1 then inc(c);
m := m shr 1;
end;
end;
s_size := c;
end;
// Funkcja sprawdza, czy
// zbiór A jest pusty
// true - tak, jest pusty
// false - nie, nie jest pusty
//----------------------------
function s_empty(var A : BSet)
: boolean;
var
i : integer;
m : cardinal;
begin
// Pobieramy bity do m
m := A.T[0];
for i := 1 to A.nmax do
// Sumujemy logicznie bity
m := m or A.T[i];
s_empty := (m = 0);
end;
// Funkcja bada, czy element x
// należy do zbioru A
// true - tak, należy
// false - nie, nie należy
//----------------------------
function s_isin(var A : BSet;
x : integer)
: boolean;
var
b : integer;
begin
// Obliczamy numer bitu
// w mapie bitowej
b := x-A.vmin;
if A.T[b shr 5] and
(1 shl (b and 31)) > 0 then
Exit(true);
s_isin := false;
end;
// Procedura wyświetla elementy
// zbioru A
//-----------------------------
procedure s_print(var A : BSet);
var
i, nb : integer;
m : cardinal;
begin
for i := 0 to A.nmax do
begin
nb := 0;
m := A.T[i];
while m > 0 do
begin
if(m and 1) = 1 then
write((i shl 5)+nb+A.vmin, ' ');
m := m shr 1;
inc(nb);
end
end;
end;
// **********************
// *** PROGRAM GŁÓWNY ***
// **********************
var
A, B, C : BSet;
i, x : integer;
begin
randomize;
// Tworzymy puste zbiory o zakresie
// elementów od -20 do 20
s_create(A, -20, 20);
s_create(B, -20, 20);
s_create(C, -20, 20);
// 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, ' ');
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) 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, C);
writeln(s_empty(C));
writeln;
// Usuwamy tablice dynamiczne w zbiorach
SetLength(A.T, 0);
SetLength(B.T, 0);
SetLength(C.T, 0);
end.
|
// Zbiory zaimplementowane
// w mapach bitowych
// Data: 1.07.2014
// (C)2014 mgr Jerzy Wałaszek
//---------------------------
#include <iostream>
#include <iomanip>
#include <cstdlib>
#include <ctime>
using namespace std;
// Definicja struktury zbioru
struct BSet
{
int vmin, nmax;
unsigned int *T;
};
// Procedura dodaje element x
// do zbioru A
//---------------------------
void s_add(BSet & A, int x)
{
// Obliczamy numer bitu
int b = x-A.vmin;
// Obliczamy indeks
int i = b >> 5;
// Ustawiamy bit na 1
A.T[i] |= 1 << (b & 31);
}
// Procedura usuwa element x
// ze zbioru
//--------------------------
void s_remove(BSet & A, int x)
{
// Obliczamy numer bitu
int b = x-A.vmin;
// Obliczamy indeks
int i = b >> 5;
// Ustawiamy bit na 0
A.T[i] &= ~(1 << (b & 31));
}
// Procedura usuwa wszystkie elementy
// ze zbioru
//-----------------------------------
void s_clear(BSet & A)
{
// Zerujemy mapę bitową
for(int i = 0; i <= A.nmax; i++)
A.T[i] = 0;
}
// Procedura tworzy zbiór
//-----------------------
void s_create(BSet & A,
int vmin,
int vmax)
{
// Wypełniamy strukturę danymi
A.vmin = vmin;
// Indeks ostatniego elementu tablicy
A.nmax = (vmax-vmin) >> 5;
// Tworzymy dynamicznie tablicę
// mapy bitowej
A.T = new unsigned int[A.nmax + 1];
// Tworzymy zbiór pusty
s_clear(A);
}
// Procedura wyznacza w C sumę
// zbiorów A i B
//----------------------------
void s_union(BSet & A,
BSet & B,
BSet & C)
{
for(int i = 0; i <= A.nmax; i++)
C.T[i] = A.T[i] | B.T[i];
}
// Procedura wyznacza część wspólną
// zbiorów A i B
//---------------------------------
void s_intersection(BSet & A,
BSet & B,
BSet & C)
{
for(int i = 0; i <= A.nmax; i++)
C.T[i] = A.T[i] & B.T[i];
}
// Procedura wyznacza różnicę
// zbiorów A i B
//---------------------------
void s_difference(BSet & A,
BSet & B,
BSet & C)
{
for(int i = 0; i <= A.nmax; i++)
C.T[i] = A.T[i] & ~B.T[i];
}
// Funkcja sprawdza, czy zbiór A
// jest podzbiorem zbioru B
// true - tak, jest
// false - nie, nie jest
//------------------------------
bool s_subset(BSet & A, BSet & B)
{
// Przeglądamy kolejne elementy tablicy
for(int i = 0; i <= A.nmax; i++)
if((A.T[i] & B.T[i]) != A.T[i])
// Jeśli elementu A nie ma w B,
// kończymy z false
return false;
return true;
}
// Funkcja oblicza liczbę elementów w A
//-------------------------------------
int s_size(BSet & A)
{
// Zerujemy licznik
int c = 0;
// Przechodzimy przez kolejne komórki
for(int i = 0; i <= A.nmax; i++)
for(unsigned int m = A.T[i]; m; m >>= 1)
// Zliczamy bity równe 1
if((m & 1) == 1) c++;
return c;
}
// Funkcja sprawdza, czy zbiór A jest pusty
// true - tak, jest pusty
// false - nie, nie jest pusty
//-----------------------------------------
bool s_empty(BSet A)
{
// Pobieramy bity do m
unsigned int m = A.T[0];
for(int i = 1; i <= A.nmax; i++)
// Sumujemy logicznie bity
m |= A.T[i];
return (m == 0);
}
// Funkcja bada, czy element x należy
// do zbioru A
// true - tak, należy
// false - nie, nie należy
//-----------------------------------
bool s_isin(BSet & A, int x)
{
// Obliczamy numer bitu w mapie bitowej
int b = x-A.vmin;
if(A.T[b >> 5] & (1 << (b & 31)))
return true;
return false;
}
// Procedura wyświetla elementy zbioru A
//--------------------------------------
void s_print(BSet A)
{
int nb;
unsigned int m;
for(int i = 0; i <= A.nmax; i++)
for(nb = 0, m = A.T[i]; m; m >>= 1, nb++)
if(m & 1)
cout << (i << 5)+nb+A.vmin << " ";
}
// **********************
// *** PROGRAM GŁÓWNY ***
// **********************
int main()
{
BSet A, B, C;
int i, x;
// Inicjujemy generator pseudolosowy
srand(time(NULL));
// Tworzymy puste zbiory o zakresie
// elementów od -20 do 20 i liczebności 30
s_create(A, -20, 20);
s_create(B, -20, 20);
s_create(C, -20, 20);
// 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 << 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, C);
cout << (s_empty(C) ? "YES": "NO")
<< endl << endl;
// Usuwamy tablice dynamiczne w zbiorach
delete [] A.T;
delete [] B.T;
delete [] C.T;
return 0;
}
|
Basic' Zbiory zaimplementowane w mapach bitowych
' Data: 01.06.2014
' (C)2014 mgr Jerzy Wałaszek
'------------------------------------------
' Definicja struktury zbioru
Type BSet
vmin As Integer
nmax As Integer
T As UInteger Ptr
End Type
' Procedura dodaje element x do zbioru A
'---------------------------------------
Sub s_add(ByRef A As BSet, _
ByVal x As Integer)
Dim As Integer b, i
' Obliczamy numer bitu
b = x-A.vmin
' Obliczamy indeks
i = b Shr 5
' Ustawiamy bit na 1
A.T[i] = A.T[i] or (1 Shl (b And 31))
End Sub
' Procedura usuwa element x ze zbioru
'------------------------------------
Sub s_remove(ByRef A As BSet, _
ByVal x As Integer)
Dim As Integer b, i
' Obliczamy numer bitu
b = x-A.vmin
' Obliczamy indeks
i = b Shr 5
' Ustawiamy bit na 0
A.T[i] = A.T[i] And Not (1 Shl (b And 31))
End Sub
' Procedura usuwa wszystkie elementy
' ze zbioru
'-----------------------------------
Sub s_clear(ByRef A As BSet)
Dim As Integer i
For i = 0 To A.nmax
' Zerujemy mapę bitową
A.T[i] = 0
Next
End Sub
' Procedura tworzy zbiór
'-----------------------
Sub s_create(ByRef A As BSet, _
ByVal vmin As Integer, _
ByVal vmax As Integer)
' Wypełniamy strukturę danymi
A.vmin = vmin
' Indeks ostatniego elementu tablicy
A.nmax = (vmax-vmin) shr 5
' Tworzymy dynamicznie tablicę
' mapy bitowej
A.T = New UInteger [A.nmax+1]
' Tworzymy zbiór pusty
s_clear(A)
End Sub
' Procedura wyznacza w C sumę zbiorów A i B
'------------------------------------------
Sub s_union(ByRef A As BSet, _
ByRef B As BSet, _
ByRef C As BSet)
Dim As Integer i
For i = 0 To A.nmax
C.T[i] = A.T[i] Or B.T[i]
Next
End Sub
' Procedura wyznacza część wspólną
' zbiorów A i B
'---------------------------------
Sub s_intersection(ByRef A As BSet, _
ByRef B As BSet, _
ByRef C As BSet)
Dim As Integer i
For i = 0 To A.nmax
C.T[i] = A.T[i] And B.T[i]
Next
End Sub
' Procedura wyznacza różnicę zbiorów A i B
'-----------------------------------------
Sub s_difference(ByRef A As BSet, _
ByRef B As BSet, _
ByRef C As BSet)
Dim As Integer i
For i = 0 To A.nmax
C.T[i] = A.T[i] And Not B.T[i]
Next
End Sub
' Funkcja sprawdza, czy zbiór A jest
' podzbiorem zbioru B
' true - tak, jest
' false - nie, nie jest
'-----------------------------------
Function s_subset(ByRef A As BSet, _
ByRef B As BSet) _
As Integer
Dim As Integer i
For i = 0 To A.nmax
if(A.T[i] And B.T[i]) <> A.T[i] Then
' Jeśli elementu A nie ma w B,
' kończymy z false
Return 0
End If
Next
Return 1
End Function
' Funkcja oblicza liczbę elementów w A
'-------------------------------------
Function s_size(ByRef A As BSet) _
As Integer
' Zerujemy licznik
Dim As Integer i, c = 0
Dim As UInteger m
For i = 0 To A.nmax
m = A.T[i]
While m
' Zliczamy bity równe 1
if(m And 1) = 1 Then c += 1
m shr= 1
Wend
Next
Return c
End Function
' Funkcja sprawdza, czy zbiór A jest pusty
' true - tak, jest pusty
' false - nie, nie jest pusty
'-----------------------------------------
Function s_empty(ByRef A As BSet) _
As Integer
Dim As Integer i
' Pobieramy bity do m
Dim As UInteger m = A.T[0]
For i = 1 To A.nmax
' Sumujemy logicznie bity
m Or = A.T[i]
Next
If m = 0 Then Return 1
Return 0
End Function
' Funkcja bada, czy element x należy
' do zbioru A
' true - tak, należy
' false - nie, nie należy
'----------------------------------
Function s_isin(ByRef A As BSet, _
ByVal x As Integer) _
As Integer
' Obliczamy numer bitu w mapie bitowej
Dim As Integer b = x-A.vmin
If A.T[b Shr 5] And _
(1 Shl (b And 31)) Then Return 1
Return 0
End Function
' Procedura wyświetla elementy zbioru A
'--------------------------------------
Sub s_print(ByRef A As BSet)
Dim As Integer nb, i
Dim As UInteger m
For i = 0 To A.nmax
nb = 0
m = A.T[i]
While m
if(m And 1) = 1 Then _
Print Using "& "; _
(i Shl 5)+nb+A.vmin;
m shr= 1
nb += 1
Wend
Next
End Sub
' **********************
' *** PROGRAM GŁÓWNY ***
' **********************
Dim As BSet A, B, C
Dim As Integer i, x
Randomize
' Tworzymy puste zbiory o zakresie elementów
' od -20 i o liczebności 30
s_create(A, -20, 30)
s_create(B, -20, 30)
s_create(C, -20, 30)
' 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) = 1 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) = 1 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 BSet B? ";_
x;
If s_isin(B, x) = 1 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) = 1 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) = 1 Then
Print "YES"
Else
Print "NO"
End If
Print
' Usuwamy tablice dynamiczne w zbiorach
Delete [] A.T
Delete [] B.T
Delete [] C.T
End
|
| Python (dodatek) |
# Zbiory zaimplementowane w mapach bitowych
# Data: 01.06.2014
# (C)2014 mgr Jerzy Wałaszek
#------------------------------------------
import random
# Definicja struktury zbioru
class BSet:
def __init__(self):
self.vmin = 0
self.nmax = 0
self.t = None
# Procedura dodaje element x
# do zbioru A
#----------------------------
def s_add(a, x):
# Obliczamy numer bitu
b = x - a.vmin
# Obliczamy indeks
i = b >> 3
# Ustawiamy bit na 1
a.t[i] |= 1 << (b & 7)
# Procedura usuwa element x
# ze zbioru
#---------------------------
def s_remove(a, x):
# Obliczamy numer bitu
b = x-a.vmin
# Obliczamy indeks
i = b >> 3
# Ustawiamy bit na 0
a.t[i] &= ~(1 >> (b & 7))
# Procedura usuwa wszystkie
# elementy ze zbioru
#--------------------------
def s_clear(a):
for i in range(a.nmax+1):
# Zerujemy mapę bitową
a.t[i] = 0
# Procedura tworzy zbiór
#-----------------------
def s_create(x, vmn, vmx):
# Wypełniamy strukturę danymi
x.vmin = vmn
# Indeks ostatniego
# elementu tablicy
x.nmax = (vmx-vmn) >> 3
# Tworzymy dynamicznie tablicę
# mapy bitowej
x.t = bytearray(x.nmax+1)
print("nmax = ", x.nmax)
# Procedura wyznacza w C
# sumę zbiorów A i B
#-----------------------
def s_union(a, b, c):
for i in range(a.nmax+1):
c.t[i] = a.t[i] | b.t[i]
# Procedura wyznacza część wspólną
# zbiorów A i B
#---------------------------------
def s_intersection(a, b, c):
for i in range(a.nmax+1):
c.t[i] = a.t[i] & b.t[i]
# Procedura wyznacza różnicę zbiorów A i B
#-----------------------------------------
def s_difference(a, b, c):
for i in range(a.nmax+1):
c.t[i] = a.t[i] & ~b.t[i]
# Funkcja sprawdza, czy zbiór A jest
# podzbiorem zbioru B
# true - tak, jest
# false - nie, nie jest
#-----------------------------------
def s_subset(a, b):
for i in range(a.nmax + 1):
if (a.t[i] & b.t[i]) != a.t[i]:
# Jeśli elementu A nie ma w B,
# kończymy z false
return False
return True
# Funkcja oblicza liczbę elementów w A
#-------------------------------------
def s_size(a):
# Zerujemy licznik
cnt = 0
for i in range(a.nmax + 1):
m = a.t[i]
while m:
# Zliczamy bity równe 1
if m & 1:
cnt += 1
m >>= 1
return cnt
# Funkcja sprawdza, czy zbiór A jest pusty
# true - tak, jest pusty
# false - nie, nie jest pusty
#-----------------------------------------
def s_empty(a):
# Pobieramy bity do m
m = a.t[0]
for i in range(a.nmax + 1):
# Sumujemy logicznie bity
m |= a.t[i]
return not m
# Funkcja bada, czy element x należy
# do zbioru A
# true - tak, należy
# false - nie, nie należy
#----------------------------------
def s_isin(a, x):
# Obliczamy numer bitu
# w mapie bitowej
b = x - a.vmin
if a.t[b >> 3] & (1 << (b & 7)):
return True
return False
# Procedura wyświetla elementy zbioru A
#--------------------------------------
def s_print(a):
for i in range(a.nmax + 1):
nb = 0
m = a.t[i]
while m:
if m & 1:
print((i << 3)+nb+a.vmin,
end=" ")
m >>= 1
nb += 1
# **********************
# *** PROGRAM GŁÓWNY ***
# **********************
a = BSet()
b = BSet()
c = BSet()
# Tworzymy puste zbiory o zakresie elementów
# od -20 i o liczebności 30
s_create(a, -20, 20)
s_create(b, -20, 20)
s_create(c, -20, 20)
# Do zbioru A dodajemy 10 losowych elementów
for i in range(10):
s_add(a, random.randrange(-20,21))
# Do zbioru B dodajemy 15 losowych elementów
for i in range(15):
s_add(b, random.randrange(-20,21))
# 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 in range(7):
s_remove(c, random.randrange(-20,21))
print("IS:", end=" ")
s_print(c)
print(" SUBSET OF A?")
if s_subset(c, a):
print("YES")
else:
print("NO")
print()
s_difference(b, a, c)
# Usuwamy 12 elementów
for i in range(12):
s_remove(c, random.randrange(-20,21))
print("IS:", end=" ")
s_print(c)
print(" SUBSET OF A?")
if s_subset(c, a):
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=" ")
s_remove(a, x)
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 in range(10):
x = random.randrange(-20,21)
print("IS ELEMENT%4d IN SET B? " % x,
end="")
if s_isin(b, x):
print("YES")
else:
print("NO")
print()
# Sprawdzenie testu na zbiór pusty
print("IS SET A EMPTY?")
if s_empty(a):
print("YES")
else:
print("NO")
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):
print("YES")
else:
print("NO")
print()
|
| Wynik: |
-17 -15 -11 -7 -6 -3 -2 7 14 15 SIZE OF A IS 10 B: -18 -17 -14 -13 -12 -9 -7 -5 -1 6 7 10 16 18 SIZE OF B IS 14 UNION OF A AND B: -18 -17 -15 -14 -13 -12 -11 -9 -7 -6 -5 -3 -2 -1 6 7 10 14 15 16 18 SIZE OF UNION IS 21 INTERSECTION OF A AND B: -17 -7 7 SIZE OF INTERSECTION IS 3 DIFFERENCE OF A AND B: -15 -11 -6 -3 -2 14 15 SIZE OF DIFFERENCE IS 7 IS: -17 -15 -11 -7 -6 -3 14 15 SUBSet OF A? TRUE IS: -13 -9 -5 -1 6 16 18 SUBSet OF A? FALSE FROM A WE REMOVE 12 18 -8 -3 -14 A: -17 -15 -11 -7 -6 -2 7 14 15 SIZE OF A IS 9 IS ELEMENT -3 IN SET B? NO IS ELEMENT 15 IN SET B? NO IS ELEMENT 13 IN SET B? NO IS ELEMENT -20 IN SET B? NO IS ELEMENT 13 IN SET B? NO IS ELEMENT -7 IN SET B? YES IS ELEMENT -17 IN SET B? YES IS ELEMENT 5 IN SET B? NO IS ELEMENT 19 IN SET B? NO IS ELEMENT 11 IN SET B? NO IS SET A EMPTY? FALSE IS INTERSECTION OF A AND DIFFERENCE OF B AND A EMPTY? TRUE |
![]() |
Zespół Przedmiotowy Chemii-Fizyki-Informatyki w I Liceum Ogólnokształcącym im. Kazimierza Brodzińskiego w Tarnowie ul. Piłsudskiego 4 ©2026 mgr Jerzy Wałaszek |
Materiały tylko do użytku dydaktycznego. Ich kopiowanie i powielanie jest dozwolone pod warunkiem podania źródła oraz niepobierania za to pieniędzy.
Pytania proszę przesyłać na adres email:
Serwis wykorzystuje pliki cookies. Jeśli nie chcesz ich otrzymywać, zablokuj je w swojej przeglądarce.
Informacje dodatkowe.