Это функция push для ввода данных в двоичное дерево. Это вызывает ошибку сегментации при третьем вызове. Проверьте код для больше.
void push(){
int data;
printf("enter the data you want to enter");
scanf("%d",&data);
struct bst* temp;
temp=(struct bst*)malloc(sizeof(struct bst*));
temp->data=data;
if(root==NULL){
temp->right=NULL;
temp->left=NULL;
root=temp;
}else{
struct bst* p;
p=root;
while(p->left!=NULL || p->right!=NULL){
if(data<<p->data){
p=p->left;
}else{
p=p->right;
}
}
if(data>>p->data){
temp->left=NULL;
temp->right=NULL;
p->right=temp;
}else{
temp->left=NULL;
temp->right=NULL;
p->left=temp;
}
}
}
Всего 3 ответа
Когда вы пересекаете дерево, вы используете условие p->left!= NULL OR p->right!= NULL
. В этом случае, если слева от вашего дерева не NULL, в этом случае вы назначаете NULL для p. Затем вы сравниваете данные с данными переменной NULL. Это вызывает ошибку сегментации. Вы должны добавить оператор AND вместо OR к условию while:
while(p->left!=NULL && p->right!=NULL){
Также в этой строке if(data>>p->data){
вы используете оператор сдвига вправо вместо оператора большего размера. Вы должны напечатать это правильно.
Существует множество проблем с представленным кодом, некоторые из которых были представлены в комментариях и в другом ответе. Среди них
Вы не выделяете достаточно места для каждого узла (на @EddInglis). В результате вы пишете за пределами выделенного объекта, когда устанавливаете один или несколько его членов, что приводит к неопределенному поведению. Это, вероятно, источник сегфолтов . В качестве связанного, но второстепенного вопроса, в C вам не нужно явно преобразовывать значения типа void *
в другие типы указателей объектов для присваивания, и, как вопрос стиля и хорошей практики программирования, вам не следует этого делать.
Ваша условная логика обхода дерева неверна (для @hhusein). Условие p->left!=NULL || p->right!=NULL
p->left!=NULL || p->right!=NULL
выполняется для всех узлов, которые не являются листьями, но вам также необходимо учесть случай внутренних узлов, у которых есть только один дочерний элемент. Это, вероятно , не является причиной segfault, хотя. Это просто склонно к потере данных и утечке памяти.
Ваша условная логика выбора направления движения в дереве неверна:
if(data<<p->data){
...
if(data>>p->data){
Операторы <<
и >>
вычисляют битовые сдвиги влево и вправо. Вместо этого вы ищете реляционные операторы ( <
и >
). Это не несет ответственности за ваш segfault, но это приведет к тому, что результирующее двоичное дерево перестает быть двоичным деревом поиска . Узлы будут расположены неправильно в большинстве случаев.
В вашем коде три опечатки,
malloc
выделяет размер указателя, а не узла. то есть malloc (sizeof (struct bst)) if(data<<p->data)
влево, чем сравнивает. Заменить на просто сравнение if(data < p->data)
if(data>>p->data)
является оператором сдвига вправо, и вам нужно if(data>p->data)
Помимо опечаток, логика, чтобы найти правильный заполнитель для нового созданного узла должна быть исправлена.
temp->left= NULL;
temp->right= NULL;
while(p){
if(data < p->data){
if(!p->left) {
p->left = temp;
break;
}
p=p->left;
}else if(data > p->data) {
if(!p->right) {
p->right = temp;
break;
}
p=p->right;
}else{
//Skip insertion for same key
break;
}
}