红黑树删除相关功能实现 - RBT Minimum - Segmentation Fault

Posted

技术标签:

【中文标题】红黑树删除相关功能实现 - RBT Minimum - Segmentation Fault【英文标题】:Red-Black Tree delete related functions implementation - RBT Minimum - Segmentation Fault 【发布时间】:2022-01-15 02:27:25 【问题描述】:

我目前正在实现红黑树 (RBT) 功能。到目前为止,插入和搜索功能都在正常工作。然而,“烦人”的部分来了。我正在尝试实现一个执行删除的功能。在删除、删除修复和移植中一切正常,但是当涉及到“最小”功能时,我确实遇到了分段错误。很可能我没有正确编写该函数,你们能帮帮我吗?

这里是删除部分相关的代码:

void rotateLeft( nodo_alberoRBT** T, nodo_alberoRBT* x)

    nodo_alberoRBT *y  = x->figlio_destro;    
    x->figlio_destro = y->figlio_sinistro;     
    if (y->figlio_sinistro != T_Nil)
        y->figlio_sinistro->padre = x;
    y->padre = x->padre;  
    if (x->padre == T_Nil)
        *T = y;
    else if (x == x->padre->figlio_sinistro)
        x->padre->figlio_sinistro = y;
    else
        x->padre->figlio_destro = y;
    y->figlio_sinistro   = x;            
    x->padre = y;


void rotateRight(nodo_alberoRBT** T, nodo_alberoRBT* y)

    nodo_alberoRBT *x  = y->figlio_sinistro;     
    y->figlio_sinistro  = x->figlio_destro;    
    if (x->figlio_destro != T_Nil)
        x->figlio_destro->padre = y;
    x->padre = y->padre;  
    if (y->padre == T_Nil)
        *T = x;
    else if (y == y->padre->figlio_destro)
        y->padre->figlio_destro = x;
    else
        y->padre->figlio_sinistro  = x;
    x->figlio_destro  = y;         
    y->padre = x;


void transplantRBT(struct nodo_alberoRBT** root, struct nodo_alberoRBT* u, struct nodo_alberoRBT* v)
    if(u->padre == T_Nil)
        *root = v;
     
    else if(u == u->padre->figlio_sinistro)
        u->padre->figlio_sinistro = v;
     else 
        u->padre->figlio_destro = v;
    

    v->padre = u->padre;


void deleteFixupRBT(struct nodo_alberoRBT** root, struct nodo_alberoRBT* x)
    while((x != root[0]) && (x->color == BLACK))
        if(x == x->padre->figlio_sinistro)
            struct nodo_alberoRBT* w = x->padre->figlio_destro;

            if(w->color == RED)
                w->color = BLACK; // caso 1
                x->padre->color = RED; // caso 1
                rotateLeft(root, x->padre); // caso 1
                w = x->padre->figlio_destro; // caso 1
            

            if((w->figlio_sinistro->color == BLACK) && (w->figlio_destro->color == BLACK))
                w->color = RED; // caso 2
                x = x->padre; // caso 2
            
            else if(w->figlio_destro->color == BLACK)
                w->figlio_sinistro->color = BLACK; // caso 3
                w->color = RED; // caso 3
                rotateRight(root, w); // caso 3
                w = x->padre->figlio_destro; // caso 3
             else 
                w->color = x->padre->color; // caso 4
                x->padre->color = BLACK; // caso 4
                w->figlio_destro->color = BLACK; // caso 4
                rotateLeft(root, x->padre); // caso 4
                x = root[0]; // caso 4
            
         else 
            struct nodo_alberoRBT* w = x->padre->figlio_sinistro;

            if(w->color == RED)
                w->color = BLACK; // caso 1
                x->padre->color = RED; // caso 1
                rotateRight(root, x->padre); // caso 1
                w = x->padre->figlio_sinistro; // caso 1
            

            if((w->figlio_destro->color == BLACK) && (w->figlio_sinistro->color == BLACK))
                w->color = RED; // caso 2
                x = x->padre; // caso 2
            
            else if(w->figlio_sinistro->color == BLACK)
                w->figlio_destro->color = BLACK; // caso 3
                w->color = RED; // caso 3
                rotateLeft(root, w); // caso 3
                w = x->padre->figlio_sinistro; // caso 3
             else

                w->color = x->padre->color; // caso 4
                x->padre->color = BLACK; // caso 4
                w->figlio_sinistro->color = BLACK; // caso 4
                rotateRight(root, x->padre); // caso 4
                x = root[0]; // caso 4
            
        
    
    x->color = BLACK;


// nodo minimo
struct nodo_alberoRBT* nodo_minimoRBT(struct nodo_alberoRBT* nodo)
    while(nodo->figlio_sinistro != T_Nil)
        nodo = nodo->figlio_sinistro;
    

    return nodo;


