background image

 

Programowanie – Głowacki – podsumowanie tego badziewia 

 

Wykład 2 (reprezentacja danych) 

Zmienne GLOBALNE – deklarowane na początku, przed funkcją main(), dostępne w każdym 
miejscu programu 

Zmienne LOKALNE – dostępne tylko w bloku gdzie zostały zdeklarowane (np. w funkcjach), 
mają charakter tymczasowy, zanikają po zakończeniu funkcji 

Zmienne STATYCZNE – dostępne tylko w bloku (funkcji) ale zachowują swoją wartość 
podczas ponownego wywołania funkcji 

Typy zmiennych: 

int 

Typ całkowity 

4 bajty 

float 

Typ zmiennoprzecinkowy (7 
znaków po przecinku) 

4 bajty 

double 

Typ zmiennoprzecinkowy 
podwójnej długości (15 
znaków po przecinku) 

8 bajtów 

char 

Typ znakowy 

1 bajt 

void 

Typ pusty 

 

Definicja przez typedef – jak nie chce nam się ciągle wpisywać długiej nazwy typu; tworzony 
jest SYNONIM, a nie nowy typ,  

np. typedef unsigned short int USHORT – od teraz możemy używać USHORT jako typu 
zmiennej 

Stałe 

1.  Literały – wpisywane bezpośrednio w danym miejscu programu, np. int a=9 (9 jest 

literałem) 

2.  Stałe symboliczne 

a.  #define a=9; stała nie ma określonego typu 
b.  const int=9 – kod jest łatwiejszy dla kompilatora, bardziej odporny na błędy 

3.  Stałe wyliczeniowe – enum,  

np. enum Kolor {red, green, blue, yellow} – wtedy red=0, green=1, blue=2, yellow=3; 
sam „Kolor” to jest nowa stała wyliczeniowa 

 

 

 

 

background image

 

Wykład 3 (rzutowanie typów) 

Przestrzeń nazw std jest wbudowana 

1.  Definicja globalna – przed main deklarujemy - using namespace std 
2.  Definicja lokalna – w main lub innych funkcjach - using std::cout 
3.  Bezpośrednie wkazanie przestrzeni nazw – std::cout << „Coś tam” 

Zmienne znakowe char – 1 bajt; wystarczą do przechowywania jednej z 256 wartości (2

8

) – 

kod ASCII 

Znaki specjalne w C++ (moim zdaniem znaczące) 

\n 

Nowa linia 

\t 

Tabulator 

Konwersje / rzutowanie typów 

1.  Niejawne – próba automatycznego dopasowania przez kompilator typu zmiennych 

do wykonywanej operacji 

2.  Jawne – wywoływane świadomie przez programistę; są 2 formy zapisu: 

a.  typ(wyrażenie) – np. int(1.454); 
b.  (typ)wyrażenie – np. (int)1.454; 

 

Wykład 3add (operacje wejścia/wyjścia) 

W języku C <stdio.h> : 

1.  printf – wypisanie czegoś na ekranie (strasznie się o tym rozpisał….) 
2.  puts – działa jak printf, ale może działać szybciej, zawsze na końcu przechodzi do 

nowej linii 

3.  fputs – jak puts, ale nie przechodzi do nowej linii 
4.  putchar – wypisywanie pojedynczych znaków 

 

5.  scanf – pobieranie danych od użytkownika; niezbędny operator &, który oznacza 

przekazanie do funkcji adresu zmiennej 

6.  gets () – nie używać :D 
7.  fgets () – czyta tekst do napotkania znaku przejścia do nowej linii 
8.  getchar () – wczytuje jeden znak z klawiatury 

Stosowanie funkcji z rodziny printf/scanf  +/- 

Plusy 

Minusy 

Są bardzo wygodne 

Trudno je rozszerzyć o nowe typy 

Cały szablon w jednym miejscu 

Kompilator nie zawsze może sprawdzić ich 
poprawność 

Umożliwiają łatwe dodawanie informacji, 
formatowanie 

Konieczna znajomość typu każdego 
przetwarzanego wyrażenia 

 

wejścia 

wyjścia 

background image

 

W języku C++ <iostream> 

1.  cout – strumień standardowego wyjścia, domyślnie skierowany na ekran 
2.  cin – strumień standardowego wejścia, domyślnie dołączony do klawiatury 
3.  cerr – komunikaty o błędach (errors), skierowane na ekran 
4.  clog – komunikaty o dzienniku (log), skierowane na ekran 

Operatory << >> 

Flagi stanu formatowania, np. 

