Podstawy informatyki 2 - PB Wydział Elektryczny

Transkrypt

Podstawy informatyki 2 - PB Wydział Elektryczny
Podstawy informatyki 2
Politechnika Białostocka - Wydział Elektryczny
Elektrotechnika, semestr II, studia stacjonarne
Rok akademicki 2006/2007
Wykład nr 2 (07.03.2007)
dr inŜ. Jarosław Forenc
Podstawy informatyki 2
Wykład nr 2
Plan wykładu nr 2
Argumenty funkcji main
Dynamiczne struktury danych
stos
kolejka
lista
jednokierunkowa
dwukierunkowa
cykliczna
drzewo
binarne
dr inŜ. Jarosław Forenc
2/46
Podstawy informatyki 2
Wykład nr 2
dr inŜ. Jarosław Forenc
3/46
Argumenty funkcji main
int main(int argc, char *argv[])
argc (ang. argument count) - liczba argumentów, z jakimi program
został wywołany
argv (ang. argument vector) - wskaźnik do tablicy zawierającej argumenty
wywołania programu umieszczone w wierszu polecenia
Przykład:
C:\>pr.exe par1 par2 par3
argv
”C:\pr.exe”
”par1”
”par2”
”par3”
NULL
argc = 4
argv[0] =
argv[1] =
argv[2] =
argv[3] =
”C:\pr.exe”
”par1”
”par2”
”par3”
Podstawy informatyki 2
Wykład nr 2
dr inŜ. Jarosław Forenc
4/46
Argumenty funkcji main
C:\>pr.exe par1 par2 par3
Argumenty funkcji main:
argc
= 4
argv[0] = pr.exe
argv[1] = par1
argv[2] = par2
argv[3] = par3
#include <stdio.h>
int main(int argc, char *argv[])
{
int i;
printf("Argumenty funkcji main:\n");
printf("argc
= %d\n",argc);
for (i=0;i<argc;i++)
printf("argv[%d] = %s\n",i,argv[i]);
return 0;
}
Wyświetlenie argumentów funkcji main
w przypadku programów uruchamianych bezpośrednio ze środowiska Dev-C++
argumenty wpisuje się wybierając: „Uruchom Parametry”
Podstawy informatyki 2
Wykład nr 2
dr inŜ. Jarosław Forenc
5/46
Dynamiczne struktury danych
Dynamiczne struktury danych są to proste i złoŜone struktury danych,
którym pamięć moŜe być przydzielana i zwalniana w trakcie
wykonywania programu
Elementami takich struktur mogą być:
dane typów prostych, np. liczby, znaki
dane typów złoŜonych, np. struktury, tablice, obiekty
Do podstawowych dynamicznych struktur danych naleŜą:
stos
kolejka
listy:
jednokierunkowa
dwukierunkowa
cykliczna, jednokierunkowa
cykliczna, dwukierunkowa
drzewa
Podstawy informatyki 2
Wykład nr 2
dr inŜ. Jarosław Forenc
6/46
Stos
stos (ang. stack) jest strukturą danych składającą się z elementów, z których
kaŜdy posiada tylko adres następnika
dostęp do danych przechowywanych na stosie jest moŜliwy tylko w miejscu
określanym mianem wierzchołka stosu (ang. top)
wierzchołek stosu jest jedynym miejscem, do którego moŜna dołączać lub
z którego moŜna usuwać elementy
top
data
data
data
next
next
next
tutaj dodajemy i
usuwamy elementy
NULL
wierzchołek
kaŜdy składnik stosu posiada wyróŜniony element (wskaźnik next) zawierający
adres następnego elementu
wskaźnik ostatniego elementu stosu wskazuje na adres pusty (NULL)
dane (data) są umowną nazwą pewnych struktur
Podstawy informatyki 2
Wykład nr 2
dr inŜ. Jarosław Forenc
7/46
Stos
nazwa stos odnosi się ściśle do funkcjonowania tej struktury - stos przypomina
stertę kartek, na której wierzchołku moŜna połoŜyć kartkę lub ją zdjąć
struktura stosu bywa nazywana stosem
LIFO (ang. Last In First Out - ostatni
wchodzi, pierwszy wychodzi)
podstawowe operacje na stosie to:
podnie
połó
zdjęcie elementu ze stosu, czyli pobranie
elementu ze stosu - funkcja pop()
ródło: A. Zalewski: „Programowanie
w j zykach C i C++ z wykorzystaniem
pakietu Borland C++”
ę
dodanie elementu do stosu, czyli połoŜenie
elementu na stosie - funkcja push()
ź
Podstawy informatyki 2
Wykład nr 2
dr inŜ. Jarosław Forenc
8/46
Stos
Implementacja w języku C:
dane przechowywane na stosie są najczęściej pewną strukturą - dla uproszczenia
przyjmijmy, Ŝe struktura skład się tylko z jednego pola typu int
struct element
{
int x;
};
kaŜdy składnik stosu skład się z „uŜytecznych” danych przechowywanych na stosie
(data) oraz ze wskaźnika (next) zawierającego adres następnego elementu
struct stos
{
struct element data;
struct stos *next;
};
data
next
Podstawy informatyki 2
Wykład nr 2
dr inŜ. Jarosław Forenc
9/46
Stos
Implementacja w języku C - połoŜenie elementu na stosie:
funkcja dodająca element do stosu ma postać:
struct stos *push(struct stos *top, struct element data)
{
struct stos *wsk;
wsk = (struct stos*) malloc(sizeof(struct stos));
wsk->next = top;
wsk->data = data;
return wsk;
}
przykładowe wywołanie funkcji:
top = push(top,data);
przed pierwszym wywołaniem funkcji push(), wskaźnik top musi mieć wartość NULL
Podstawy informatyki 2
Wykład nr 2
dr inŜ. Jarosław Forenc
Stos
Implementacja w języku C - zdjęcie elementu ze stosu:
funkcja usuwająca element ze stosu ma postać:
struct stos *pop(struct stos *top, struct element *data)
{
struct stos *wsk;
if (top!=NULL)
{
wsk = top->next;
*data = top->data;
free(top);
return wsk;
}
else return NULL;
}
przykładowe wywołanie funkcji:
top = pop(top,&data);
10/46
Podstawy informatyki 2
Wykład nr 2
dr inŜ. Jarosław Forenc
11/46
Stos - przykład (1/3)
#include <stdio.h>
#include <stdlib.h>
struct element
{
int x;
};
struct stos
{
struct element data;
struct stos *next;
};
Implementacja stosu w języku C
Podstawy informatyki 2
Wykład nr 2
dr inŜ. Jarosław Forenc
12/46
Stos - przykład (2/3)
struct stos *push(struct stos *top, struct element data)
{
struct stos *wsk;
wsk = (struct stos*) malloc(sizeof(struct stos));
wsk->next = top;
wsk->data = data;
return wsk;
}
struct stos *pop(struct stos *top, struct element *data)
{
struct stos *wsk;
if (top!=NULL)
{
wsk = top->next;
*data = top->data;
free(top);
return wsk;
}
else
return NULL;
}
Implementacja stosu w języku C
Podstawy informatyki 2
Wykład nr 2
dr inŜ. Jarosław Forenc
13/46
Stos - przykład (3/3)
int main()
{
int tab[5] = {1,2,3,4,5};
struct stos *top = NULL;
struct element data;
int i;
for (i=0;i<5;i++)
{
data.x = tab[i];
top = push(top,data);
printf("push() --> %d\n",data.x);
}
push()
push()
push()
push()
push()
pop()
pop()
pop()
pop()
pop()
-->
-->
-->
-->
-->
-->
-->
-->
-->
-->
1
2
3
4
5
5
4
3
2
1
printf("\n");
while (top!=NULL)
{
top=pop(top,&data);
printf("pop() --> %d\n",data.x);
}
system("pause");
return 0;
}
Implementacja stosu w języku C
Podstawy informatyki 2
Wykład nr 2
dr inŜ. Jarosław Forenc
14/46
Stos
Tablicowa implementacja stosu:
przedstawiona wcześniej struktura stosu jest to tzw. listowa implementacja stosu
istniej takŜe tablicowa implementacja stosu
0
1
2
3
4
5
data
data
data
data
data
6
wska nik=5
rozmiar tablicy jest stały i określany w momencie tworzenia stosu
elementy stosu przechowywane są w tablicy, przy czym im później element został
połoŜony, tym dalej w tablicy się znajduje
wskaźnik stosu określa indeks tablicy, pod który zapisana zostanie następna dana
umieszczana na stosie
przy umieszczaniu danej na stosie indeks jest zwiększany, zaś przy zdejmowaniu
danej ze stosu - zmniejszany
Podstawy informatyki 2
Wykład nr 2
dr inŜ. Jarosław Forenc
15/46
Notacja polska
notacja polska (zapis przedrostkowy, Notacja Łukasiewicza) jest to sposób zapisu
wyraŜeń arytmetycznych, podający najpierw operator, a następnie argumenty
wyraŜenie arytmetyczne:
ma w notacji polskiej postać:
wyraŜenie w notacji polskiej nie wymaga nawiasów, poniewaŜ przypisanie
argumentów do operatorów wynika wprost z ich kolejności w zapisie
notacja polska jest bliska naturalnemu sposobowi wyraŜania działań, w którym
zazwyczaj najpierw podaje się czynność, a następnie dopełnia wyraŜenia
wskazaniem rzeczy, do których czynność się odnosi, np.
4 / (1 + 3)
/ 4 + 1 3
„podziel cztery przez sumę jednego i trzech”
notację polską przedstawił w 1920 roku polski matematyk Jan Łukasiewicz
zapis wyraŜeń w notacji polskiej stał się podstawą języków: Logo, Tcl i LISP
notacja polska była podstawą opracowania tzw. odwrotnej notacji polskiej
Podstawy informatyki 2
Wykład nr 2
dr inŜ. Jarosław Forenc
16/46
Odwrotna notacja polska
odwrotna notacja polska - ONP (ang. Reverse Polish Notation, RPN) jest sposobem
zapisu wyraŜeń arytmetycznych, w którym znak wykonywanej operacji
umieszczany jest po argumentach, a nie pomiędzy nimi jak w konwencjonalnym
zapisie algebraicznym
wyraŜenie arytmetyczne:
ma w odwrotnej notacji polskiej postać:
ONP została opracowana przez australijskiego naukowca Charlesa Hamblina
jako „odwrócenie” beznawiasowej notacji polskiej Jana Łukasiewicza
na potrzeby zastosowań informatycznych
zapis wyraŜenia w ONP pozwala na całkowita rezygnację z uŜycia nawiasów
w wyraŜeniach, gdyŜ jednoznacznie określa kolejność wykonywania działań
ONP uŜywana jest w niektórych językach programowania (FORTH, Postscript)
oraz w kalkulatorach naukowych HP:
(1 + 3) / 2
1 3 + 2 /
programy komputerowe kompilujące program analizują wyraŜenie arytmetyczne
i przekształcają je na ciąg instrukcji odpowiadający odwrotnej notacji polskiej
otrzymane wyraŜenie obliczane jest podczas wykonywania programu
Podstawy informatyki 2
Wykład nr 2
dr inŜ. Jarosław Forenc
17/46
Odwrotna notacja polska
obliczenie wartości wyraŜenia arytmetycznego przy zastosowaniu odwrotnej notacji
polskiej wymaga wykonania dwóch operacji:
zamiany notacji konwencjonalnej (nawiasowej) na odwrotną notację polską
obliczenia wartości wyraŜenia arytmetycznego zapisanego w odwrotnej notacji polskiej
oba powyŜsze algorytmy są bardzo proste i wykorzystują stos
Zamiana wyraŜenia z notacji konwencjonalnej na ONP:
zamiana wykonywana jest przy zastosowaniu algorytmu Dijkstry nazywanego
stacją rozrządową
czytając wyraŜenie arytmetyczne od strony lewej do strony prawej operatory
odkładamy na stos a liczby na wyjście
wyjście naleŜy traktować jako kolejkę, która po zakończeniu algorytmu będzie
zawierała wyraŜenie w odwrotnej notacji polskiej
Podstawy informatyki 2
Wykład nr 2
dr inŜ. Jarosław Forenc
18/46
Odwrotna notacja polska
Zamiana wyraŜenia z notacji konwencjonalnej na ONP:
wykonując powyŜsze operacje trzeba stosować następujące reguły:
operator moŜemy odłoŜyć na stos tylko wtedy, jeśli ostatnim elementem stosu jest
operator o niŜszym priorytecie
jeŜeli ma on wyŜszy lub równy priorytet to zdejmujemy ze stosu dotąd elementy
i wysyłamy na wyjście, aŜ ostatni operator będzie miał niŜszy priorytet lub stos
będzie pusty
jeśli kolejnym elementem jest nawias otwierający „(”, to odkładamy go na stos,
bez względu na to co znajduje się w danym momencie na stosie i bez względu
na to czy stos jest pusty
powyŜszy nawias traktujemy jak dno stosu i odczytujemy kolejne elementy wyraŜenia
według standardowego algorytmu
jeśli dojdziemy do nawiasu zamykającego „)”, to nigdzie go nie odkładamy,
tylko zdejmujemy kolejne operatory ze stosu i wysyłamy na wyjście, aŜ dojdziemy
do nawiasu otwierającego, który równieŜ zdejmujemy ze stosu i wysyłamy na wyjście
jeśli dojdziemy do końca wyraŜenia arytmetycznego, to zdejmujemy ze stosu pozostałe
operatory i wysyłamy je na wyjście
Podstawy informatyki 2
Wykład nr 2
dr inŜ. Jarosław Forenc
19/46
Odwrotna notacja polska
Zamiana wyraŜenia z notacji konwencjonalnej na ONP - przykład:
równanie w notacji konwencjonalnej:
Krok
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
równanie w ONP:
(2+1)*3-4*(7+4)
Wejście
Stos
(
2
+
1
)
*
3
4
*
(
7
+
4
)
Koniec
( NULL
( NULL
+ ( NULL
+ ( NULL
NULL
* NULL
* NULL
- NULL
- NULL
* - NULL
( * - NULL
( * - NULL
+ ( * - NULL
+ ( * - NULL
* - NULL
- NULL
NULL
Wyjście
2
1
+
3
*
4
7
4
+
*
-
2 1 + 3 * 4 7 4 + * -
Podstawy informatyki 2
Wykład nr 2
dr inŜ. Jarosław Forenc
20/46
Odwrotna notacja polska
Obliczenie wartości wyraŜenia arytmetycznego w ONP:
w algorytmie obliczania wartości wyraŜenia arytmetycznego zapisanego
w odwrotnej notacji polskiej wykonujemy następujące operacje:
pobieramy kolejny element wyraŜenia
jeśli elementem jest liczba to odkładamy ją na stos
jeśli elementem jest operator, to pobieramy ze stosu tyle liczb, aby moŜna było
„zastosować” operator na tych liczbach, np. dla dodawania, odejmowania, mnoŜenia
i dzielenia są to dwie kolejne liczby, zaś dla negacji - jedna liczba
wykonujemy operację na liczbach i jej wynik odkładamy na stos
jeśli dotrzemy do końca wyraŜenia, to pobieramy wynik ze stosu, który jest wartością
wyraŜenia arytmetycznego
jeśli nie ma jeszcze końca, to wracamy na początek algorytmu
Uwaga:
jeśli np. stos ma postać: 2 4 NULL i mamy wykonać operację dzielenia /,
to operacja ta ma postać: 4 / 2, czyli do wykonania operacji argumenty
brane są w odwrotnej kolejności
Podstawy informatyki 2
Wykład nr 2
dr inŜ. Jarosław Forenc
21/46
Odwrotna notacja polska
Obliczenie wartości wyraŜenia arytmetycznego w ONP - przykład:
równanie w ONP:
Krok
1
2
3
4
5
6
7
8
9
10
11
12
równanie w ONP:
2 1 + 3 * 4 7 4 + * Wejście
Stos
2
1
+
3
*
4
7
4
+
*
Koniec
2 NULL
1 2 NULL
3 NULL
3 3 NULL
9 NULL
4 9 NULL
7 4 9 NULL
4 7 4 9 NULL
11 4 9 NULL
44 9 NULL
-35 NULL
-35
NULL
Działanie
2 + 1
3 * 3
7 + 4
4 * 11
9 – 44
wynik: -35
Podstawy informatyki 2
Wykład nr 2
dr inŜ. Jarosław Forenc
22/46
Kolejka
kolejka (ang. queue) jest strukturą danych składającą się z liniowo
uporządkowanych elementów, do której moŜna dołączać elementy tylko w jednym
końcu (na końcu kolejki), a usuwać tylko w drugim końcu (na początku kolejki)
kolejka często określana jest jako stos FIFO (ang. First In First Out - pierwszy
wchodzi, pierwszy wychodzi)
powiązanie między elementami kolejki jest takie samo, jak w przypadku stosu
head
tail
data
data
data
next
next
next
tutaj usuwamy
elementy
pocz tek kolejki
tutaj dodajemy
elementy
NULL
koniec kolejki
head jest wskaźnikiem na pierwszy element kolejki (początek kolejki), zaś tail - na
ostatni element kolejki (koniec kolejki)
Podstawy informatyki 2
Wykład nr 2
dr inŜ. Jarosław Forenc
23/46
Kolejka
korzystając z poprzedniej analogii, stosu kartek, moŜemy powiedzieć, Ŝe kładziemy
kartki na wierzchołku stosu, zaś wyjmujemy ze spodu
kolejkę moŜna takŜe wyobraŜać sobie
jako typową kolejkę sklepową
podstawowe operacje dotyczące
kolejki to:
usunięcie elementu z kolejki
- Remove() lub dequeue()
usu
ródło: A. Zalewski: „Programowanie
w j zykach C i C++ z wykorzystaniem
pakietu Borland C++”
ę
dołączenie elementu do kolejki
- Insert() lub enqueue()
ź
wstaw
Podstawy informatyki 2
Wykład nr 2
dr inŜ. Jarosław Forenc
24/46
Kolejka
Implementacja w języku C:
dane przechowywane w kolejce są najczęściej pewną strukturą - dla uproszczenia
przyjmijmy, Ŝe struktura skład się tylko z jednego pola typu int
struct element
{
int x;
};
kaŜdy składnik kolejki skład się z „uŜytecznych” danych przechowywanych w
kolejce (data) oraz ze wskaźnika (next) zawierającego adres następnego elementu
struct kolejka
{
struct element data;
struct kolejka *next;
};
data
next
Podstawy informatyki 2
Wykład nr 2
dr inŜ. Jarosław Forenc
25/46
Kolejka
Implementacja w języku C - dołączenie elementu do kolejki:
funkcja dodająca element do kolejki ma postać:
struct kolejka *Insert(struct kolejka *tail, struct element data)
{
struct kolejka *wsk;
wsk = (struct kolejka*) malloc(sizeof(struct kolejka));
wsk->data = data;
wsk->next = NULL;
if (tail != NULL) tail->next = wsk;
return wsk;
}
przykładowe wywołanie funkcji:
head = tail = Insert(tail,data);
tail = Insert(tail,data);
/* pierwsze wywołanie */
/* kolejne wywołania */
przed pierwszym wywołaniem funkcji head i tail powinny mieć wartość NULL
Podstawy informatyki 2
Wykład nr 2
dr inŜ. Jarosław Forenc
26/46
Kolejka
Implementacja w języku C - usunięcie elementu z kolejki:
funkcja usuwająca element z kolejki ma postać:
struct kolejka *Remove(struct kolejka *head, struct element *data)
{
struct kolejka *wsk;
if (head!=NULL)
{
wsk = head->next;
*data = head->data;
free(head);
return wsk;
}
else return NULL;
}
przykładowe wywołanie funkcji:
head = Remove(head,&data);
Podstawy informatyki 2
Wykład nr 2
dr inŜ. Jarosław Forenc
27/46
Kolejka - przykład (1/3)
#include <stdio.h>
#include <stdlib.h>
struct element
{
int x;
};
struct kolejka
{
struct element data;
struct kolejka *next;
};
Implementacja kolejki w języku C
Podstawy informatyki 2
Wykład nr 2
dr inŜ. Jarosław Forenc
28/46
Kolejka - przykład (2/3)
struct kolejka *Insert(struct kolejka *tail, struct element data)
{
struct kolejka *wsk;
wsk = (struct kolejka*) malloc(sizeof(struct kolejka));
wsk->data = data;
wsk->next = NULL;
if (tail != NULL) tail->next = wsk;
return wsk;
}
struct kolejka *Remove(struct kolejka *head, struct element *data)
{
struct kolejka *wsk;
if (head!=NULL)
{
wsk = head->next;
*data = head->data;
free(head);
return wsk;
}
else return NULL;
}
Implementacja kolejki w języku C
Podstawy informatyki 2
Wykład nr 2
dr inŜ. Jarosław Forenc
29/46
Kolejka - przykład (3/3)
int main()
{
int tab[5] = {1,2,3,4,5};
struct kolejka *head, *tail;
struct element data;
int i;
head = tail = NULL;
for (i=0;i<5;i++)
{
data.x = tab[i];
if (i==0)
head = tail = Insert(tail,data);
else
tail = Insert(tail, data);
printf("Insert() --> %d\n",data.x);
}
Insert()
Insert()
Insert()
Insert()
Insert()
-->
-->
-->
-->
-->
1
2
3
4
5
Remove()
Remove()
Remove()
Remove()
Remove()
-->
-->
-->
-->
-->
1
2
3
4
5
printf("\n");
while (head!=NULL)
{
head = Remove(head,&data);
printf("Remove() --> %d\n",data.x);
}
return 0;
}
Implementacja kolejki w języku C
Podstawy informatyki 2
Wykład nr 2
dr inŜ. Jarosław Forenc
30/46
Lista
listą (liniową) nazywamy liniowo uporządkowany zbiór elementów, z którego
w dowolnym miejscu moŜna usunąć element, jak równieŜ dołączyć nowy element
sposób budowy listy jest ściśle uzaleŜniony od zamierzeń programisty
elementy moŜna wstawiać do listy na początku, na końcu lub w dowolnym innym
miejscu (np. w celu przechowywania elementów posortowanych)
w zaleŜności od powiązań pomiędzy elementami wyróŜniamy listy:
jednokierunkowe
dwukierunkowe
cykliczne, jednokierunkowe
cykliczne, dwukierunkowe
Podstawy informatyki 2
Wykład nr 2
dr inŜ. Jarosław Forenc
31/46
Lista jednokierunkowa
organizacja listy jednokierunkowej podobna jest do organizacji stosu i kolejki,
tzn. dla kaŜdego składnika (poza ostatnim) jest określony następny składnik
(lub poprzedni - zaleŜnie od implementacji)
zapamiętywany jest wskaźnik tylko na pierwszy element listy lub wskaźniki na
pierwszy i ostatni element listy
first
elementy wstawiamy
i usuwamy w dowolnym
miejscu
last
data
data
data
next
next
next
pocz tek listy
koniec listy
NULL
Podstawy informatyki 2
Wykład nr 2
dr inŜ. Jarosław Forenc
32/46
Lista jednokierunkowa
Implementacja w języku C:
dane przechowywane na liście są najczęściej pewną strukturą - dla uproszczenia
przyjmijmy, Ŝe struktura skład się tylko z jednego pola typu int
struct element
{
int x;
};
kaŜdy składnik listy skład się z „uŜytecznych” danych przechowywanych na liście
(data) oraz ze wskaźnika (next) zawierającego adres następnego elementu
struct lista
{
struct element data;
struct lista *next;
};
data
next
Podstawy informatyki 2
Wykład nr 2
dr inŜ. Jarosław Forenc
33/46
Lista jednokierunkowa
Implementacja w języku C - dołączenie elementu na początku listy:
funkcja dodająca element na początku listy ma postać:
struct lista *dodaj_pierwszy(struct lista *first, struct element data)
{
struct lista *wsk;
wsk = (struct lista*) malloc(sizeof(struct lista));
wsk->data = data;
wsk->next = first;
return wsk;
}
przykładowe wywołanie funkcji:
first = last = dodaj_pierwszy(first,data); /* pierwsze wywołanie */
first = dodaj_pierwszy(first,data);
/* kolejne wywołania */
przed pierwszym wywołaniem funkcji wskaźnik first powinien mieć wartość NULL
Podstawy informatyki 2
Wykład nr 2
dr inŜ. Jarosław Forenc
34/46
Lista jednokierunkowa
Implementacja w języku C - dołączenie elementu na końcu listy:
funkcja dodająca element na końcu listy ma postać:
struct lista *dodaj_ostatni(struct lista *last, struct element data)
{
struct lista *wsk;
wsk = (struct lista*) malloc(sizeof(struct lista));
wsk->data = data;
wsk->next = NULL;
if (last!=NULL) last->next = wsk;
return wsk;
}
przykładowe wywołanie funkcji:
first = last = dodaj_ostatni(last,data); /* pierwsze wywołanie */
last = dodaj_ostatni(last,data);
/* kolejne wywołania */
przed pierwszym wywołaniem funkcji wskaźnik last powinien mieć wartość NULL
Podstawy informatyki 2
Wykład nr 2
dr inŜ. Jarosław Forenc
Lista jednokierunkowa
Implementacja w języku C - usunięcie wszystkich elementów:
funkcja usuwająca wszystkie elementy z listy ma postać:
struct lista *usun_wszystko(struct lista *first)
{
struct lista *wsk;
while (first!=NULL)
{
wsk = first->next;
free(first);
first = wsk;
}
return first;
}
przykładowe wywołanie funkcji:
first = last = usun_wszystko(first);
35/46
Podstawy informatyki 2
Wykład nr 2
dr inŜ. Jarosław Forenc
Lista jednokierunkowa
Implementacja w języku C - wyświetlenie wszystkich elementów:
funkcja wyświetlająca wartość wszystkich elementów listy:
void wyswietl_liste(struct lista *first)
{
while (first!=NULL)
{
printf("Lista --> %d\n",first->data.x);
first = first->next;
}
}
przykładowe wywołanie funkcji:
wyswietl_liste(first);
36/46
Podstawy informatyki 2
Wykład nr 2
dr inŜ. Jarosław Forenc
37/46
Lista jednokierunkowa - przykład (1/5)
#include <stdio.h>
#include <stdlib.h>
struct element
{
int x;
};
struct lista
{
struct element data;
struct lista *next;
};
Implementacja listy jednokierunkowej w języku C
Podstawy informatyki 2
Wykład nr 2
dr inŜ. Jarosław Forenc
38/46
Lista jednokierunkowa - przykład (2/5)
struct lista *dodaj_pierwszy(struct lista *first, struct element data)
{
struct lista *wsk;
wsk = (struct lista*) malloc(sizeof(struct lista));
wsk->data = data;
wsk->next = first;
return wsk;
}
struct lista *dodaj_ostatni(struct lista *last, struct element data)
{
struct lista *wsk;
wsk = (struct lista*) malloc(sizeof(struct lista));
wsk->data = data;
wsk->next = NULL;
if (last!=NULL)
last->next = wsk;
return wsk;
}
Implementacja listy jednokierunkowej w języku C
Podstawy informatyki 2
Wykład nr 2
dr inŜ. Jarosław Forenc
39/46
Lista jednokierunkowa - przykład (3/5)
struct lista *usun_wszystko(struct lista *first)
{
struct lista *wsk;
while (first!=NULL)
{
wsk = first->next;
free(first);
first = wsk;
}
return first;
}
void wyswietl_liste(struct lista *first)
{
while (first!=NULL)
{
printf("Lista --> %d\n",first->data.x);
first = first->next;
}
}
Implementacja listy jednokierunkowej w języku C
Podstawy informatyki 2
Wykład nr 2
dr inŜ. Jarosław Forenc
40/46
Lista jednokierunkowa - przykład (4/5)
int main()
{
int tab[5] = {1,2,3,4,5};
struct lista *first = NULL, *last = NULL;
struct element data;
int i;
for (i=0;i<5;i++)
{
data.x = tab[i];
if (i==0)
first = last = dodaj_pierwszy(first,data);
else
first = dodaj_pierwszy(first,data);
printf("dodaj_pierwszy() --> %d\n",data.x);
}
dodaj_pierwszy()
dodaj_pierwszy()
dodaj_pierwszy()
dodaj_pierwszy()
dodaj_pierwszy()
Lista
Lista
Lista
Lista
Lista
-->
-->
-->
-->
-->
-->
-->
-->
-->
-->
1
2
3
4
5
5
4
3
2
1
printf("\n");
wyswietl_liste(first);
first = last = usun_wszystko(first);
Implementacja listy jednokierunkowej w języku C
Podstawy informatyki 2
Wykład nr 2
dr inŜ. Jarosław Forenc
41/46
Lista jednokierunkowa - przykład (5/5)
printf("\n\n");
for (i=0;i<5;i++)
{
data.x = tab[i];
if (i==0)
first = last = dodaj_ostatni(last,data);
else
last = dodaj_ostatni(last,data);
printf("dodaj_ostatni() --> %d\n",data.x);
}
dodaj_ostatni()
dodaj_ostatni()
dodaj_ostatni()
dodaj_ostatni()
dodaj_ostatni()
Lista
Lista
Lista
Lista
Lista
-->
-->
-->
-->
-->
-->
-->
-->
-->
-->
1
2
3
4
5
1
2
3
4
5
printf("\n");
wyswietl_liste(first);
first = last = usun_wszystko(first);
system("pause");
return 0;
}
Implementacja listy jednokierunkowej w języku C
Podstawy informatyki 2
Wykład nr 2
dr inŜ. Jarosław Forenc
42/46
Lista dwukierunkowa
w liście dwukierunkowej kaŜdy węzeł posiada adres następnika, jak i poprzednika
W strukturze tego typu wygodne jest przechodzenie pomiędzy elementami w obu
kierunkach (od początku do końca i odwrotnie)
NULL
prev
prev
prev
prev
data
data
data
data
next
next
next
next
NULL
Podstawy informatyki 2
Wykład nr 2
dr inŜ. Jarosław Forenc
43/46
Lista cykliczna
listę cykliczną moŜna utworzyć z listy jednokierunkowej lub dwukierunkowej,
jeśli ostatni element tej struktury połączymy z pierwszym
Jednokierunkowa:
data
data
data
data
next
next
next
next
Dwukierunkowa:
prev
prev
prev
prev
data
data
data
data
next
next
next
next
Podstawy informatyki 2
Wykład nr 2
dr inŜ. Jarosław Forenc
44/46
Drzewo
drzewo jest najbardziej ogólną dynamiczną strukturą danych i moŜe być
reprezentowane graficznie na róŜne sposoby
korzeń drzewa jest umieszczony u góry
skojarzone z korzeniem poddrzewa
połączone są z korzeniem liniami
zwanymi gałęziami drzewa
potomkiem węzła w nazywamy kaŜdy,
róŜny od w, węzeł naleŜący do drzewa,
w którym w jest korzeniem
a
b
e
węzeł w nazywamy przodkiem węzłów drzewa,
w którym w jest korzeniem
bezpośrednich potomków nazywamy synami
bezpośrednich przodków nazywamy ojcami
synów tego samego ojca nazywamy braćmi
węzeł, który nie ma potomków, to liść drzewa
c
f
g
d
h
i
j
Podstawy informatyki 2
Wykład nr 2
dr inŜ. Jarosław Forenc
45/46
Drzewo binarne
drzewo binarne jest szczególnym przypadkiem ogólnej struktury zwanej drzewem
kaŜdy wierzchołek drzewa ma co najwyŜej dwóch potomków, tzn. kaŜdy ojciec ma
co najwyŜej dwóch synów
korze
data
next1
next2
li
data
data
next1
next2
next1
next2
NULL
NULL
li
li
data
data
next1
next2
next1
next2
NULL
NULL
NULL
NULL
Podstawy informatyki 2
Wykład nr 2
dr inŜ. Jarosław Forenc
46/46
Binarne drzewo wyszukiwawcze
jest to drzewo binarne, w którym dla kaŜdego węzła wi wszystkie klucze
(przechowywane wartości) w lewym poddrzewie węzła wi są mniejsze
od klucza w węźle wi, a wszystkie klucze w prawym poddrzewie węzła wi
są większe od klucza w węźle wi
największą zaletą takiej struktury jest szybkość wyszukiwania informacji
10
5
20
2
8
3
7
15
12
23
17
21
27