【问题标题】:Red-Black Tree delete related functions implementation - RBT Minimum - Segmentation Fault红黑树删除相关功能实现 - 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 我已经发布了主要功能。

标签: c segmentation-fault red-black-tree


【解决方案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节点的叔叔,可能不存在

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

【讨论】:

    猜你喜欢
    • 2011-08-23
    • 1970-01-01
    • 2020-12-03
    • 2016-08-03
    • 2021-01-03
    • 1970-01-01
    • 2021-10-17
    • 2014-07-05
    相关资源
    最近更新 更多