红黑树删除相关功能实现 - 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的主要内容,如果未能解决你的问题,请参考以下文章