Struktury dynamiczne

Podobne dokumenty
INFORMATYKA. Podstawy programowania w języku C. (Wykład) Copyright (C) 2005 by Sergiusz Sienkowski IME Zielona Góra

Dynamiczny przydział pamięci w języku C. Dynamiczne struktury danych. dr inż. Jarosław Forenc. Metoda 1 (wektor N M-elementowy)

WYKŁAD 10. Zmienne o złożonej budowie Statyczne i dynamiczne struktury danych: lista, kolejka, stos, drzewo. Programy: c5_1.c, c5_2, c5_3, c5_4, c5_5

Dynamiczne struktury danych

ALGORYTMY I STRUKTURY DANYCH

Algorytmy i Struktury Danych. Co dziś? Drzewo decyzyjne. Wykład IV Sortowania cd. Elementarne struktury danych

dr inż. Paweł Myszkowski Wykład nr 11 ( )

Listy, kolejki, stosy

E S - uniwersum struktury stosu

Algorytmy i złożoności. Wykład 3. Listy jednokierunkowe

Temat: Dynamiczne przydzielanie i zwalnianie pamięci. Struktura listy operacje wstawiania, wyszukiwania oraz usuwania danych.

Programowanie i struktury danych

Stos LIFO Last In First Out

Struktury danych: stos, kolejka, lista, drzewo

Wykład 3. Złożoność i realizowalność algorytmów Elementarne struktury danych: stosy, kolejki, listy

Programowanie obiektowe

Struktury. Przykład W8_1

Abstrakcyjne struktury danych - stos, lista, drzewo

Laboratorium z przedmiotu Programowanie obiektowe - zestaw 04

Wykład X. Programowanie. dr inż. Janusz Słupik. Gliwice, Wydział Matematyki Stosowanej Politechniki Śląskiej. c Copyright 2016 Janusz Słupik

Materiał uzupełniający do ćwiczen z przedmiotu: Programowanie w C ++ - ćwiczenia na wskaźnikach

Struktury Danych i Złożoność Obliczeniowa

Wstęp do programowania

Zmienne i struktury dynamiczne

Programowanie i struktury danych 1 / 44

Algorytmy i Struktury Danych

Podstawy informatyki 2

Programowanie obiektowe i C++ dla matematyków

Podstawy informatyki 2. Podstawy informatyki 2. Wykład nr 2 ( ) Plan wykładu nr 2. Politechnika Białostocka. - Wydział Elektryczny

Co to jest sterta? Sterta (ang. heap) to obszar pamięci udostępniany przez system operacyjny wszystkim działającym programom (procesom).

Wykład 6_1 Abstrakcyjne typy danych stos Realizacja tablicowa i za pomocą rekurencyjnych typów danych

Uniwersytet Zielonogórski Instytut Sterowania i Systemów Informatycznych. Ćwiczenie 3 stos Laboratorium Metod i Języków Programowania

WYKŁAD 8. Funkcje i algorytmy rekurencyjne Proste przykłady. Programy: c3_1.c..., c3_6.c. Tomasz Zieliński

Obliczenia na stosie. Wykład 9. Obliczenia na stosie. J. Cichoń, P. Kobylański Wstęp do Informatyki i Programowania 266 / 303

Dynamiczny przydział pamięci (język C) Dynamiczne struktury danych. Sortowanie. Klasyfikacja algorytmów sortowania. Algorytmy sortowania

WYKŁAD 9. Algorytmy sortowania elementów zbioru (tablic) Programy: c4_1.c... c4_3.c. Tomasz Zieliński

Teoretyczne podstawy informatyki

Wstęp do programowania

Wykład 5 Wybrane zagadnienia programowania w C++ (c.d.)

int tab_a [ 2 ] [ 3 ];

Wysokość drzewa Głębokość węzła

Wskaźniki. Programowanie Proceduralne 1

Podstawy Programowania 2 Dwukierunkowa lista liniowa. Plan. Wstęp. Implementacja. Notatki. Notatki. Notatki. Notatki.

Rekurencja. Dla rozwiązania danego problemu, algorytm wywołuje sam siebie przy rozwiązywaniu podobnych podproblemów. Przykład: silnia: n! = n(n-1)!