1.  left – justowanie lewe 
2.  right – justowanie prawe 
3.  internal – justowanie środkowe 
4.  dec – konwersja dziesiętna 
5.  hex – konwersja ósemkowa 
6.  scientific – notacja wykładnicza 
7.  fixed – notacja zwykła 

 

Wykład 4 (instrukcje decyzyjne, cykliczne) 

Operatory arytmetyczne: +, -, =, *, /, %, ++….. 

Operatory relacyjne: >, <, >=, <=, ==, != 

Operatory logiczne: &&(koniunkcja AND), II (alternatywa OR), ! (negacja NOT) 

Operatory bitowe:  

Koniunkcja - & 

10110011

 (179) 

00100110

 (38) 

--------

 

00100010

 (34) 

Alternatywa – I 

00100010

 (34) 

01000001

 (65) 

--------

 

01100011

 (99) 

 

Przesunięcie w lewo << 
 

00001111 << 3 = 01111000 
00000001 << 5 = 00100000

 

Przesunięcie w prawo >> 

 
00111100 >> 2 = 00001111 
10000000 >> 3 = 00010000

 

 

Inkrementacja ++ 

Dekrementacja – 

 

Modyfikacje flag formatowania 

1.  Użycie prostych funkcji setf, unsetf 
2.  Użycie złożonych funkcji, np. width, 

precision, fill - (cout.width(8)) 

3.  Manipulatory <iomanip> 

 

background image

 

Instrukcje decyzyjne

1.  if 
2.  if … else 
3.  switch (break, default) 
4.  while (continue) 
5.  do … while (continue, break) 
6.  for 

 

Wykład 5 (funkcje) 

Deklaracja funkcji – na początku, samo wypisanie nazwy i argumentów 

Definicja funkcji – na końcu, zawiera instrukcje 

Przekazywanie argumentów: 

1.  przez wartość (klasycznie) 
2.  przez referencje (& - dostęp do adresu zmiennej, zmieniasz wartość globalną) 

Domyślne argumenty funkcji – podawane już przy deklaracji funkcji np.  

void Suma (int a=20, int b=4, int c=8) 

Możemy pominąć tylko wszystkie argumenty począwszy od tego którego pominiemy jako 
pierwszy. 

Przeciążenie funkcji – nadajemy funkcjom te same nazwy, różnią się jednak ilością i typem 
parametrów 

 

Wykład 7 (tablice i wskaźniki)  

Zmienne wskaźnikowe – wartościami wskaźników są adresy wskazujące na miejsce w 
pamięci operacyjnej obiektu 

Wskaźnik zajmuje 4 bajty pamięci (2 bajty adresu segmentu i 2 bajty adresu offsetu) 

int *w – deklaracja zmiennej wskaźnikowej 
int a=10 
wa=&a – w zaczyna wskazywać na ‘a’ 
cout << aa ==== cout << *w 
 
Tablice – uporządkowany zbiór obiektów tego samego typu, jednowymiarowe to wektory, a 
wielowymiarowe to macierze 

Tablice są indeksowane od 0!! 

Nazwa tablicy podaje adres – jest wskazaniem na pierwszy element tablicy o indeksie 0 

Element tab[0]=*tab 

background image

 

Element tab[3] == *(tab+3) <- w tablicy jednowymiarowej 

Element tab[2][2] == *(*(tab+2)+2) <- w tablicy wielowymiarowej 

 

Wykład 8 (tablice znakowe)  

Teksty przechowuje się w tablicach typu char 

1.  pojedyncze znaki w pojedynczych apostrofach 

‘Z’ 

2.  wyrazy/zdania w cudzysłowie 

 

 

„MARCIN” 

char Imie [] = „MARCIN”; 

