#include <iostream>
struct wezel
{
int wartosc;
struct wezel *rodzic;
struct wezel *l_syn;
struct wezel *p_syn;
};
struct wezel *root=NULL;
using namespace std;
//funkcja zwraca wskaznik elementu o najmniejszej wartosci (najbardziej na lewo)
struct wezel* naj_lewo(struct wezel *start)
{
if(start && start->l_syn)
return naj_lewo(start->l_syn);
else
return start;
}
//funkcja zwraca wskaznik elementu o najwiekszej wartosci (najbardziej na prawo)
struct wezel* naj_prawo(struct wezel *start)
{
if(start && start->p_syn)
return naj_prawo(start->p_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)
{
if(!start)
return NULL;
//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 = new wezel;
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 = new wezel;
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 = new wezel;
nowy->wartosc = n;
nowy->l_syn = NULL;
nowy->p_syn = NULL;
nowy->rodzic = start;
start->p_syn=nowy;
}
}
return 0;
}
void kasowanie(struct wezel *start)
{
if(start==NULL)
return;
//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) || (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)
{
in_order_tree_walk(start->l_syn);
cout << start->wartosc << " ";
in_order_tree_walk(start->p_syn);
}
}
void pre_order_tree_walk(struct wezel *start)
{
if(start)
{
cout << start->wartosc << " ";
pre_order_tree_walk(start->l_syn);
pre_order_tree_walk(start->p_syn);
}
}
void post_order_tree_walk(struct wezel *start)
{
if(start)
{
post_order_tree_walk(start->l_syn);
post_order_tree_walk(start->p_syn);
cout << start->wartosc << " ";
}
}
// Funkcja znajduje następnik węzła p
//-----------------------------------
wezel * znajdzNastepnika(wezel * p)
{
wezel * r;
if(p)
{
if(p->rodzic)
return naj_lewo(p->p_syn);
else
{
r = p->rodzic;
while(r && (p == r->p_syn))
{
p = r;
r = r->rodzic;
}
return r;
}
}
return p;
}
// Funkcja znajduje poprzednik węzła p
//------------------------------------
wezel * znajdzPoprzednika(wezel * p)
{
wezel * r;
if(p)
{
if(p->l_syn)
return naj_prawo(p->l_syn);
else
{
r = p->rodzic;
while(r && (p == r->l_syn))
{
p = r;
r = r->rodzic;
}
return r;
}
}
return p;
}
void Clear(wezel *x)
{
if( x != NULL )
{
Clear( x->l_syn );
Clear( x->p_syn );
delete x;
}
}
int main()
{
int ileTestow;
cin >> ileTestow;
for(int i=1; i<=ileTestow; i++)
{
cout << "test " << i << endl;
int n;
cin >> n;
while(n--)
{
char command;
int x;
cin >> command >> x;
if(command=='I')
{
dodawanie(x,root);
}
else if(command=='D')
{
if(root)
{
wezel *element = szukaj(root,x);
if(element)
{
kasowanie(element);
}
}
}
else if(command=='S')
{
if(root)
{
wezel *element = szukaj(root,x);
if(element)
{
cout << element->wartosc << endl;
}
else
{
cout << "-" << endl;
}
}
}
else if(command=='X')
{
if(root)
{
if(x==0)
{
wezel *element=naj_lewo(root);
cout << element->wartosc << endl;
}
else if(x==1)
{
wezel *element=naj_prawo(root);
cout << element->wartosc << endl;
}
}
else
{
cout << "-" << endl;
}
}
else if(command=='N')
{
wezel *element=szukaj(root,x);
if(element)
{
wezel *nastepnik = znajdzNastepnika(element);
if(nastepnik)
{
cout << nastepnik->wartosc << endl;
}
else
{
cout << "-" << endl;
}
}
else
{
cout << "-" << endl;
}
}
else if(command=='P')
{
wezel *element=szukaj(root,x);
if(element)
{
wezel *poprzednik = znajdzPoprzednika(element);
if(poprzednik)
{
cout << poprzednik->wartosc << endl;
}
else
{
cout << "-" << endl;
}
}
else
{
cout << "-" << endl;
}
}
else if(command=='R')
{
switch(x)
{
case 0:
in_order_tree_walk(root);
break;
case 1:
pre_order_tree_walk(root);
break;
case 2:
post_order_tree_walk(root);
break;
}
cout << endl;
}
}
Clear(root);
root=NULL;
}
return 0;
}