Kiedy potrzebne. Struktura (rekord) Struktura w języku C# Tablice struktur. struktura, kolekcja

Algorytmy i struktury danych. wykład 5

. Podstawy Programowania 2. Drzewa bst - część druga. Arkadiusz Chrobot. 12 maja 2019

Programowanie obiektowe i C++ dla matematyków

Wyszukiwanie w BST Minimalny i maksymalny klucz. Wyszukiwanie w BST Minimalny klucz. Wyszukiwanie w BST - minimalny klucz Wersja rekurencyjna


Dynamiczne struktury danych

Algorytmy i. Wykład 3: Stosy, kolejki i listy. Dr inż. Paweł Kasprowski. FIFO First In First Out (kolejka) LIFO Last In First Out (stos)

Drzewa wyszukiwań binarnych (BST)

Lista, Stos, Kolejka, Tablica Asocjacyjna

Teoretyczne podstawy informatyki

Laboratorium 6: Dynamiczny przydział pamięci. dr inż. Arkadiusz Chrobot dr inż. Grzegorz Łukawski

Jak napisać listę jednokierunkową?

wykład II uzupełnienie notatek: dr Jerzy Białkowski Programowanie C/C++ Język C - funkcje, tablice i wskaźniki wykład II dr Jarosław Mederski Spis

Wskaźniki. Przemysław Gawroński D-10, p marca Wykład 2. (Wykład 2) Wskaźniki 8 marca / 17

METODY I JĘZYKI PROGRAMOWANIA PROGRAMOWANIE STRUKTURALNE. Wykład 02

Podstawy programowania. Wykład 7 Tablice wielowymiarowe, SOA, AOS, itp. Krzysztof Banaś Podstawy programowania 1

DYNAMICZNE PRZYDZIELANIE PAMIECI

. Podstawy Programowania 2. Drzewa bst - część pierwsza. Arkadiusz Chrobot. 22 maja 2016

Podstawy programowania 2. Temat: Drzewa binarne. Przygotował: mgr inż. Tomasz Michno

Porządek symetryczny: right(x)

WYŻSZA SZKOŁA INFORMATYKI STOSOWANEJ I ZARZĄDZANIA

Wstęp. #define include include include include include include

Podstawy Informatyki. Wykład 6. Struktury danych

dodatkowe operacje dla kopca binarnego: typu min oraz typu max:

. Podstawy Programowania 2. Dwukierunkowa lista liniowa. Arkadiusz Chrobot. 7 kwietnia 2019

Języki i metodyka programowania. Wskaźniki i tablice.

Algorytmy i struktury danych. Drzewa: BST, kopce. Letnie Warsztaty Matematyczno-Informatyczne

Programowanie w C++ Wykład 5. Katarzyna Grzelak. 26 marca kwietnia K.Grzelak (Wykład 1) Programowanie w C++ 1 / 40

INFORMATYKA W SZKOLE. Podyplomowe Studia Pedagogiczne. Dr inż. Grażyna KRUPIŃSKA. D-10 pokój 227

Programowanie obiektowe

Algorytmy i Struktury Danych.

Podstawowe struktury danych

Programowanie obiektowe

Wskaźniki. Informatyka

Typy wyliczeniowe Konwersje napis <-> liczba Struktury, unie Scanf / printf Wskaźniki

tablica: dane_liczbowe

Przykładowe B+ drzewo

Lista 5 Typy dynamiczne kolejka

Temat: Dynamiczne liniowe struktury danych - stos, kolejka, lista. 1. Wady i zalety struktury tablicy

Struktury czyli rekordy w C/C++

Wstęp do programowania INP001213Wcl rok akademicki 2018/19 semestr zimowy. Wykład 4. Karol Tarnowski A-1 p.

Wykłady opracowane zostały w oparciu o materiały prof. dr hab. Jerzego Weresa. Poznań 2009/2010 Algorytmy i struktury danych Krzysztof Nowakowski 2

Algorytmy i Struktury Danych.

Wskaźniki w C. Anna Gogolińska

KURS C/C++ WYKŁAD 6. Wskaźniki

Podstawy programowania 2. Przygotował: mgr inż. Tomasz Michno

Podstawy informatyki. Elektrotechnika I rok. Język C++ Operacje na danych - wskaźniki Instrukcja do ćwiczenia

