Я хочу поместить данные в двоичное дерево, но оно показывает ошибку сегментации после 3 входов

Это функция 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, но это приведет к тому, что результирующее двоичное дерево перестает быть двоичным деревом поиска . Узлы будут расположены неправильно в большинстве случаев.


В вашем коде три опечатки,

  1. Ваш malloc выделяет размер указателя, а не узла. то есть malloc (sizeof (struct bst))
  2. if(data<<p->data) влево, чем сравнивает. Заменить на просто сравнение if(data < p->data)
  3. 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;
    }

}


Есть идеи?

10000