#c #segmentation-fault #red-black-tree
#c #ошибка сегментации #красно-черное дерево
Вопрос:
Вот уже много дней я не могу избавиться от этой проблемы. Я пытаюсь реализовать простое красно-черное дерево (в C) с дополнительной функцией, которая вычисляет время в часах в течение всего периода вставки и поиска в дереве.
Ниже приведен мой код:
#include lt;stdio.hgt; #include lt;time.hgt; #include lt;stdlib.hgt; #include lt;limits.hgt; #define RED 'R' #define BLACK 'B' typedef struct rbtNode{ int key; char color; //this time i also added the color since its an rbt struct rbtNode *leftChild; struct rbtNode *rightChild; struct rbtNode *parent; } rbtNode; struct tree{ int cardinality; struct rbtNode *root; }; struct rbtNode* TNIL(){ rbtNode *temp = (rbtNode*)malloc(sizeof(rbtNode)); temp-gt;key; temp-gt;color = 'B'; temp-gt;leftChild = NULL; temp-gt;rightChild = NULL; temp-gt;parent = NULL; return temp; }; struct rbtNode* RootCreator(int key){ rbtNode *temp = (rbtNode*)malloc(sizeof(rbtNode)); temp-gt;key = key; temp-gt;color = 'B'; temp-gt;leftChild = NULL; temp-gt;rightChild = NULL; temp-gt;parent = NULL; return temp; }; //function for creating a new node struct rbtNode* newNodeRBT(int key){ rbtNode *temp =(rbtNode*)malloc(sizeof(rbtNode)); temp-gt;key = key; temp-gt;color = 'R'; temp-gt;leftChild = NULL; temp-gt;rightChild = NULL; temp-gt;parent = NULL; return temp; } //function for performing a left side rotation void TreeLeftRotate(struct rbtNode* root, struct rbtNode* x){ struct rbtNode* t_nil = TNIL(); struct rbtNode* y = x-gt;rightChild; //y is initialize x-gt;rightChild = y-gt;leftChild; //y's left subtree are turning into x's right subtree if(y-gt;leftChild != t_nil){ y-gt;leftChild-gt;parent = x; //y's left subtree's parent is x } y-gt;parent = x-gt;parent; //y's parent is x's parent if(x-gt;parent == t_nil){ root = y; }else if (x-gt;parent != t_nil amp;amp; x == x-gt;parent-gt;leftChild){ x-gt;parent-gt;leftChild = y; }else if(x-gt;parent != t_nil amp;amp; x == x-gt;parent-gt;rightChild){ x-gt;parent-gt;rightChild = y; } y-gt;leftChild = x; //x is turning into y's left subtree x-gt;parent = y; //x's parent is y } //function for performing a right side rotation void TreeRightRotate(struct rbtNode* root, struct rbtNode* y){ struct rbtNode* t_nil = TNIL(); struct rbtNode* x = y-gt;leftChild; //x is initialize y-gt;leftChild = x-gt;rightChild; //x's right subtree is turning into y's left subtree if(x-gt;rightChild != t_nil){ x-gt;rightChild-gt;parent = y; //x's right subtree's parent is y } x-gt;parent = y-gt;parent; //x's parent is y's parent if(y-gt;parent == t_nil){ root = x; }else if (y-gt;parent != t_nil amp;amp; y == y-gt;parent-gt;rightChild){ y-gt;parent-gt;rightChild = x; }else if(y-gt;parent != t_nil amp;amp; y == y-gt;parent-gt;leftChild){ y-gt;parent-gt;leftChild = x; } x-gt;rightChild = y; //y is turning into x's right subtree y-gt;parent = x; //y's parent is x } //function for implementing the fixup for the left side, this function is needed for performing the insert fixup void RBTreeInsertFixUpLeft(struct rbtNode* root, struct rbtNode* z){ struct rbtNode* y = z-gt;parent-gt;parent-gt;rightChild; //y is initialize if(y-gt;color == 'R'){ z-gt;parent-gt;color = 'B'; y-gt;color = 'B'; z-gt;parent-gt;parent-gt;color = 'R'; z = z-gt;parent-gt;parent; }else{ if(z == z-gt;parent-gt;rightChild){ z = z-gt;parent; TreeLeftRotate(root,z); } z-gt;parent-gt;color = 'B'; z-gt;parent-gt;parent-gt;color = 'R'; TreeRightRotate(root,z-gt;parent-gt;parent); } } //function for implementing the fixup for the right side, this function is needed for performing the insert fixup void RBTreeInsertFixUpRight(struct rbtNode* root,struct rbtNode* z){ struct rbtNode* y = z-gt;parent-gt;parent-gt;leftChild; //y is initialize if(y-gt;color == 'R'){ z-gt;parent-gt;color = 'B'; y-gt;color = 'B'; z-gt;parent-gt;parent-gt;color = 'R'; z = z-gt;parent-gt;parent; }else{ if(z == z-gt;parent-gt;leftChild){ z = z-gt;parent; TreeRightRotate(root,z); } z-gt;parent-gt;color = 'B'; z-gt;parent-gt;parent-gt;color = 'R'; TreeLeftRotate(root,z-gt;parent-gt;parent); } } //function for performing a fixup of the RBT (necessary for pergorming an insertion) void RBTreeInsertFixup(struct rbtNode* root, struct rbtNode* z){ while(z-gt;parent-gt;color == 'R'){ if(z-gt;parent == z-gt;parent-gt;parent-gt;leftChild){ RBTreeInsertFixUpLeft(root,z); //calling the function for the left side }else{ RBTreeInsertFixUpRight(root,z); //calling the function for the right side } } root-gt;color = 'B'; } //Function for inserting a new key in the RBT void RBTreeInsert(struct rbtNode* root, struct rbtNode* z){ struct rbtNode* t_nil = TNIL(); struct rbtNode* y = t_nil; struct rbtNode* x = root; while(x != t_nil){ y = x; if(z-gt;key lt; x-gt;key){ x = x-gt;leftChild ; }else{ x = x-gt;rightChild; } } z-gt;parent = y; if(y == t_nil){ root = z; }if(y != t_nil amp;amp; z-gt;key lt; y-gt;key){ y-gt;leftChild = z; }if(y != t_nil amp;amp; z-gt;key gt;= y-gt;key){ y-gt;rightChild = z; } z-gt;leftChild = t_nil; z-gt;rightChild = t_nil; z-gt;color = 'R'; RBTreeInsertFixup(root,z); } //experimenting with the insert function /*void insert(struct rbtNode* root, struct rbtNode* z) { z-gt;leftChild = z-gt;rightChild = z-gt;parent = NULL; //if root is null make z as root if (root == NULL) { z-gt;color = 'B'; root = z; } else { struct rbtNode* y = NULL; struct rbtNode* x = root; // Follow standard BST insert steps to first insert the node while (x != NULL) { y = x; if (z-gt;key lt; x-gt;key) x = x-gt;leftChild; else x = x-gt;rightChild; } z-gt;parent = y; if (z-gt;key gt; y-gt;key) y-gt;rightChild = z; else y-gt;leftChild = z; z-gt;color = 'R'; // call insertFixUp to fix reb-black tree's property if it // is voilated due to insertion. RBTreeInsertFixup(root,z); } }*/ //Function for searching a key in the RBT void RBTreeSearch(struct rbtNode* root, int k){ struct rbtNode* t_nil = TNIL(); if(root == t_nil || root-gt;key == k){ return; } if(k lt;= root-gt;key){ RBTreeSearch(root-gt;leftChild,k); RBTreeSearch(root-gt;rightChild,k); } } //Function for emptying a RBT void RBTreeDeallocate(struct rbtNode* root){ if(root == NULL){ return; } RBTreeDeallocate(root-gt;leftChild); RBTreeDeallocate(root-gt;rightChild); free(root); } //Function which executes the Single Experiment in regards to the RBT double SingleExperimentRBT(int max_keys,double max_search,int max_instances){ double t_tot = 0; int i; int key; double search; for(i = 1; ilt;=max_instances;i ){ clock_t start_t, end_t; srand(0); struct rbtNode* root = RootCreator(rand()); start_t = clock(); for(key = 1; key lt;= max_keys;key ){ RBTreeInsert(root,newNodeRBT(rand())); //inserting the keys } for(search = 1; search lt;= max_search; search ){ RBTreeSearch(root,rand()); //searching the keys } end_t = clock(); double t_elapsed = (double)(end_t - start_t); //calculating the time elapsed t_tot = t_elapsed; //RBTreeDeallocate(amp;root); //Emptying the RBT } return t_tot/max_keys; } int main(void){ int min_keys = 100000; int max_keys = 1000000; int max_instances = 5; int percentage_search = 60; int keys; int seed = 0; //setting up the main parameters for the experiments for(keys = min_keys; keys lt;= max_keys; keys = 100000){ srand(seed); double max_search = keys * percentage_search / 100; double max_delete = keys - max_search; double timeRBT = SingleExperimentRBT(keys,max_search,max_instances); printf("Number of keys: %d -- timeRBT: %fn",keys,timeRBT); seed = seed 1; } }
Если, возможно, кто-нибудь из вас сумеет помочь мне и найти решение этого ужасного кошмара, я был бы чрезвычайно благодарен!
PS: Я использовал отладчик (gdb) и нада, не могу найти никакого решения
Комментарии:
1. В качестве общего замечания я бы сделал только одну функцию, которая выделяет и инициализирует узел, а не три. Если вам часто нужны помощники, вы все равно можете вызывать эту функцию из других. Кроме того, хотя у вас есть
RED
иBLACK
определено, вы все еще используете литерал во многих местах.2. В любом случае, слишком много кода для чтения, но похоже, что вы назначаете
root
в различных функциях, но аргументroot
является локальным для функций. Вам нужен указатель на указатель, чтобы изменение было видно за пределами этой функции.3. @Arkku я пытался это сделать, но из того, что я понял, t_nil и root должны быть черными, а в обычной функции newNode-только красными
4. Хорошо, вы отредактировали вопрос, и теперь мои комментарии больше не применяются. Вы можете удалить свои комментарии по этому поводу.
5. Вставьте
if (x == NULL) { printf("Bummern"); exit(1); }
сразу послеy = x;
RBTreeInsert
ввода . Вам действительно следует потратить час или два на изучение основ вашего отладчика, который является именно тем инструментом, который вам нужен для отладки такого рода проблем.