struct nodo_alberoRBT* successoreRBT(struct nodo_alberoRBT* nodo)
    if(nodo != T_Nil)
        return nodo_minimoRBT(nodo->figlio_destro);
    

    struct nodo_alberoRBT* nodo2 = nodo->padre;
    while(nodo2 != T_Nil && nodo == nodo2->figlio_destro)
        nodo = nodo2;
        nodo2 = nodo2->padre;
    

    return nodo2;


void deleteRBT(struct nodo_alberoRBT** root, struct nodo_alberoRBT* z)
    struct nodo_alberoRBT* y = z;
    char y_colore_originale;
    y_colore_originale = y->color;
    struct nodo_alberoRBT* x;

    if(z->figlio_sinistro == T_Nil)
        x = z->figlio_destro;
        transplantRBT(root, z, z->figlio_destro);
     
    else if(z->figlio_destro == T_Nil)
        x = z->figlio_sinistro;
        transplantRBT(root, z, z->figlio_sinistro);
    
    else 
        y = nodo_minimoRBT(z->figlio_destro);
        y_colore_originale = y->color;
        x = y->figlio_destro;
        if(y->padre == z)
            x->padre = y;
         else 
            transplantRBT(root, y, y->figlio_destro);
            y->figlio_destro = z->figlio_destro;
            y->figlio_destro->padre = y;
        
        transplantRBT(root, z, y);
        y->figlio_sinistro = z->figlio_sinistro;
        y->figlio_sinistro->padre = y;
        y->color = z->color;
    

    if(y_colore_originale == BLACK)
        deleteFixupRBT(root, x);
    

    root[0]->color = BLACK;


float singolo_esperimentoRBT(int max_chiavi, int max_search, int max_delete, int max_istanze)
    double t_tot = 0;
    int istanza = 0;
    int chiave, ricerca, eliminazione;
    struct nodo_alberoRBT* t_root;

    for(istanza = 1 ; istanza <= max_istanze ; istanza++)

        t_root = T_Nil;
        clock_t inizioTempo, fineTempo; //dichiaro queste due variabili di tipo clock_t (typedef)
        inizioTempo = clock(); // inizia il tempo

        for(eliminazione = 1; eliminazione <= max_delete; eliminazione++)
            deleteRBT(&t_root, newNode(rand()));
         

        fineTempo = clock(); // termina il tempo
        double differenzialeTempo = (double) (fineTempo - inizioTempo);  //differenza tra tempo di fine e inizio
        t_tot = t_tot + differenzialeTempo; // sommo il tempo totale dell'esperimentoBST singolo

    

    return t_tot/max_chiavi;


void esperimentoRBT(int min_chiavi, int max_chiavi)
    int step = 10000;
    int istanze_massime = 5;
    int percentuale_ricerca = 60;
    int chiavi = 0; 
    int seed = 164333; // seed
    double tempoBST = 0 , tempoRBT = 0;
    for(chiavi = min_chiavi; chiavi <= max_chiavi; chiavi = chiavi + step)
        double max_search = chiavi * percentuale_ricerca/100;
        double max_delete = chiavi - max_search;
        srand(seed);
        tempoBST = singolo_esperimentoBST(chiavi, max_search, max_delete, istanze_massime); // richiamo s.esperimento BST
        tempoRBT = singolo_esperimentoRBT(chiavi, max_search, max_delete, istanze_massime); // richiamo s.esperimento RBT
        printf("Tempo RBT: %f - Chiavi: %d\n",tempoRBT, chiavi);

        seed++;
    


int main(void)

    int min_chiavi = 10000;
    int max_chiavi = 100000;

    esperimentoRBT(min_chiavi, max_chiavi);
    return 0;

提前致谢!

【问题讨论】:

没有人能够阅读您的代码。您还可以发布一个测试失败的main 吗? @alinsoar 我已经发布了主要功能。 【参考方案1】:

这些行几乎肯定是错误的:

if((w->figlio_destro->color == BLACK) && (w->figlio_sinistro->color == BLACK))

因为如果你删除 x 作为一个节点并且它是一个叶子节点,w(它的兄弟)将会存在,但是 w 的子节点可能不存在。这意味着 w->figlio_destro 可能为 NULL,而 w->figlio_sinistro 可能为 NULL

你应该有一个函数(可能是内联的)

bool IsBlack(const nodo_alberoRBT* n) return n == NULL || n->颜色==黑色)

并使用它。

Insert 情况也是如此。底部插入节点的Parent节点的叔叔,可能不存在

黑节点:如果叶子可能不存在,否则它确实存在 红节点:永远真实

【讨论】:

以上是关于红黑树删除相关功能实现 - RBT Minimum - Segmentation Fault的主要内容,如果未能解决你的问题,请参考以下文章

深入理解红黑树(RBT)

BST(二叉搜索树),AVL(平衡二叉树)RBT(红黑树)的区别

C语言中的红黑树实现

红黑树-RBT(基本操作之左旋)

RBT

RBT