вставка и удаление бинарного дерева - C

Я вставил узел и удалил дерево с помощью учебника. Я тестирую его, и он работает нормально. Однако я не могу понять, почему мне нужно передать по ссылке корень в вставке, а в deleteAll только указатель. Потому что я думаю, что передача только указателя является ссылкой на значение, а затем каждое изменение видно только в функции.

typedef struct node{
    int element;
    struct node *left;
    struct node *right;
}*tTree;

void insert(tTree *myTree, int element){
  if(*myTree == NULL){
    myTree= (tTree)malloc(sizeof(*myTree));
    myTree->element = element;
    myTree->left = NULL;
    myTree->right = NULL;   
  }
  else{
    int treeElement = (*myTree)->element;
    if( treeElement > element){
      insert(&(*myTree)->left, element);
    }
    else{
      insert(&(*myTree)->right, element);
    }
  }
}



void deleteAll(tTree myTree){
    if(myTree != NULL){
        deleteAll(myTree->right);
        deleteAll(myTree->left);
        free(myTree);
    }
}

int size(tTree myTree){
    if (myTree != NULL){
        return 1 + size(myTree->right) + size(myTree->left);    
    }
    else
        return 0;
}

int main(){

  tTree root = NULL;
  insert(&root,3);
  insert(&root,2);
  insert(&root,4);
  insert(&root,1);
  printf("Number of nodes: %d\n",size(root));   
  deleteAll(root);
    root = NULL;
  printf("Number of nodes: %d\n",size(root));   
  return 1;
}

person Joseph    schedule 27.07.2015    source источник
comment
Это просто, подписывая функции, вставка получает указатель на структуру, а удаление получает только структуру. Я рекомендую прочитать об арифметике указателей и ее использовании в каждом случае   -  person santiago92    schedule 27.07.2015
comment
Другие плохие практики - это новое в C, потому что вы смешиваетесь с POO и структурированным программированием.   -  person santiago92    schedule 27.07.2015
comment
это имя переменной.   -  person Joseph    schedule 27.07.2015
comment
@ Джозеф, «новый» - это ключевое слово в C ++. Во избежание путаницы (и проблем с компиляцией/выполнением, если вы используете компилятор, поддерживающий C++), не используйте неправильно имена ключевых слов одного языка в программе, предназначенной для другого языка.   -  person user3629249    schedule 27.07.2015
comment
вы можете заметить, что 'tTree' не дает никаких указаний на то, что это на самом деле указатель. Это одна из «многих» проблем с использованием «typedef» в определениях структур. Такая проблема будет наиболее заметна через 6 месяцев (или 6 лет), когда другой программе придется поддерживать ваш код. Даже сейчас мне пришлось посмотреть несколько раз, прежде чем я понял, что код создал указатель с помощью оператора typedef в структуре. Теперь некоторые «программисты» не могут печатать очень хорошо, поэтому они пытаются свести к минимуму объем ввода, используя «typedef», чтобы им не приходилось вводить «struct» несколько раз.   -  person user3629249    schedule 27.07.2015
comment
@user3629249user3629249Не тратьте деньги на объяснение, я просто хотел знать, так кажется, потому что, если вы продолжаете смотреть на код для использования malloc, это довольно плохо, и это делает небольшое знание C, но ни один из них не интересовался изучением или исправлением имени переменная   -  person santiago92    schedule 27.07.2015
comment
@ santiago92 santiago92 Я не изменил его, потому что, хотя вы не видели, что переменная была названа новой. Я изменю его, чтобы другие не повторяли ту же ошибку. Иногда, когда мы пишем комментарии на подобных форумах, то, как они пишутся, отличается от того, как мы бы это сказали.   -  person Joseph    schedule 27.07.2015
comment
@user3629249 user3629249 Да, я знаю, что это не лучший способ, но мне пришлось сделать это именно так, потому что именно так структура была определена в книге, чтобы показать использование typedef. Я определенно предпочитаю другие формы. Спасибо за ваш комментарий!   -  person Joseph    schedule 27.07.2015
comment
Это нормально, но помните в следующий раз, что в большинстве языков ООП слово new зарезервировано, поэтому его нельзя использовать для имени локальной переменной :)   -  person santiago92    schedule 27.07.2015
comment
@ santiago92 да, ты прав. Спасибо за совет. Также я читал, что вы сказали что-то о Мэллоке. Я использую это так, потому что я видел, что это правильно. Я протестировал программу с помощью valgrind, и вывод был правильным. Может быть, вы знаете что-то, что я забыл.   -  person Joseph    schedule 27.07.2015
comment
Извините, я неправильно выразился, malloc используется правильно, я вижу что-то сложное, это то, что решает функция sizeof(), обычно это используется для определения размера в байтах различных типов данных, поэтому правильно поставить sizeof(tTree ) вместо sizeof(* new), это совет для будущих реализаций, не поймите меня неправильно, Приветствую   -  person santiago92    schedule 28.07.2015
comment
myTree= (tTree)malloc(sizeof(*myTree)); здесь вас смутил собственный типизированный указатель. (с обеих сторон отсутствует уровень косвенности)   -  person wildplasser    schedule 28.07.2015
comment
@wildplasser У меня были утечки памяти, поэтому я прочитал здесь: заголовок stackoverflow.com/questions/14964658/ В нем говорится, что определение лучше всего в памяти, а также было решением моей утечки памяти. Я не знаю, правильно ли это.   -  person Joseph    schedule 28.07.2015
comment
Теперь я вижу: вы его отредактировали. Первоначальная версия с new в качестве имени переменной казалась правильной. Приведение указателя приносит больше вреда, чем пользы.   -  person wildplasser    schedule 28.07.2015


Ответы (1)


Для удаления нужен только указатель на операторы, которые он выполняет. Он не передает никакой информации вызывающей функции. Однако ваша функция вставки выделяет при необходимости и в этом случае должна возвращать выделенный указатель вызывающей стороне.

person donjuedo    schedule 27.07.2015
comment
typedef struct node{ int element; struct node *left; struct node *right; }*tTree; можете ли вы объяснить часть *tTree? Этот синтаксис для меня новый - person scottysseus; 27.07.2015
comment
Я думал, что причина в этом, но не был уверен. Итак, как и удаление, нужно только освободить память, правильно передать только указатель. Спасибо! - person Joseph; 27.07.2015
comment
*tTree встречается нечасто, лучше всего использовать typedef struct { fields of structs }name_structs; name_structs *str; - person santiago92; 27.07.2015
comment
Это то же самое, что сказать: typedef struct node *tTree. Итак, теперь вы можете использовать tTree как псевдоним узла структуры *. узел структуры * переменная = переменная tTree - person Joseph; 27.07.2015