Почему эта практика настолько распространена? Использовать двойной указатель, чтобы сделать то же самое, не хорошо?
Это в основном вопрос стиля и предпочтений.
Использование двойного указателя позволяет функции изменять сам корневой указатель, что я считаю выгодным, но это означает, что ваш код должен иметь дело с несколькими уровнями косвенного обращения одновременно, что некоторые люди считают запутанным или неприятным.
Возврат нового корня позволяет поддерживать один уровень косвенности, но это накладывает дополнительную нагрузку на всех пользователей функций, которые изменяют дерево: они должны обновить корневой указатель на значение, возвращаемое функцией. Это также означает, что если функция также хочет возвращать что-то еще, то вам нужен выходной параметр, или структура для возвращаемого типа, или подобного, которая теряет большую часть полученной простоты.
Лично я не предпочитаю ничего из вышеперечисленного. Вместо того чтобы работать с пустым корневым указателем, я предпочитаю помещать корневой указатель в структуру контейнера, возможно, с другими общими данными о дереве, и передавать указатели на методы. Хотя технически это все еще два уровня косвенности, он выглядит и ощущается скорее как один, и он позволяет задействованным функциям самостоятельно обновлять корневой указатель. Пример,
struct node {
int data;
struct node *left,
struct node *right;
};
struct tree {
struct node *root;
// ... maybe other members ...
};
void insert(struct tree *tree, int data) {
// ... perform insertion, ultimately finishing with
tree->root = new_root;
}
Конечно, это делает реализацию рекурсивных функций немного (не очень) сложным, но рекурсия часто является плохим выбором для реальных программ.