Transcript wyk2
Algorytmy i Struktury Danych
Struktury Danych
WYKŁAD 2
PROWADZĄCY: DR PAWEŁ DROZDA
Plan Wykładu
Tablice
Stosy
Kolejki
Listy
Drzewa
dr Paweł Drozda
Struktury danych – po co?
porządkowanie informacji na komputerach w formie
zrozumiałej dla człowieka
pomocne narzędzie przy rozwiązywaniu
skomplikowanych problemów algorytmicznych
listy – ułatwiają tworzenie elastycznych baz danych
drzewa binarne – ułatwiają analizę wyrażeń
arytmetycznych
grafy – duże zastosowanie w dziedzinie sztucznej
inteligencji
dr Paweł Drozda
Tablice (1)
Najprostsza struktura danych
Kontener zawierający N elementów typu T
Dostęp do elementów przy pomocy indeksu (pozycji)
Operacje
USTAW(τ, x, p) – w tablicy τ wstaw element x na pozycji p
POBIERZ(τ, p) – z tablicy τ odczytaj element na pozycji p
USUŃ(τ, p) – z tablicy τ usuń element na pozycji p
Przykład: tablica liczb całkowitych
indeks
0
1
2
3
4
1
2
3
5
7
5
6
7
8
9
11 13 17 19 23
element tablicy o indeksie 2, zawierający
wartość 3
dr Paweł Drozda
Tablice (2)
Tworzenie tablicy w C++
T nazwa[const rozmiar];
int tab[100];
char znaki[] = {‘x’, ’y’, ’z’};
Dostęp do elementów
indeksy: 0,…,N-1
tab[0] = 1;
int x = tab[i];
Rozmiar tablicy musi być znany a priori (tablica statyczna)
dr Paweł Drozda
Tablica – przykład
#include <iostream>
int main()
{
int tab[4];
tab[0] = 12;
tab[1] = 65;
tab[2] = 44;
tab[3] = 7;
int suma = 0;
for (int i=0; i<4; i++)
{
suma = suma + tab[i];
}
std::cout << suma;
return 0;
}
dr Paweł Drozda
void usun (int tab, int p)
{
for (i=p; i<length(tab); i++)
tab[i]=tab[i+1];
}
void wstaw(int tab, int p, int x)
{
tab[p]=x;
}
void wstaw1 (int tab, int p, int x)
{
for ()
tab[p]=x;
}
Tablice wielowymiarowe
Deklaracja tablicy wielowymiarowej
T tab[N1] [N2]…[Nk]
można zapisać N1 *N2*…*Nk
elementów w tablicy
Przykład
int tab[2][2][2];
tab[][][]={{1,2,3},{1,4,3},{5,6,7},{7,6,5},{2,2,2}}
Dostęp do elementów
poprzez indeksy n1 n2…nk
Przykład – tablica dwuwymiarowa
(macierz)
tab[0][0]=1
tab[1][2]=5
dr Paweł Drozda
#include <iostream>
int main()
{
int tab[10][10];
for (int i=0;i<9;i++)
{
for (int j=0;j<9;j++)
{
tab[i][j] = i*j;
tab[j][i] = i*j;
}
}
std::cout << tab[4][7];
return 0;
}
Stos
dostęp tylko od wierzchołka
zasada działania tzw. LIFO (Last In First Out)
Dostępne dwie podstawowe funkcje:
Top
PUSH(S,X) – umieszczenie elementu na stosie
POP(S) – zdjęcie elementu ze stosu
Każdy element składa się z dwóch pól:
dane – dowolna zmienna
wskaźnik - zawiera informacje o miejscu
przechowania kolejnego elementu na stosie
Dodatkowy element:
Top – przechowuje wskaźnik do szczytu stosu
Dodatkowe funkcje stosu:
przepełnienie - dla stosu o zadeklarowanej max
wielkości
stos pusty – sprawdza czy stos nie jest pusty
dr Paweł Drozda
dane3
wskaźnik
dane2
wskaźnik
ogniwo
dane1
wskaźnik
…
Przykład – użycie stosu
push(S,1)
push(S,5)
push(S,3)
3
5
1
PUSTO
pop(S)
-> 3
top(S) -> 5
S
dr Paweł Drozda
pop(S)
->5
Implementacja stosu - wskaźniki
void push (int x)
{
ELEMENT *q = new ELEMENT;
if (top==NULL)
{
q->wartosc=x;
top=q;
}
else{
q-> wartosc =x;
q-> next=top;
top=q;
}
dr Paweł Drozda
Stos jako tablica
1
2
3
4
12
4
5
6
5
6
7
7
START,
Wielkość stosu 6
top[S]=4
1
2
3
4
5
6
12
4
5
6
4
5
PUSH(S,4), PUSH(S,5)
PUSH(S,7) – przepełnienie!!
top[S]=6
1
2
3
12
4
5
top[S]=3
dr Paweł Drozda
4
5
6
7
POP(S), POP(S), POP(S)
Stos jako tablica - implementacja
int Pusty(S){
if (top(S)==0) return true;
else return false;
}
void Push(S,x){
top(S)=top(S)+1;
S[top(S)]=x;
}
Pop(S){
If Pusty(S) error „nie ma co zdjac”;
else { top(S)--;
return S[top(S)+1];}
}
dr Paweł Drozda
Kolejka
Zasada działania – FIFO (First In First Out)
Podstawowe funkcje:
ENQUEUE(Q,x) – dodanie elementu x do kolejki
DEQUEUE(Q) – zdjęcie elementu z kolejki
Struktura elementu:
wartość elementu
wskaźnik do elementu następnego w kolejce
Elementy dodatkowe
Head – przechowuje wskaźnik do początku kolejki
Tail – przechowuje wskaźnik do końca kolejki
head
tail
dane1
wskaźnik
dr Paweł Drozda
dane2
wskaźnik
dane3
wskaźnik
Przykład – użycie kolejki
Enqueue(Q,2)
Enqueue(Q,5)
Enqueue(Q,3)
DEQUEUE(Q)
HEAD(Q) -> 5
Dequeue(Q)
2
dr Paweł Drozda
5
3
Implementacja kolejki
void dequeue(Q){
if (head!=NULL)
head=head->next;
else error „nic nie ma w kolejce”;
}
void enqueue(Q, x){
ELEMENT *q= new ELEMENT;
q->wartosc=x;
tail->next=q;
tail=q;
}
dr Paweł Drozda
Kolejka za pomocą tablicy
1
2
3
4
5
6
7
12
4
5
6
START
Head(Q)=4, Tail(Q)=7
1
2
14
1
3
4
5
6
7
12
4
5
6
6
7
5
6
ENQUEUE(Q,4),
ENQUEUE(Q,1)
Tail(Q)=2, Head(Q)=4
1
2
14
1
3
4
5
Tail(Q)=2, Head(Q)=6
dr Paweł Drozda
DEQUEUE(Q),
DEQUEUE(Q)
Kolejka – implementacja tablicy
void dequeue(Q){
x = Q[head(Q)];
If (head(Q)= length(Q)) head(Q)=1;
else head(Q)++;
return x;
}
void enqueue(Q,x){
if (tail(Q))==lenght(Q)) tail(Q)=1;
else tail(Q)++;
Q[tail(Q)]=x;
}
dr Paweł Drozda
Problem
Jak za pomocą dwóch kolejek stworzyć stos?
Kolejka 2
Kolejka 1
2
5
2
5
Jak za pomocą dwóch stosów stworzyć kolejkę?
dr Paweł Drozda
3
Listy (1)
Struktura danych z elementami ułożonymi w
liniowym porządku – porządek ustalony przez
wskaźniki
Element złożony:
lista jednokierunkowa: wartość i wskaźnik
lista dwukierunkowa wartość,
dwa wskaźniki
head
tail
Lista
jednokierunkowa
dr Paweł Drozda
wartość
wartość
wartość
następny
następny
NULL
Listy (2)
Podstawowe funkcje
Search(L, x) – znajduje wskaźnik do elementu o kluczu x, bądź
NULL gdy nie ma elementu z kluczem x
Insert (L, x, w) – wstawia element o kluczu x w miejscu
wskazywanym przez w
Delete (L,w) – usuwa element wskazywany przez w
Min(L) – zwraca element o najmniejszym kluczu
Max(L) – zwraca element o największym kluczu
head
tail
wartość
wartość
wartość
prev | next
prev | next
prev | next
dr Paweł Drozda
Lista
dwukierunkowa
Tworzenie listy
Head(L)
Tail(L)
/
3
Insert(L,3,Head)
Insert(L,5,Tail)
Insert(L,6,Tail)
Insert(L,3,Tail)
Search(L,5)
dr Paweł Drozda
5
6
Delete(L,Tail)
Tail(L)
7
/
Lista jednokierunkowa
Dodanie elementu pomiędzy dwa istniejące
wartość
wartość
wartość
następny
następny
NULL
wartość
następny
dr Paweł Drozda
Listy - implementacja
Search (L,x){
temp=head(L);
while ((temp->next!=null) &&(temp->wartosc!=x))
temp=temp->next;
return temp;
}
Insert(L,x){ // na koniec listy
ELEMENT q = new ELEMENT;
tail->next=q;
tail=q;
q->wartosc=x;
}
dr Paweł Drozda
Listy - własności
Liniowe uporządkowanie elementów
Elastyczność
wstawianie / usuwanie na dowolnej pozycji
dynamiczna długość
Brak bezpośredniego dostępu do i-go elementu (O(n))
Dodatkowy koszt pamięciowy (wskaźniki)
Drzewa binarne (1)
Węzeł reprezentowany za pomocą rekordów
klucz węzła
parent
wskaźnik do ojca
klucz
left right
wskaźnik do lewego syna
wskaźnik do prawego syna
parent
klucz
left
parent
klucz
left
dr Paweł Drozda
right
parent
klucz
left
right
right
parent
parent
klucz
parent
klucz
klucz
left
right
left
right
left
right
Drzewo binarne (2)
Oznaczenia
root(T) – wierzchołek korzenia – gdy wskaźnik parent
wskazuje na NULL
leaf(T) – wierzchołek liścia – gdy wskaźniki left i right
wskazują na NULL
dr Paweł Drozda