void BSTDelete (tBSTNodePtr *RootPtr, char K) { /* --------- ** Zru¹í uzel stromu, který obsahuje klíè K. ** ** Pokud uzel se zadaným klíèem neexistuje, nedìlá funkce nic. ** Pokud má ru¹ený uzel jen jeden podstrom, pak jej zdìdí otec ru¹eného uzlu. ** Pokud má ru¹ený uzel oba podstromy, pak je ru¹ený uzel nahrazen nejpravìj¹ím ** uzlem levého podstromu. Pozor! Nejpravìj¹í uzel nemusí být listem. ** ** Tuto funkci implementujte rekurzivnì s vyu¾itím døíve deklarované ** pomocné funkce ReplaceByRightmost. **/ tBSTNodePtr help_ptr = NULL; // pomocny ukazatel if ( (*RootPtr) != NULL ){ if ( (*RootPtr)->Key > K ) BSTDelete(&((*RootPtr)->LPtr), K); // hledej v levem podstromu else if ( (*RootPtr)->Key < K ) BSTDelete(&((*RootPtr)->RPtr), K); // hledej v pravem podstromu else{ // budeme rusit uzel help_ptr = *RootPtr; // preulozeni ukazatele if ( help_ptr->LPtr == NULL ){ // obsahuje jen pravy podstrom? *RootPtr = help_ptr->RPtr; free(help_ptr); } else if ( help_ptr->RPtr == NULL ){ // obsahuje jen levy podstrom? *RootPtr = help_ptr->LPtr; free(help_ptr); } else // uzel obsahuje oba podstromy, budeme hledat nejpravejsi prvek ReplaceByRightmost(*RootPtr, (&((*RootPtr)->LPtr))); } } }
void BSTDelete (tBSTNodePtr *RootPtr, char K) { /* --------- ** Zru¹í uzel stromu, který obsahuje klíè K. ** ** Pokud uzel se zadaným klíèem neexistuje, nedìlá funkce nic. ** Pokud má ru¹ený uzel jen jeden podstrom, pak jej zdìdí otec ru¹eného uzlu. ** Pokud má ru¹ený uzel oba podstromy, pak je ru¹ený uzel nahrazen nejpravìj¹ím ** uzlem levého podstromu. Pozor! Nejpravìj¹í uzel nemusí být listem. ** ** Tuto funkci implementujte rekurzivnì s vyu¾itím døíve deklarované ** pomocné funkce ReplaceByRightmost. **/ if(*RootPtr!=NULL){ //neprazdny strom if((*RootPtr)->Key==K){ //prvek nalezen tBSTNodePtr ptr=(*RootPtr); if((*RootPtr)->LPtr==NULL){ //prvek nema leveho syna *RootPtr=(*RootPtr)->RPtr; free(ptr); }else if((*RootPtr)->RPtr==NULL){//prvek nema praveho syna *RootPtr=(*RootPtr)->LPtr; free(ptr); }else //prvek ma oba syny ReplaceByRightmost(*RootPtr,&((*RootPtr)->LPtr)); }else if((*RootPtr)->Key>K) //prvek je u leveho syna BSTDelete(&((*RootPtr)->LPtr),K); else //prvek je u praveho syna BSTDelete(&((*RootPtr)->RPtr),K); } }
void ReplaceByRightmost (tBSTNodePtr PtrReplaced, tBSTNodePtr *RootPtr) { /* ------------------ ** Pomocná funkce pro vyhledání, pøesun a uvolnìní nejpravìj¹ího uzlu. ** ** Ukazatel PtrReplaced ukazuje na uzel, do kterého bude pøesunuta hodnota ** nejpravìj¹ího uzlu v podstromu, který je urèen ukazatelem RootPtr. ** Pøedpokládá se, ¾e hodnota ukazatele RootPtr nebude NULL (zajistìte to ** testováním pøed volání této funkce). Tuto funkci implementujte rekurzivnì. ** ** Tato pomocná funkce bude pou¾ita dále. Ne¾ ji zaènete implementovat, ** pøeètìte si komentáø k funkci BSTDelete(). **/ tBSTNodePtr help_ptr = NULL; // pomocny ukazatel if ( *RootPtr != NULL ){ if( (*RootPtr)->RPtr != NULL ) // overeni, jestli je opravdu nejpravejsi ReplaceByRightmost(PtrReplaced, (&((*RootPtr)->RPtr))); // posun doprava else{ PtrReplaced->Key = (*RootPtr)->Key; // prepis klic PtrReplaced->BSTNodeCont = (*RootPtr)->BSTNodeCont; // prepis obsah help_ptr = *RootPtr; // preulozeni ukazatele *RootPtr = (*RootPtr)->LPtr; // uvolneni uzlu free(help_ptr); // odstraneni pomocneho ukazatele } } }
/* POZOR NASLEDUJÍCÍ PROCEDURA BUDE POU®ITA DÁLE, ** PREÈTÌTE SI PROTO PODROBNÌ NEJPRVE KOMENTÁØ K PROCEDUØE BSTDELETE(), ** NE® ZAÈNETE VYTVÁØET REPLACEBYRIGHTMOST(). */ void ReplaceByRightmost (tBSTNodePtr PtrReplaced,tBSTNodePtr *RootPtr) { /* Pomocná procedura pro vyhledání, pøestìhování a uvolnìní nejpravìj¹ího ** uzlu v podstromu urèeném ukazatelem RootPtr. Na vstupu se pøedpokládá ** hodnota ukazatele RootPtr rùzná od NULL (zajistìte to testováním pøed ** volání procedury). Dále se pøedpokládá, ¾e pomocný ukazatel PtrReplaced ** ukazuje na uzel, který se má naplnit hodnotami vyhledaného uzlu. */ tBSTNodePtr ptr; /* pou¾ívejte tento pomocný ukazatel */ ptr = NULL; if(*RootPtr){ if((*RootPtr)->RPtr != NULL) { ReplaceByRightmost(PtrReplaced, &((*RootPtr)->RPtr)); } else if((*RootPtr)->RPtr == NULL && (*RootPtr)->LPtr != NULL) { PtrReplaced->Key = (*RootPtr)->Key; PtrReplaced->BSTNodeCont = (*RootPtr)->BSTNodeCont; ptr = PtrReplaced->LPtr; PtrReplaced->LPtr = (*RootPtr)->LPtr; free(ptr); } else { ptr = (*RootPtr); PtrReplaced->Key = (*RootPtr)->Key; PtrReplaced->BSTNodeCont = (*RootPtr)->BSTNodeCont; free(ptr); *RootPtr = NULL; } } }
void ReplaceByRightmost (tBSTNodePtr PtrReplaced, tBSTNodePtr *RootPtr) { if ( *RootPtr != NULL ) { /* Vytvoreni pomocne promenne */ tBSTNodePtr tmp = NULL ; /* Pokud RootPtr ukazuje na nejpravejsi uzel */ if ( ( *RootPtr ) -> RPtr == NULL ) { /* Do pomocne priradi ukazatel na nejpravejsi ukazatel */ tmp = *RootPtr ; /* Do uzlu, na ktery ukazuje PtrReplaced, ulozi hodnotu a klic nejpravejsiho uzlu */ PtrReplaced -> BSTNodeCont = tmp -> BSTNodeCont ; PtrReplaced -> Key = tmp -> Key ; /* Navazani do stromu */ *RootPtr = tmp -> LPtr ; /* Uvolneni pomocneho ukazatele */ free ( tmp ) ; } /* Pokud RootPtr neukazuje na nejpravejsi ukazatel */ else { ReplaceByRightmost ( PtrReplaced , ( &( *RootPtr ) -> RPtr ) ) ; } } }
void ReplaceByRightmost (tBSTNodePtr PtrReplaced, tBSTNodePtr *RootPtr) { /* ------------------ ** Pomocná funkce pro vyhledání, pøesun a uvolnìní nejpravìj¹ího uzlu. ** ** Ukazatel PtrReplaced ukazuje na uzel, do kterého bude pøesunuta hodnota ** nejpravìj¹ího uzlu v podstromu, který je urèen ukazatelem RootPtr. ** Pøedpokládá se, ¾e hodnota ukazatele RootPtr nebude NULL (zajistìte to ** testováním pøed volání této funkce). Tuto funkci implementujte rekurzivnì. ** ** Tato pomocná funkce bude pou¾ita dále. Ne¾ ji zaènete implementovat, ** pøeètìte si komentáø k funkci BSTDelete(). **/ if (*RootPtr != NULL) { if ((*RootPtr)->RPtr != NULL) { // presunuti se do nejpravejsiho uzlu ReplaceByRightmost(PtrReplaced, &(*RootPtr)->RPtr); } else { // nahrazeni nejpravejsim uzlem PtrReplaced->Key = (*RootPtr)->Key; PtrReplaced->BSTNodeCont = (*RootPtr)->BSTNodeCont; // smazani tBSTNodePtr tmpAddress; tmpAddress = (*RootPtr); (*RootPtr) = (*RootPtr)->LPtr; free(tmpAddress); } } }
void BSTDelete (tBSTNodePtr *RootPtr, char K) { /* --------- ** Zru¹í uzel stromu, který obsahuje klíè K. ** ** Pokud uzel se zadaným klíèem neexistuje, nedìlá funkce nic. ** Pokud má ru¹ený uzel jen jeden podstrom, pak jej zdìdí otec ru¹eného uzlu. ** Pokud má ru¹ený uzel oba podstromy, pak je ru¹ený uzel nahrazen nejpravìj¹ím ** uzlem levého podstromu. Pozor! Nejpravìj¹í uzel nemusí být listem. ** ** Tuto funkci implementujte rekurzivnì s vyu¾itím døíve deklarované ** pomocné funkce ReplaceByRightmost. **/ if (*RootPtr != NULL) { if ((*RootPtr)->Key == K) { // nalezl uzel s klicem K if (((*RootPtr)->RPtr != NULL) && ((*RootPtr)->LPtr != NULL)) { // ma obadva podstromy ReplaceByRightmost((*RootPtr), &(*RootPtr)->LPtr); } else if (((*RootPtr)->RPtr != NULL) || ((*RootPtr)->LPtr != NULL)) { // ma jeden podstrom if ((*RootPtr)->RPtr != NULL) { // podstrom je ulozeny jako prava vetev tBSTNodePtr tmpAddress; tmpAddress = *RootPtr; *RootPtr = (*RootPtr)->RPtr; free(tmpAddress); } else { // podstrom je ulozeny jako leva vetev tBSTNodePtr tmpAddress; tmpAddress = *RootPtr; *RootPtr = (*RootPtr)->LPtr; free(tmpAddress); } } else { // nema zadnou vetev free(*RootPtr); *RootPtr = NULL; } } else { // nenalezl klic, pokracuje v dalsi vetvi if (K < (*RootPtr)->Key) { BSTDelete(&(*RootPtr)->LPtr, K); } else { BSTDelete(&(*RootPtr)->RPtr, K); } } } else { // neni inicializovany strom return; } }
void BSTDelete (tBSTNodePtr *RootPtr, char K) { /* Zru¹í uzel stromu, který obsahuje klíè K. Pokud uzel se zadaným klíèem ** neexistuje, nedìlá nic. Ve¹keré manipulace øe¹te rekurzivnì. ** ** Pokud má ru¹ený uzel jen jeden podstrom, pak jej zdìdí otec. Pokud má ** oba podstromy, pak je ru¹ený uzel nahrazen nejpravìj¹ím uzlem levého ** podstromu. Pozor! Nejpravìj¹í uzel nemusí být listem. Pro tuto operaci ** jsme deklarovali proceduru ReplaceByRightmost -- viz. její komentáø ** uveden vý¹e. ** POZOR: Vzhledem k jisté slo¾itosti rekurzívního volání této fce zde uvádím ** pøíklad jak funkci zavolat (kdy¾ jsme pøijali RootPtr jako ukazatel na ** ukazatel). Správné zavolání napø. na levý podstrom: ** BSTDelete(&((*RootPtr)->LPtr), K). ** Podobnì je tomu tak i u ReplaceByRightMost(). ** Napøíklad: ReplaceByRightmost(*RootPtr, (&((*RootPtr)->LPtr))) */ tBSTNodePtr ptr; /* pou¾ívejte tento pomocný ukazatel */ ptr=NULL; if(*RootPtr){ if((*RootPtr)->Key < K) { BSTDelete(&((*RootPtr)->RPtr), K); } else if((*RootPtr)->Key > K) { BSTDelete(&((*RootPtr)->LPtr), K); } else if((*RootPtr)->Key == K) { if((*RootPtr)->LPtr == NULL && (*RootPtr)->RPtr != NULL){ ptr = (*RootPtr); (*RootPtr) = (*RootPtr)->RPtr; free(ptr); } else if((*RootPtr)->RPtr == NULL && (*RootPtr)->LPtr != NULL){ ptr = (*RootPtr); (*RootPtr) = (*RootPtr)->LPtr; free(ptr); } else if ((*RootPtr)->RPtr == NULL && (*RootPtr)->LPtr == NULL){ free((*RootPtr)); *RootPtr = NULL; } else { ReplaceByRightmost(*RootPtr, (&((*RootPtr)->LPtr))); } } } }
void BSTDelete (tBSTNodePtr *RootPtr, char K) { if ( *RootPtr != NULL ) { /* Pokud je klic vetsi nez K */ if ( ( *RootPtr ) -> Key > K ) { /* Pokracuje v levem podstromu */ BSTDelete ( ( &( *RootPtr ) -> LPtr ) , K ) ; } /* Pokud je klic mensi nez K */ else if ( ( *RootPtr ) -> Key < K ) { /* Pokracuje v pravem podstromu */ BSTDelete ( ( &( *RootPtr ) -> RPtr ) , K ) ; } /* Pokud najde uzel, ktery se ma rusit */ else { /* Vytvoreni pomocne promenne */ tBSTNodePtr tmp = *RootPtr ; /* Pokud uzel nema pravy podstrom */ if ( ( *RootPtr ) -> RPtr == NULL ) { /* Pripojeni leveho podstromu */ *RootPtr = ( *RootPtr ) -> LPtr ; free ( tmp ) ; } /* Pokud uzel nema levy podstrom */ else if ( ( *RootPtr ) -> LPtr == NULL ) { /* Pripojeni praveho podstromu */ *RootPtr = ( *RootPtr ) -> RPtr ; free ( tmp ) ; } else { ReplaceByRightmost ( *RootPtr , ( &( *RootPtr ) -> LPtr ) ) ; } } } }
void ReplaceByRightmost (tBSTNodePtr PtrReplaced, tBSTNodePtr *RootPtr) { /* ------------------ ** Pomocná funkce pro vyhledání, pøesun a uvolnìní nejpravìj¹ího uzlu. ** ** Ukazatel PtrReplaced ukazuje na uzel, do kterého bude pøesunuta hodnota ** nejpravìj¹ího uzlu v podstromu, který je urèen ukazatelem RootPtr. ** Pøedpokládá se, ¾e hodnota ukazatele RootPtr nebude NULL (zajistìte to ** testováním pøed volání této funkce). Tuto funkci implementujte rekurzivnì. ** ** Tato pomocná funkce bude pou¾ita dále. Ne¾ ji zaènete implementovat, ** pøeètìte si komentáø k funkci BSTDelete(). **/ //nasli jsme nejpravejsi prvek if((*RootPtr)->RPtr==NULL){ tBSTNodePtr ptr=(*RootPtr); PtrReplaced->Key=(*RootPtr)->Key; PtrReplaced->BSTNodeCont=(*RootPtr)->BSTNodeCont; *RootPtr=(*RootPtr)->LPtr; free(ptr); //zavolame funkci na praveho syna }else ReplaceByRightmost(PtrReplaced, &((*RootPtr)->RPtr)); }