Podstawy programowania skrót z wykładów:

Marcin Matusiak i Łukasz Stasiak

Teoretyczne podstawy informatyki

. Podstawy Programowania 2. Jednokierunkowa lista liniowa. Arkadiusz Chrobot. 28 marca 2017

Paradygmaty programowania. Paradygmaty programowania

Lab 9 Podstawy Programowania

Drzewa poszukiwań binarnych

Wykład 7 Abstrakcyjne typy danych słownik (lista symboli)

Transkrypt:

Struktury dynamiczne lista jednokierunkowa lista dwukierunkowa lista cykliczna stos kolejka drzewo Ich wielkość i stopień złożoności zmieniają się w czasie. Struktury dynamiczne oparte są o struktury (struct). Sposób definicji komponentów struktur związany jest z funkcjonalnościami i przeznaczeniem struktur. Poniżej znajdują się opisy implementacji struktur dynamicznych, jak również fragmenty kodów w języku c z podstawowymi działaniami w poszczególnych przypadkach.

Lista jednokierunkowa Lista jednokierunkowa zawiera pewne dane (elementy listy) tak jak struktura, oraz wskaźnik na następny element listy. Ostatni element listy jednokierunkowej posiada wskaźnik ustawiony na. Dostęp do listy umożliwia wskaźnik ustawiony na pierwszy element listy. Przeglądanie listy i pobieranie jej elementów (wstawianie tam wartości) możliwe jest dzięki operatorowi wskaźnikowemu ->. start next (1) (2) (3) (N) struct lista_jednokierunkowa { typ dana1; typ dana2;... typ danan; struct lista_jednokierunkowa *next; ;

Lista jednokierunkowa Przykład: 1. Zdefiniowanie struktury. struct list_element { int data1; int data2; struct list_element *next; ; 2. Deklaracja wskaźników typu strukturalnego (takiego jak element listy) i ustawienie ich tymczasem na : struct list_element *start=, *pointer=;

Lista jednokierunkowa 3. Dynamiczne przydzielenie pamięci dla struktury i ustawienie wskaźnika start na tym obszarze pamięci czyli na tym pierwszym elemencie listy: start = malloc ( sizeof (struct list_element) ); start 4. Ustawienie wskaźnika next na gdyż struktura ta jest jednocześnie ostatnim elementem listy. start->next = ; 5. Przy okazji nadamy wartości polom w pierwszym elemencie listy start->data1 = 100; start->data2 = 100;

Lista jednokierunkowa Bieżący stan start 6. Utworzenie następnego elementu listy, dynamicznie. Tym razem ustawimy na ten obszar pamięci wskaźnik pointer. pointer = malloc ( sizeof (struct list_element) ); Po tej operacji sytuacja wygląda następująco: dwa elementy listy jeszcze ze sobą nie skojarzone: pointer start

Lista jednokierunkowa 7. Następnie nadamy wartosci polom elemntowi listy, pokazywanemu wskaźnikiem pointer ale, co najważniejsze, połączymy elementy ze sobą w listę dwuelementową pointer->data1 = 200; pointer->data2 = 200; pointer->next = start; //!! po tych operacjach sytuacja wygląda następująco pointer start next 8. Na koniec ustawiamy wskaźnik start na początku listy i kończymy tym samym dodanie nowego elementu na początek listy. start=pointer; Na koniec sytuacja wygląda następująco: pointerstart next

Lista jednokierunkowa Teraz wypiszemy wartości elementów listy, poruszając się po elementach listy przy pomocy zdefiniowanych wcześniej wskaźników: while (pointer!= 0){ printf( dana1 = %d, dana2 = %d\n, \ pointer->dana1, pointer->dana2); pointer=pointer->next; //!! Wynik działania będzie następujący (dla przykładowej listy wcześniej zdefiniowanej, dwuelementowej): dana1 = 200, dana2 = 200 dana1 = 100, dana2 = 100

Lista jednokierunkowa - przyklad #include <stdio.h> #include <stdlib.h> //deklaracja elementu listy jednokier struct onedir { int data1; int data2; struct onedir *next; ; int main (){ 10 //deklaracja wskaznika do pierwsz. elementu listy i alokacja struct onedir *start; start = (struct onedir*)malloc(sizeof (*start) ); //ustawienie wskaznika next na bo to ostatni(!) elem. listy //kolejne elementy bedziemy wstawiac do listy na poczatek, nie na koniec start >next=; start >data1 = 100; 20 start >data2 = 100; //nastepny element listy, //ale bedzie on (pozniej) w kolejnosci pierwszy struct onedir *pointer; pointer = (struct onedir*)malloc(sizeof (*pointer) ); pointer >data1=200; pointer >data2=200; //ustawienie wskaznika elementu na elemencie nastepnym 30 pointer >next=start;

//ustawimy wskaznik start na pocztaku listy //w tym momencie obydwa wskazniki (pointer oraz start) //pokazuja na poczatek listy czyli na pierwszy element start=pointer; //nastepny element listy, chwilowo "niezlokalizowany" //ale za chwile ustawimy go na poczatku //"przesuwajac" pozostale 40 pointer = (struct onedir*)malloc(sizeof (*pointer) ); pointer >data1=300; pointer >data2=300; //ustawienie wskaznikow; jakby ustawienie elementu listy //na poczatku listy pointer >next=start; start=pointer; //wypisanie pol wszystkich elementow listy 50 //petla leci po elementach listy zaczynajac od poczatku listy printf ("\n elementy listy struktur:\n\n"); while (pointer!= 0){ printf (" data1 = %d; data2 = %d\n",pointer >data1, pointer >data2); pointer=pointer >next; printf ("\n\n"); return 0; 60

Wynik dzialania elementy listy struktur: data1 = 300; data2 = 300 data1 = 200; data2 = 200 data1 = 100; data2 = 100

Lista dwukierunkowa Lista dwukierunkowa zawiera pewne dane (elementy listy) tak jak struktura, oraz dwa wskaźniki: jeden pokazujący na następny element listy oraz drugi - na poprzedni element listy. Wskaźnik na następny element listy ostatniego elementu listy dwukier. jest ustawiany na, i podobnie, wskaźnik pierwszego elementu listy na element poprzedni jest ustawiany na. Przeglądanie listy dwukierunkowej może się odbywać zarówno od początku, za pomocą wskaźnika ustawionego na pierwszym elemencie (tutaj wskaźnik o nazwie start) jak też od końca za pomocą wskaźnika ustawionego na ostatnim elemencie listy. Podobnie jak w przypadku listy jednokierunkowej przeglądanie listy i pobieranie jej elementów (wstawianie tam wartości) możliwe jest dzięki operatorowi wskaźnikowemu ->. start next N pre pre (1) (2) (3) (N) struct lista_dwukierunkowa { typ dana1; typ dana2;... typ danan; struct lista_dwukierunkowa *next, *prev; ;

Lista dwukierunkowa Przykład: 1. Zdefiniowanie struktury. struct twodir_element { int data1; int data2; struct twodir_element *next, *prev; ; 2. Deklaracja wskaźników typu strukturalnego (takiego jak element listy) i ustawienie ich tymczasem na : struct twodir_element *start=, *pointer=;

Lista dwukierunkowa 3. Dynamiczne przydzielenie pamięci dla dwóch elementów strukturalnych (dwóch elementów listy) i ustawienie wskaźników: start = malloc ( sizeof (struct twodir_element) ); start->data1=100; start->data2=100; start->next=; start->prev=; pointer = malloc ( sizeof (struct twodir_element) ); pointer->data1=200; pointer->data2=200; pointer->next=; pointer->prev=; pointer start

Lista dwukierunkowa 4. Połączenie elementów listy poprzez odpowiednie ustawienie wskaźników next oraz prev. Wskaźnik start trzeba ustawić na początku listy, zaś pointer zostanie usunięty. Wcześniej wyświetlimy też listę tzn. pola jej elementów. pointer->next=start; start->prev=pointer; start=pointer; while(pointer!= 0) { printf( %d %d\n,wsk->data1, wsk->data2); pointer=pointer->next; free(pointer); Obraz końcowej sytuacji start

Lista dwukierunkowa Następny przykład: trzy elementy listy (obraz po zbudowaniu listy) pointer i usunięcie drugiego elementu (obraz po usunięciu drugiego elementu). start Poniżej pełny program.

Lista dwukierunkowa - pełny przykład #include <stdio.h> #include <stdlib.h> //deklaracja elementu listy dwukierunkowej struct twodir{ int data1; int data2; struct twodir *prev, *next; ; int main(){ //pierwszy element listy struct twodir *start; start = (struct twodir*)malloc(sizeof(*start)); start >data1 = 100; start >data2 = 100; start >next=; start >prev=; 10 //drugi elem. listy 20 struct twodir *pointer; pointer = (struct twodir*)malloc(sizeof(*pointer)); pointer >data1=200; pointer >data2=200; pointer >prev=; pointer >next=; //trzeci elem. listy struct twodir *pointer2; pointer2 = (struct twodir*)malloc(sizeof(*pointer)); 30 pointer2 >data1=300;

pointer2 >data2=300; pointer2 >prev=; pointer2 >next=; //Polaczenie elementow listy. //Pierwszy element trzeba ustawic na poczatku listy. //Czyli najpierw ma byc 100, pozniej 200 a pozniej 300 //(od lewej do prawej) start >next=pointer; 40 pointer >prev=start; pointer >next=pointer2; pointer2 >prev=pointer; //wypisanie elementow listy: //utworzymy pomocniczy wskaznik, aby pozniej // nie przesuwac wstecz wskaznikow. //ustawimy go na poczatku listy i nim bedziemy sie poslugiwac // przy wypisywaniu. 50 //pozostale wskazniki pozostaja nietkniete struct twodir *temp; // tu nie ma alokacji, nie potrzeba! temp=start; printf ("\n elementy listy, wierszami, przed usunieciem elem. drugiego:\n"); while ( temp!= 0 ){ printf (" data1 = %d, data2 = %d\n",temp >data1,temp >data2); temp=temp >next; printf ("\n\n"); 60 //usuniecie drugiego elementu i polaczenie pierwszego z trzecim pointer >next=; pointer >prev=; start >next=; pointer2 >prev=; free(pointer);

start >next=pointer2; pointer2 >prev=start; //wypisanie elementow listy przy pomocy wskaznika temp 70 temp=start; printf ("\n elementy listy, wierszami, po usunieciu elem. drugiego:\n"); while ( temp!= 0 ){ printf (" data1 = %d, data2 = %d\n",temp >data1,temp >data2); temp=temp >next; printf ("\n\n"); return 0; 80 elementy listy, wierszami, przed usunieciem elementu drugiego: data1 = 100, data2 = 100 data1 = 200, data2 = 200 data1 = 300, data2 = 300 elementy listy, wierszami, po usunieciu elementu drugiego: data1 = 100, data2 = 100 data1 = 300, data2 = 300

Listy cykliczne Lista dwukierunkowa cykliczna charakteryzuje się tym, że wskaźnik na następny element w ostatnim elemencie nie ma wartości ale pokazuje na początek listy. W przypadku listy cyklicznych dwukierunkowych wskaźnik na poprzedni element w pierwszym elemencie listy pokazuje na element ostatni, zaś wskaźnik elementu ostatniego pokazuje na pierwszy element tej listy. Jednakw przypadku list cyklicznych raczej nie mówi się o początku i końcu, choć często pierwszy element takiej listy wynika z kontekstu i zawartości danych struktury. Pozycję na liście wskazuje zewnętrzny wskaźnik, którego położenie może się dowolnie zmieniać, wówczas trzeba określić jakiś dodatkowy warunek na zakończenie pętli po elementach listy. pointer next next next xt (1) (2) (3) (N) pointer pre next pr xt (1) (2) (3) (N)

Stosy Stos jest kolejką typu LIFO (ang. Last In First Out), tzn. elementy położone jako ostatnie są zdejmowane jako pierwsze. Domyślamy się, że mamy zatem np. w przypadku list, szybko dostęp do takiego elementu za pomocą wskaźnika. W przypadku stosu taki wskaźnik nazywany jest wskaźnikiem stosu i konsekwentnie pokazuje na ostatnio dołożony element (pierwszy na górze, na szczycie stosu) Ze stosu zdejmujemy ostatnio dołożony element. Stos może też być zaimplementowany jako tablica jednowymiarowa. Musimy wtedy zaopatrzyć nasze procedury w jakiś sposób identyfikacji ostatnio wprowadzonego elementu do tablicy (indeksu ostatniego elementu, odpowiedniego licznika). Stos w formie tablicy musi zapewnić poprawne wykonanie przynajmniej dwóch funkcji push() - położenie elementu na stosie (w tablicy - dołożenie elementu do tablicy i zwiększenie dynamiczne rozmiaru tablicy o jeden element), oraz pop() - zdjęcie ostatniego elementu z listy (w tablicy - usunięcie ostatniego elementu tablicy i skrócenie tablicy o jeden element). W przypadku implementacji listowej, szczyt stosu znajduje się na początku listy, zaś nowe elementy dokładane są do początku listy. Usuwanie elementów odbywa się od wierzchołka stosu.

Stos 1. definicja elementów stosu (tutaj trzech). Bez połączenia, tymczasem. pierwszy = malloc (sizeof(*pierwszy)); pierwszy->data1=100; pierwszy->next=; drugi = malloc (sizeof(*drugi)); drugi->data1=200; drugi->next=; trzeci = malloc (sizeof(*trzeci)); trzeci->data1=300; trzeci->next=; 2. Połączenie elem. stosu pierwszy->next=drugi; drugi->next=trzeci; //ustawienie wskaźnika stosu: wsk_stosu=pierwszy;

Stos Stos wygląda tak (można też narysować w pionie ) wsk. stosu pierwszy drugi trzeci 3. zdjęcie elementu ze stosu (zgodnie z zasadą LIFO). To operacja podobna do działania funkcji pop(). wsk_stosu=drugi; pierwszy->next=; free(pierwszy); wsk. stosu drugi trzeci

Stos 4. Dołożenie elementu do stosu, w przypadku stosu - zawsze na początek (na szczyt stosu), tak jak w funkcji push(). czwarty = malloc (sizeof(*czwarty)); czwarty->data1=400; czwarty->next=; czwarty->next=drugi; //ustawienie wskaźnika stosu na szczycie stosu wsk_stosu=czwarty; wsk. stosu (pierwszy) drugi trzeci

Stos - pełny przykład #include <stdio.h> #include <stdlib.h> //deklaracja elementu stosu; struct stos { int data1; struct stos *next; ; int main (){ 10 //zaalokowanie 3 elementów stosu struct stos *pierwszy; pierwszy = (struct stos*)malloc(sizeof (*pierwszy) ); pierwszy >data1=100; pierwszy >next=; struct stos *drugi; drugi = (struct stos*)malloc(sizeof (*drugi) ); 20 drugi >data1=200; drugi >next=; struct stos *trzeci; trzeci = (struct stos*)malloc(sizeof (*trzeci) ); trzeci >data1=300; trzeci >next=; //polaczenie elemetow stosu pierwszy >next=drugi; 30 drugi >next=trzeci;

//wskaznik stosu i ustawienie go na pierwszym elemencie struct stos *wsk stosu; wsk stosu=pierwszy; //wypisanie pol wszystkich elementow stosu printf ("\n elementy stosu przed zdjeciem jednego elementu:\n"); while (wsk stosu!= 0){ printf (" data1 = %d;\n",wsk stosu >data1); 40 wsk stosu=wsk stosu >next; printf ("\n\n"); //zdjecie elementu ze stosu zgodnie z regula LIFO //czyli zdjecie nawyjzej polozonego elementu, pierwszego wsk stosu=drugi; pierwszy >next=; free(pierwszy); printf ("\n elementy stosu po zdjeciu pierwszego elementu:\n"); 50 while (wsk stosu!= 0){ printf (" data1 = %d;\n",wsk stosu >data1); wsk stosu=wsk stosu >next; printf ("\n\n"); //nastepnie dodanie kolejnego elementu na wierzch stosu, //czyli na poczatek listy struct stos *czwarty; czwarty = (struct stos*)malloc(sizeof (*czwarty) ); 60 czwarty >data1=400; czwarty >next=; czwarty >next=drugi; wsk stosu=czwarty;

printf ("\n elementy stosu po dodaniu czwartego elementu:\n"); while (wsk stosu!= 0){ printf (" data1 = %d;\n",wsk stosu >data1); wsk stosu=wsk stosu >next; 70 printf ("\n\n"); return 0; elementy stosu przed zdjeciem jednego elementu: data1 = 100; data1 = 200; data1 = 300; elementy stosu po zdjeciu pierwszego elementu: data1 = 200; data1 = 300; elementy stosu po dodaniu czwartego elementu: data1 = 400; data1 = 200; data1 = 300;

Kolejka Kolejka jest strukturą danych typu FIFO (ang. First In First Out), czyli pierwszy element jest zdejmowany jako pierwszy, w przeciwieństwie do stosu. Implementowana jest przy pomocy listy jednokierunkowej przy udziale dwóch wskaźników: jeden pokazuje na początek kolejki (na pierwszy element) zaś drugi - na koniec (na ostatni element). Elementy dopisywane są zawsze na koniec kolejki z przesunięciem wskaźnika. Zaś pobierane są zawsze z początku listy (z początku kolejki). start next next next xt (1) (2) (3) (N) struct que { int data1; int data2; struct que *next; ;

Kolejka 1. definicja elementów kolejki (tutaj trzech). Bez połączenia, tymczasem. struct que *pierwszy; struct que *drugi; struct que *trzeci; pierwszy = malloc (sizeof(*pierwszy)); pierwszy->data1=100; pierwszy->data2=100; pierwszy->next=; drugi = malloc (sizeof(*drugi)); drugi->data1=200; drugi->data2=200; drugi->next=; trzeci = malloc (sizeof(*trzeci)); trzeci->data1=300; trzeci->data2=300; trzeci->next=;

Kolejka 2. Połączenie elem. kolejki pierwszy->next=drugi; drugi->next=trzeci; //ustawienie wskaźnikow kolejki: struct stos *start; struct stos *end; start=pierwszy; end=trzeci; start next next next pierwszy drugi trzeci

Kolejka 3. Zdjęcie pierwszego elementu kolejki i dodanie czwartego elementu (na zasadzie FIFO) start=drugi; pierwszy->next=; free(pierwszy); struct que *czwarty; czwarty = malloc (sizeof(*czwarty)); czwarty->data1=400; czwarty->data2=400; czwarty->next=; pierwszy i) i (czwa

Kolejka - pełny przykład #include <stdio.h> #include <stdlib.h> //deklaracja elementu kolejki; struct que { int data1; int data2; struct que *next; ; int main (){ 10 //zaalokowanie 3 elementów kolejki struct que *pierwszy; pierwszy = (struct que*)malloc(sizeof (*pierwszy) ); pierwszy >data1=100; pierwszy >data2=100; pierwszy >next=; struct que *drugi; 20 drugi = (struct que*)malloc(sizeof (*drugi) ); drugi >data1=200; drugi >data2=200; drugi >next=; struct que *trzeci; trzeci = (struct que*)malloc(sizeof (*trzeci) ); trzeci >data1=300; trzeci >data2=300; trzeci >next=; 30

//polaczenie elemetow kolejki pierwszy >next=drugi; drugi >next=trzeci; //wskazniki kolejki struct que *start, *end; start=pierwszy; end=trzeci; //? end nie wydaje sie potrzebny //wypisanie pol wszystkich elementow kolejki //przed zmianami w kolejce printf ("\n elementy kolejki przed zdjeciem jednego elementu:\n"); while (start!= 0){ printf (" data1 = %d, data2 = %d;\n",start >data1,start >data2); start=start >next; printf ("\n\n"); 40 //usuniecie elementu z kolejki zgodnie z regula FIFO 50 //czyli zdjecie pierwszego elementu start=drugi; pierwszy >next=; free(pierwszy); printf ("\n elementy kolejki po usunieciu pierwszego elementu:\n"); while (start!= 0){ printf (" data1 = %d, data2 = %d;\n",start >data1,start >data2); start=start >next; printf ("\n\n"); 60 //nastepnie dodanie kolejnego elementu na koniec kolejki struct que *czwarty; czwarty = (struct que*)malloc(sizeof (*czwarty) ); czwarty >data1=400; czwarty >data2=400;

czwarty >next=; trzeci >next=czwarty; end=czwarty; //? end nie wydaje sie potrzebny 70 printf ("\n elementy kolejki po dodaniu czwartego elementu:\n"); start=drugi; // trzeba z powrotem ustawic na poczatku while (start!= 0){ printf (" data1 = %d, data2 = %d;\n",start >data1,start >data2); start=start >next; printf ("\n\n"); return 0; 80 elementy kolejki przed zdjeciem jednego elementu: data1 = 100, data2 = 100; data1 = 200, data2 = 200; data1 = 300, data2 = 300; elementy kolejki po usunieciu pierwszego elementu: data1 = 200, data2 = 200; data1 = 300, data2 = 300; elementy stosu po dodaniu czwartego elementu: data1 = 200, data2 = 200; data1 = 300, data2 = 300; data1 = 400, data2 = 400;

Drzewo Drzewo jest strukturą danych hierarchiczną i (najczęściej) rekurencyjną. Struktury nazywane są węzłami drzewa (ang. node). Drzewa dzielą się na drzewa mnogościowe (każdy węzęł może mieć dowolną ilość potomków nazywanych dziećmi) lub tylko dwóch (w takim przypadku mówimy o drzewach binarnych).

Drzewo Specjalny wskaźnik umożliwia dostęp do całego drzewa, ustawiany jest na węźle praoujcu, który nie ma żadnych rodziców, nazywany jest on root czyli korzeń. Jeśli węzęł nie ma któregoś z potomków wówczas wskaźnik next ustawiany jest na. Algorytmy operujące na drzewach oparte są najczęściej o rozwiązania rekurencyjne gdyż każdy węzeł może być traktowany jako osobny rodzic a więc od niego może się teoretycznie zaczynać kolejne drzewo. Typowe algorytmy: wstawianie nowego węzła w jakimś miejscu (na końcu, w środku), usuwanie węzłów i usuwanie całego drzewa, przeszukiwanie drzewa (różne warianty).

Rekurencja - przykład #include <stdio.h> //rekurencyjna funkcja obliczajaca silnie long silnia( long n ) { if ( n <= 1 ) return 1; else { return (n * silnia( (n 1) )); int main (){ 10 long ile = 10; long wynik; long i=1; printf("\n\n"); while (i <= 10){ wynik = silnia(i); printf(" %10ld! = %10ld\n",i,wynik); 20 i++; printf("\n\n"); return 0;

Drzewo - przykład #include <stdio.h> #include <stdlib.h> #include <time.h> //deklaracja wezla (nodu ) czyli elem. drzewa binarnego; struct node { int data1; struct node *left, *right, *up; ; //funkcja tworzaca nody (wezly) w drzewie //Jako wartosc w polu data1 zostanie wstawiony //podany parametr ile struct node* add node(struct node *new, int ile){ 10 //inicjalizacja wezla i ustawienie wskaznikow na //utworzenie wskaznika pomocniczego do nodu struct node *helper, *which; which = (struct node*)malloc(sizeof (*which) ); which >left = which >right = ; 20 which >data1 = ile; helper = new; // jesli nie bylo zadnego korzenia to mamy nowe drzewo // i nasz nowy nod jest wtedy rootem if (!helper) {new = which; else{ // Petla nieskonczona // W zaleznosci od klucza idziemy do lewego lub 30 // prawego syna, o ile takowy istnieje

while(1){ if (ile < helper >data1) { if (!helper >left){ helper >left = which; break; else helper=helper >left; else{ 40 if (!helper >right){ helper >right = which; break; else helper=helper >right; which >up = helper; 50 return which; void rmtree(struct node *tree){ if (tree) { rmtree(tree >left); rmtree(tree >right); rmtree(tree >up); free(tree); 60 int main (){

//wskaznik do nodu, //alokacje pamieci zapewnia funkcja add node struct node *root = ; int i, k, ile; 70 //liczba nodow, granicznie moze byc nawet tylko jeden ile = 10; srand(time()); for(i = 0; i < ile; i++){ //liczby losowe 1 9. Takie umiescimy w wezlach //i na podstawie wartosci tych liczb rozmiescimy //kolejne nody w odpowiedni sposob k = 1 + rand() % 9; 80 root = add node(root,k); //usuniecie drzewa rmtree(root); return 0; 90