Nadesłany przez Rafał Gawlik, 05 lutego 2012 00:52
Kod przedstawiony poniżej przedstawia główną część rozwiązania problemu.Pobierz pełne rozwiązanie.
Jeżeli nie odpowiada Ci sposób formatowania kodu przez autora skorzystaj z pretty printer'a i dostosuj go automatycznie do siebie.
bst.c:
//Drzewo BST
//Rafal Gawlik
//www.algorytm.org
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
//definicja wezla
struct wezel
{
int wartosc; //wartosc przechowywana w wezle
struct wezel *rodzic; //wskaznik na rodzica
struct wezel *l_syn; //wskaznik na lewe dziecko
struct wezel *p_syn; //wskaznik na prawe dziecko
};
struct wezel *root; //wskaźnik na root'a
//funkcja zwraca wskaznik elementu o najmniejszej wartosci (najbardziej na lewo)
struct wezel* naj_lewo(struct wezel *start)
{
if(start->l_syn != NULL)
return naj_lewo(start->l_syn);
else
return start;
}
//funkcja zwraca wezel o podanej wartosci, badz NULL, gdy taki wezel nie istnieje
struct wezel* szukaj(struct wezel *start, int wartosc)
{
//jezeli wezel ma szukana wartosc to odnalezlismy go
if (start->wartosc == wartosc) return start;
//jezeli szukana wartosc jest mniejsza to szukamy w lewym poddrzewie o ile istnieje
else if (wartosc < start->wartosc && start->l_syn != NULL) return szukaj(start->l_syn, wartosc);
//jezeli szukana wartosc jest wieksza to szukamy w prawym poddrzewie o ile istnieje
else if (wartosc > start->wartosc && start->p_syn != NULL) return szukaj(start->p_syn, wartosc);
return NULL;
}
//dodaje wezel o podanej wartosci n, do drzewa o korzeniu start
int dodawanie(int n, struct wezel *start)
{
//jezeli drzewo jest puste to dodaj korzen
if (root == NULL)
{
root = (wezel*)malloc(sizeof *root);
root->wartosc = n;
root->l_syn = NULL;
root->p_syn = NULL;
root->rodzic = NULL;
}
//jezeli zadana wartosc jest mniejsza od korzenia idz do lewego poddrzewa
else if(n < start->wartosc)
{
//jezeli lewe poddrzewo istnieje wywolaj dla niego ta funkcje rekurencyjnie
if(start->l_syn != NULL)
{
dodawanie(n,start->l_syn);
}
//jezeli lewe poddrzewo nie istnieje dodaj nowy wezel o zadanej wartosci
else
{
wezel *nowy = (wezel*)malloc(sizeof *root);
nowy->wartosc = n;
nowy->l_syn = NULL;
nowy->p_syn = NULL;
nowy->rodzic = start;
start->l_syn=nowy;
}
}
//jezeli zadana wartosc jest wieksza lub rowna korzeniowi idz do prawego poddrzewa
else
{
//jezeli prawe poddrzewo istnieje wywolaj dla niego ta funkcje rekurencyjnie
if(start->p_syn!=NULL)
{
dodawanie(n,start->p_syn);
}
//jezeli prawe poddrzewo nie istnieje dodaj nowy wezel o zadanej wartosci
else
{
wezel *nowy = (wezel*)malloc(sizeof *root);
nowy->wartosc = n;
nowy->l_syn = NULL;
nowy->p_syn = NULL;
nowy->rodzic = start;
start->p_syn=nowy;
}
}
return 0;
}
//usun wezel start
void kasowanie(struct wezel *start)
{
//jezeli wezel nie ma dzieci
if(start->l_syn==NULL && start->p_syn==NULL)
{
//jezeli wezel jest korzeniem
if(start->rodzic==NULL)
{
root=NULL;
}
//jezeli wezel jest po lewej stronie rodzica,
else if(start->rodzic->l_syn==start)
{
//usun wezel z lewej strony wezla rodzica
start->rodzic->l_syn=NULL;
}
else
{
//usun wezel z prawej strony wezla rodzica
start->rodzic->p_syn=NULL;
}
delete start;
}
//jezeli wezel ma tylko jedno dziecko
else if(start->l_syn==NULL || start->p_syn==NULL)
{
//jezeli po lewej stronie nie ma dziecka
if(start->l_syn==NULL)
{
//jezeli wezel jest korzeniem
if(start->rodzic==NULL)
{
root=start->p_syn;
}
//jezeli wezel jest po lewej stronie rodzica
else if(start->rodzic->l_syn==start)
{
//przyczep z lewej strony rodzica wezel bedacy po prawej stronie usuwanego wezla
start->rodzic->l_syn=start->p_syn;
}
else
{
//przyczep z prawej strony rodzica wezel bedacy po prawej stronie usuwanego wezla
start->rodzic->p_syn=start->p_syn;
}
}
else
{
//jezeli wezel jest korzeniem
if(start->rodzic==NULL)
{
root=start->l_syn;
}
//jezeli wezel jest po lewej stronie rodzica
else if(start->rodzic->l_syn==start)
{
//przyczep z lewej strony rodzica wezel bedacy po lewej stronie usuwanego wezla
start->rodzic->l_syn=start->l_syn;
}
else
{
//przyczep z prawej strony rodzica wezel bedacy po prawej stronie usuwanego wezla
start->rodzic->p_syn=start->l_syn;
}
}
delete start;
}
else
{
//wstaw w miejsce usuwanego elementu - najmniejsza wartosc z prawego poddrzewa
struct wezel *temp;
temp=naj_lewo(start->p_syn);
start->wartosc = temp->wartosc;
kasowanie(temp);
}
}
//przejdz drzewo w kolejnosci zaczynajac od wezla start
void in_order_tree_walk(struct wezel *start)
{
if(start->l_syn != NULL) //jezeli ma dzieci po lewej stronie wywolaj funkcje rekurencyjnie
in_order_tree_walk(start->l_syn);
printf("%d\n", start->wartosc); //wypisz wartosc
if(start->p_syn != NULL) //jezeli ma dzieci po prawej stronie wywolaj rekurencyjnie
in_order_tree_walk(start->p_syn);
}
//lsouje wartosc w przedziale od a do b
int losowanie(int a, int b)
{
if(a < b)
return a + (int)((b-a+1.0)*(rand()/(RAND_MAX+1.0)));
else
{
fprintf(stderr, "złe wartości");
return -1;
}
}
//przklad uzycia drzewa BST
int main(int argc, char *argv[])
{
int i;
//pobierz rozmiar drzewa z parametru wejsciowego
int a,k,size=atoi(argv[1]);
root = NULL;
struct timezone tz;
struct timeval tv;
gettimeofday(&tv, &tz);
srand(tv.tv_usec);
//losuj wartosc elementow
for(i=0;i<size;i++)
{
a=losowanie(1,100);
dodawanie(a, root);
}
printf("\n");
//przejdz drzewo w kolejnosci
in_order_tree_walk(root);
//usun wartosc z drzewa
printf("Wartość węzła do usunięcia: \n");
scanf("%d", &k);
kasowanie(szukaj(root,k));
printf("\n\n");
//przejdz drzewo w kolejnosci
in_order_tree_walk(root);
return 0;
}

