Poniżej znajdą Państwo niektóre programy omawiane/tworzone/modyfikowane przez nas na ćwiczeniach. Nie jest to stricte materiał dydaktyczny - raczej coś w rodzaju "bloga z kodami", ot dla zgrubnej informacji, co było robione.
W trakcie ćwiczeń często będziemy modyfikowali te programy, lub wręcz pisali je od nowa (by były lepsze!)
Poniższe pliki źródłowe możesz pobierać, klikając w nazwę programu.
#include <stdio.h> #include <stdlib.h> #include <math.h> #define MAXIT 5000 /* liczba iteracji algorytmu PageRank */ /* wskaĹşnik do pomocniczego wektora roboczego */ /* do reprezentacji grafu rzadkiego wykorzystamy tym razem macierz rzadkÄ *//* macierz kwadratowa rzadka w formacie wspĂłĹrzÄdnych *//* liczba krawÄdzi, tj. liczba niezerowych elementĂłw *//* liczba wierzchoĹkĂłw grafu, tj. wymiar macierzy *//* tablice wymiaru nnz *//* wyznacza normÄ sum_i |x_i| wektora x *//* wczytuje macierz rzadkÄ z pliku formatu: n nnz I[0] J[0] V[0] I[1] J[1] V[1] I[2] J[2] V[2] .... I[nnz-1] J[nnz-1] V[nnz-1] UWAGA: w tym formacie indeksy sÄ numerowane od "1" */ { FILE *fp; /* plik z ktĂłrego czytamy macierz */ SparseMx A; /* wczytywana macierz */"r"); fscanf(fp, "%d%d", &A.n, &A.nnz); /* znamy wymiary, wiec alokujemy niezbedne tablice *//* czytamy kolejne wartosci z pliku */"%d%d%lf\n"/* oblicza y = A*x; por. SparseMultSlow() *//* algorytm obliczania Ax w innej niz "standardowa" kolejnosci *//* ta funkcja jeszcze nie dziaĹa poprawnie; uzupeĹnij puste miejsce! */ /* wskazĂłwkÄ jest postaÄ gĹĂłwnej pÄtli! *//* zwraca A[i][j], gdzie A jest w formacie wspĂłĹrzÄdnych *//* y = A*x, ale BARDZO wolno; por. SparseMult() *//* indeksy w macierzy sÄ od "1" *//* wyznacza wektor taki, ze w przyblizeniu A*p = p, stosujac metode potegowa dla wektora startowego p; w trakcie iteracji wektor p jest nadpisywany przez lepsze przyblizenia *//* work = A*x; WERSJA SLIMACZA */ norm = VecNorm(work, N); /* p = work/norm(work) */#ifdef DEBUG //G = SparseRead("c14-lab.txt"); /* graf, w ktĂłrym wystÄpujÄ liĹcie; tam algorytm moĹźe mieÄ problemy */ G = SparseRead("c14-test.txt"/* pomocniczy wektor roboczy */"%e\n"#endif
/* Wybrane procedury obsĹugi drzewa BST - drukowanie zawartoĹci: PrintTree() - wyznaczanie wysokoĹci: HeightTree() - tworzenie drzewa o losowych kluczach: InitBSTree() - sprawdzanie, czy jest BST: IsBSTree() Przyjmujemy konwencjÄ, Ĺźe prawe poddrzewo zawiera klucze wiÄksze lewe poddrzewo zawiera klucze mniejsze od klucza w korzeniu. Na potrzeby testowania kompilujemy gcc -DDEBUG -o c4-tree c4-tree.c */ #include "c4-tree.h" /*********************************************************************//* drukuje drzewo binarne w porzÄ dku pre-order */" %d ""("")"); } } /*********************************************************************//* wysokoĹÄ drzewa binarnego *//*********************************************************************//* Tworzy (byÄ moĹźe niezbalansowane) drzewo BST o "n" losowych kluczach UĹźywa - procedury AllocLeaf(), ktĂłra tworzy nowy wierzchoĹek o zadanym kluczu - procedury InsertBSTree(), ktĂłra tworzy nowy wierzchoĹek i doĹÄ cza go jako liĹÄ we wĹaĹciwym miejscu drzewa MoĹźesz poprawiÄ tak, by nie wpadaĹa w nieskoĹczonÄ pÄtlÄ "while", gdy np. brakuje pamiÄci na nowe liĹcie. Wystarczy ograniczyÄ liczbÄ ponawianych prĂłb, ale moĹźna bardziej subtelnie (wymaga wiÄkszych przerĂłbek). *//* wskaĹşnik do korzenia generowanego drzewa *//* KorzeĹ robimy na piechotÄ */ { k = rand() % (2*max); /* losujemy liczbÄ *//* skoro udaĹo siÄ zrobiÄ korzeĹ, to mamy o jeden element mniej do wstawiania! */"wstawilem korzen: %d\n"/* wstawiamy kolejne wierzchoĹki */ { k = rand() % (2*max); /* losujemy liczbÄ *//* wstawia i sprawdza, czy udalo siÄ wstawiÄ? */"wstawilem: %d\n", k); n--; /* jak udaĹo siÄ wstawiÄ, to zmniejszamy licznik *//* przydziela pamiÄÄ na liĹÄ drzewa typu "tree"; bÄdziemy to robili kilka razy, wiÄc dobrze mieÄ takÄ gotowÄ procedurÄ Od razu inicjalizuje pole "key" na zadanÄ wartoĹÄ "k"*//* inicjalizujemy liĹÄ *//* jeĹli siÄ uda, wstawia liĹÄ o kluczu "k" do NIEPUSTEGO drzewa BST "T" tak, by zachowaÄ wĹasnoĹÄ BST; generalnie moĹźe prowadziÄ do drzewa niezrĂłwnowaĹźonego; zwraca liczbÄ faktycznie wstawionych elementĂłw (tzn. 0 lub 1); */ { tree *v; /* nowy wierzchoĹek *//* ojciec bieĹźÄ cego wierzchoĹka *//* szukamy istniejÄ cego w drzewie liĹcia, do ktĂłrego moĹźnaby go doczepiÄ *//* nie wstawiamy kopii */ } parentT = T; /* ojciec dla nastÄpnego badanego wÄzĹa musimy go zapamietac, aby moc sie don potem cofnac */ /* wybieramy nastepny badany wÄzeĹ *//* doszliĹmy do koĹca drzewa, cofamy siÄ do ojca; na mocy niepustoĹci drzewa, parentT != NULL *//*********************************************************************//* zwraca logicznÄ wartoĹÄ, czy drzewo ma wĹasnoĹÄ BST Dodatkowo, jeĹli drzewo JEST drzewem BST, max == maksymalny klucz w drzewie, min == minimalny klucz w drzewie Algorytm: 1. sprawdzamy, czy lewe poddrzewo jest BST i jakie ma maksimum 2. sprawdzamy, czy prawe poddrzewo jest BST i jakie ma minimum 3. drzewo o korzeniu T jest BST, jeĹli - oba w/w poddrzewa byĹy BST - klucz korzenia speĹnia warunek: maksimum lewego poddrzewa <= klucz korzenia <= minimum prawego poddrzewa 4. obliczamy maksymalny i minimalny klucz w caĹym drzewie biorÄ c maksimum (minimum) z wĹaĹciwego poddrzewa i klucza korzenia. ZwrĂłÄ uwagÄ, nasza funkcja IsBSTree musi zwracaÄ TRZY wartoĹci (czy jest BST, maksimum i minimum), dlatego dwie ostatnie sÄ argumentami wywoĹania ze wskaĹşnikami! Jak chcesz, popraw funkcjÄ by zawsze zwracaĹa max i min z caĹego drzewa, niezaleĹźnie od tego, czy ma ono wĹasnoĹÄ BST, czy nie. *//* sprawdzamy lewe poddrzewo (o ile istnieje!) */ isBSTLeft = IsBSTree( T->left, &maxleft, &minleft); /* teraz wiemy, czy ono ma wĹasnoĹÄ BST i dodatkowo znamy maksymalny i minimalny klucz w tym poddrzewie */ /* zatem maksymalny element w caĹym drzewie "T" musi byÄ... */ *max = MAX(maxleft,T->key); /* drzewo "T" ma wĹasnoĹÄ BST, jeĹli 1. jego lewe poddrzewo jest BST i DODATKOWO 2. klucz w wierzchoĹku "T" nie jest wiÄkszy od wszystkich z lewego poddrzewa, czyli od maksymalnego klucza z lewego poddrzewa *//* powtarzamy analogiczny test dla prawego poddrzewa */#ifdef DEBUG "Wywolanie: %s N,\n\t gdzie N jest liczba wierzcholkow\n""\n""Drzewo ma wysokosc %d\n""BST: %d, %d %d\n"#endif
#include <stdlib.h> #include <stdio.h> /* zawsze przydatne makra liczÄ ce MAX i MIN z dwĂłch liczb */ #define MIN(X,Y) ((X) < (Y) ? (X) : (Y)) #define MAX(X,Y) ((X) > (Y) ? (X) : (Y)) /* definicja typu drzewiastego *//* kilka staĹych symbolicznych potrzebnych do obsĹugi procedury tworzenia drzewa */ #define TREE_SUCCESS 0 #define TREE_UNDEFINED_ERROR -1 #define TREE_MEMORY_ERROR -2 #define TREE_EXIST_ERROR -4 /* lista prototypĂłw funkcji definiowanych w c4-tree.c */Ćwiczenia 2
c2-mx1.c
#include <stdio.h> #include "c2-mx1.h" /* drukuje zadana macierz A wymiaru n */"%5.2f ""\n"/* wypelnia macierz A wymiaru n kolejnymi liczbami *//* alokuje pamiec na macierz A wymiaru n i zwraca wskaznik do niej */"Not enough free memory\n"/* mozesz poprawic te funkcje tak, by w przypadku braku pamieci zwracala NULL i wypisywala komunikat o bledzie (pamietaj, na stderr!) *//* usuwa z pamieci macierz A */ free(A); } #ifdef DEBUG #define N 4 #endifc2-mx1.h
#include <stdlib.h>c2-mx2.c
#include <stdio.h> #include "c2-mx2.h" /* drukuje zadana macierz A wymiaru nxm *//* wypelnia macierz A wymiaru nxm kolejnymi liczbami *//* alokuje pamiec na macierz A wymiaru nxm i zwraca wskaznik do niej *//* mozesz poprawic te funkcje tak, by w przypadku braku pamieci na ktorykolwiek z elementow: - usuwala dotychczas zarezerwowane wiersze - usuwala pamiec przydzielona na A - zwracala NULL Czy da sie w tym celu skorzystac z delete_mx_2d? *//* usuwa z pamieci macierz A o n wierszach *//*******************DIRTY TRICK***********************//* * NIE UZYWAJ! * drukuje zadana macierz A (statycznie alokowana) wymiaru nxm */"%5.2f ""\n"); } } /******************* end of DIRTY TRICK***********************/ #ifdef DEBUG #define N 4 #define M 3 /* dynamicznie *//* statycznie */#endifc2-mx2.h
#include "c2-mx1.h"c2-testmx.c
#include "c2-mx2.h" /* uwaga: automatycznie dolacza c1-mx1.h */ #define N 9 #define M 8 /* test dla macierzy 1d: X jest statyczna *//* test dla macierzy 1d: Y jest dynamiczna *//* test dla macierzy 2d: Z jest dynamiczna */c2-Makefile
# przed uzyciem, zmien nazwe tego pliku na "Makefile" # lub uzywaj go poleceniem # make -f c2-Makefile testmx CC = gcc OBJ = c2-testmx.o c2-mx1.o c2-mx2.o INC = c2-mx1.h c2-mx2.h testmx: $(OBJ) $(CC) -o $@ $(OBJ) %.o: %.c $(INC) Makefile $(CC) -c $< clean: rm -f $(OBJ) textmxĆwiczenia 1
c1-mx1.c
#include <stdio.h> #include <stdlib.h> #include "c1-mx1.h" /* drukuje zadana macierz A wymiaru n */"%5.2f ""\n"/* wypelnia macierz A wymiaru n kolejnymi liczbami */#ifdef DEBUG #define N 4 #endifc1-mx1.h
c1-mx2.c
#include <stdio.h> #include <stdlib.h> #include "c1-mx2.h" /* drukuje zadana macierz A wymiaru nxm */"%5.2f ""\n"/* wypelnia macierz A wymiaru nxm kolejnymi liczbami *//* alokuje pamiec na macierz A wymiaru nxm i zwraca wskaznik do niej *//* mozesz poprawic te funkcje tak, by w przypadku braku pamieci: - usuwala dotychczas zarezerwowane wiersze - usuwala pamiec przydzielona na A - zwracala NULL *//* usuwa z pamieci macierz A o n wierszach */#ifdef DEBUG #define N 4 #define M 3 #endifc1-mx2.h
c1-testmx.c
#include "c1-mx1.h" #define N 9 /* test dla macierzy 1d: X */c14-google.c
#include <stdio.h> #include <stdlib.h> #include <math.h> #define MAXIT 5000 /* liczba iteracji algorytmu PageRank */ /* wskaĹşnik do pomocniczego wektora roboczego */ /* do reprezentacji grafu rzadkiego wykorzystamy tym razem macierz rzadkÄ *//* macierz kwadratowa rzadka w formacie wspĂłĹrzÄdnych *//* liczba krawÄdzi, tj. liczba niezerowych elementĂłw *//* liczba wierzchoĹkĂłw grafu, tj. wymiar macierzy *//* tablice wymiaru nnz *//* wyznacza normÄ sum_i |x_i| wektora x *//* wczytuje macierz rzadkÄ z pliku formatu: n nnz I[0] J[0] V[0] I[1] J[1] V[1] I[2] J[2] V[2] .... I[nnz-1] J[nnz-1] V[nnz-1] UWAGA: w tym formacie indeksy sÄ numerowane od "1" */ { FILE *fp; /* plik z ktĂłrego czytamy macierz */ SparseMx A; /* wczytywana macierz */"r"); fscanf(fp, "%d%d", &A.n, &A.nnz); /* znamy wymiary, wiec alokujemy niezbedne tablice *//* czytamy kolejne wartosci z pliku */"%d%d%lf\n"/* oblicza y = A*x; por. SparseMultSlow() *//* algorytm obliczania Ax w innej niz "standardowa" kolejnosci *//* ta funkcja jeszcze nie dziaĹa poprawnie; uzupeĹnij puste miejsce! */ /* wskazĂłwkÄ jest postaÄ gĹĂłwnej pÄtli! *//* zwraca A[i][j], gdzie A jest w formacie wspĂłĹrzÄdnych *//* y = A*x, ale BARDZO wolno; por. SparseMult() *//* indeksy w macierzy sÄ od "1" *//* wyznacza wektor taki, ze w przyblizeniu A*p = p, stosujac metode potegowa dla wektora startowego p; w trakcie iteracji wektor p jest nadpisywany przez lepsze przyblizenia *//* work = A*x; WERSJA SLIMACZA */ norm = VecNorm(work, N); /* p = work/norm(work) */#ifdef DEBUG //G = SparseRead("c14-lab.txt"); /* graf, w ktĂłrym wystÄpujÄ liĹcie; tam algorytm moĹźe mieÄ problemy */ G = SparseRead("c14-test.txt"/* pomocniczy wektor roboczy */"%e\n"#endifc1-Makefile
# przed uzyciem, zmien nazwe tego pliku na "Makefile" CC = gcc OBJ = c1-testmx.o c1-mx1.o c1-mx2.o INC = c1-mx1.h c1-mx2.h testmx: $(OBJ) $(CC) -o $@ $(OBJ) %.o: %.c $(INC) Makefile $(CC) -c $< clean: rm -f $(OBJ) textmx