char Imie [] = { ‘M’, ‘A’, ‘R’, ‘C’, ‘I’, ‘N’, ‘\0’

6 znaków, ale 7 elementów 

‘\0’ – specjalny znak oznaczający koniec tekstu w tablicy, trzeba o tym pamiętać, gdy 
zadajemy rozmiar tablicy 

Gotowe funkcje przetwarzania tekstów: 

1.  size_t strlen (char str) – oblicza długość tekstu 

 

2.  int strcmp (char str1, char str2) – porównuje 2 teksty (który jest dłuższy) 
3.  int strncmp (char str1, char str2, n) – porównuje 2 teksty do n-tego znaku 

 

4.  int strcpy (char przeznaczenie, char źródło) – kopiowanie dwóch tekstów 
5.  int strncpy (char przeznaczenie, char źródło, n) – kopiowanie dwóch tekstów do n-

tego znaku 
 

6.  char strcat (char przeznaczenie, char źródło) – kopiowanie przez dopisanie na końcu 
7.  char strncat (char przeznaczenie, char źródło, n) – kopiowanie przez dopisanie na 

końcu do n-tego znaku 
 

8.  int toupper (char c) – mała litera na dużą 
9.  int tolower (char c) – duża litera na małą 

 

10.  int atoi (char c) – ASCII do int 
11.  int atol (char c) – ASCII do long 
12.  int atof (char c) – ASCII do double 

 

Funkcja cin.getline () – umożliwia ustawienie granicznej liczby pobieranych znaków, aby nie 
przekroczyć pojemności tablicy 

 

 

<ctype.h> 

<string.h>
.> 

Konwersje 

typów 

background image

 

Wykład 9 (struktury, unie, przeciążenia)  

Struktura – nowy typ zdefiniowany przez programistę, ale pośrednio lub bezpośrednio 
składa się z typów wbudowanych. 

Operator ‘.’ (kropka) – dostęp do zmiennych struktury 

Operator ‘->’ – wskaźnik na strukturę 

Unia – dane przetwarzane pojedynczo we wspólnej przestrzeni pamięci; ogólnie mało 
praktyczna. 

Ma rozmiar największego elementu. 

Przeciążenie operatorów (w sumie nie ogarniam tego :D ) 

arg1 @ arg2 

typ operatora @ (typ arg1, typ arg2) 

Nie można przeciążyć: 

.  .*  ::  ?: 

 

Wykład 10 (zmienne i struktury dynamiczne) 

new – dynamicznie tworzy zmienną w trakcie działania programu 

delete – kasuje zmienną utworzoną przez new 

new typ zwraca WSKAŹNIK na nowo utworzoną zmienną danego typu 

int *wd = new int; 

Int x = (*wd)++ <- pamiętać o nawiasach! 

Tablice tworzymy dynamicznie ale musimy zadać rozmiar! 

Dynamiczne struktury danych: 

1.  Stos – posiada dno i wierzchołek, dane ułożone są w sekwencji od dna do 

wierzchołka, nowe dane zapisywane są na szczycie i stają się nowym wierzchołkiem, 
pobieranie danych w odwrotnej kolejności (LIFO – last in first out) – pobierane od 
góry do dołu 

2.  Kolejka – posiada początek i koniec, dane ułożone od końca, nowe dane zapisywane 

na końcu, a pobieranie zachodzi od początku (FIFO – first in first out) 

3.  Lista – ciąg zmiennych dynamicznych powiązanych wskazaniami, zmienne posiadają 

pole wskaźnikowe (na inne zmienne), powiązania mogą być jedno- lub 
dwukierunkowe 

 

background image

 

Wykład 11 (operacje na plikach) 

Plik jest identyfikowany w każdym systemie operacyjnym w postaci nazwy 

Plik jest sekwencyjny od początku do końca. Przy zapisie/odczycie operacje odbywają się na 
aktualnej pozycji pliku 

Plik przechowuje dane o określonych typach 

1.  Pliki tekstowe, podczas dostępu następuję konwersja znaków specjalnych 
2.  Pliki binarne – brak konwersji 

#include <fstream> 

Odczyt  ifstream 

Zapis   ofstream 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

background image

 

 

Wykład 12 (wskaźniki na funkcje, rekurencja)

 

Wskaźniki do funkcji – zawierają adresy  

typ (*wskaźnik)(arg1, arg2,….) 

Rekurencja – wywołanie funkcji w treści innej (lub tej samej) funkcji 

1.  Bezpośredni – funkcja wywołuje samą siebie 
2.  Pośrednia – funkcja wywołuje inną funkcję 

Metoda iteracyjna – bez funkcji, poprzez pętle,  w ciele main() 

Metoda rekurencyjna – funkcja w funkcji w funkcji… 

Bardziej złożone algorytmy rekurencyjne mogą szybko zużyć całą przestrzeń pamięci stosu i 
zakłócić działanie programu 

 

Wykład 13 (drzewa) 

Drzewo jest strukturą przypominającą graf, składa się z węzłów i połączeń miedzy węzłami 
(krawędziami). 

Korzeń jest jedynym węzłem, który nie posiada węzłów poprzednich. 

Dla każdego innego węzła określany jest dokładnie jeden węzeł poprzedni. 

Węzły ostatnie nazywane są liśćmi

Węzeł poprzedni == przodek 

Węzły dowiązane (następne) == potomek 

Głębokość węzła u – liczba węzłów przez które trzeba przejść od korzenia do do węzła u (z 
korzeniem włącznie, sam korzeń ma głębokość 1) 

Wysokość węzła u – maksymalna liczba węzłów po drodze począwszy od u do najbardziej 
oddalonego liścia w jego poddrzewie (z węzłem u włącznie) 

Stopień węzła – liczba jego bezpośrednich następników 

Stopień drzewa – maksymalny stopień węzłów drzewa 

background image

 

 

 Na przykładzie: 

Głębokość drzewa – 5 

Stopień drzewa – 3 

 

 

 

 

 

 

Drzewo binarne – drzewo, w którym liczba następnych elementów wynosi dokładnie 2 
(drzewo stopnia 2). 

W drzewie binarnym każdy z węzłów zawiera wskazania na dwa inne węzły: lewy i prawy. 

Kopiec (stog) – uporządkowane drzewo binarne spełniające tzw. warunek kopca tzn. każdy 
następnik jest nie większy (może być równy!) od poprzednika 

1.  W korzeniu jest największy element 
2.  Na ścieżkach od korzenia do liścia elementy są posortowane nierosnąco (max-heap) 

lub niemalejąco (min-heap) 

3.  Drzewo musi być kompletne – wypełnione od lewej do prawej i kompletne na 

wszystkich poziomach (za wyjątkiem ostatniego który może być niedopłeniony od 
prawej) 

4.  Tablica posortowana w porządku nierosnącym jest kopcem max-heap 

 

 

 

 

 

 

 

 

 

 

background image

10 

 

Binarne drzewo poszukiwań – BST – elementy są uporządkowane wg ustalonego klucza 

Wszystkie węzły lewego poddrzewa są wartością mniejszą od danego węzła, a wszystkie 
węzły prawego poddrzewa są wartością większą lub równą 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Metody przeszukiwania drzewa (K-korzeń, L-lewy 
węzeł, P-prawy węzeł) 

1.  Pre-order: KLP 
2.  In-order: LKP 
3.  Post-order: LPK 
4.  Poziomami  

 

 

 

 

 

 

background image

11 

 

Wykład 14 (złożoność obliczeniowa, algorytmy sortowania) 

Złożoność obliczeniowa algorytmu – ilość zasobów komputera jakiej potrzebuje algorytm, 
inaczej: złożoność czasowa, złożoność pamięciowa 

Za jednostkę złożoności pamięciowej przyjmuję się np. bajt 

Liczba wykonań operacji dominującej jest proporcjonalna do wykonań wszystkich operacji 

Złożoność (niewygodna w użyciu, zależy od komputera): 

1.  Pesymistyczna – w najgorszym wypadku 
2.  Oczekiwana – średnia, wartość zmiennej losowej 

Złożoność asymptotyczna: 

1.  Notacja O 
2.  Notacja Ω (duże omega) 
3.  Notacja Θ (duże teta) 

Sortowanie – proces ustawieniu zbioru elementów w określonym porządku liniowym 

1.  Sortowanie wewnętrzne – sortowanie tablic 
2.  Sortowanie zewnętrzne – sortowanie plików 

Dobra metoda sortowania powinna zachować porządek względny obiektów identycznych – 
stabilność algorytmu 

Algorytm sortowania 

Optymistyczne 

Średnie 

Pesymistyczne 

Bąbelkowe (BubbleSort) 

n

2

 

n

2

 

Wstawianie (InsertionSort) 

n

2

 

n

2

 

Wybieranie (SelectionSort 

n

2

 

n

2

 

n

2

 

Scalanie (MergeSort) 

n log n 

n log n 

n log n 

Szybkie (QuickSort) 

n log n 

n log n 

n

2

 

Kopcowanie (HeapSort) 

n log n 

n log n 

n log n 

Zliczanie (CountingSort) 

n+k 

n+k 

n+k 

 

 

 

 

 

 

 

 

 

background image

12 

 

                               Sortowanie Bąbelkowe (BubbleSort) 

 

 

 

 

 

 

 

 

Sortowanie przez Wstawianie (InsertionSort) 

 

 

 

 

 

 

 

 

 

 

 

 

 

Sortowanie przez Wybieranie (SelectionSort) 

 

 

 

 

 

 

background image

13 

 

Sortowanie szybkie (QuickSort) – 
podział tablicy, wybór piv’ota 

 

 

 

 

 

 

 

  

 

 

 

 

Sortowanie stogowe (HeapSort)  

 

Sortowanie przez Scalanie (MergeSort)