2010-10-14 6 views
6

Я прочитал еще несколько статей, которые выглядели похожими, но не совсем ответили на мою проблему. Мне задан вопрос о назначении назначить каждому узлу в двоичном дереве соответствующую глубину. Я просто не могу это получить.Назначение глубины каждому узлу

Для справки это мой код:

struct treeNode { 
    int item; 
    int depth; 
    treeNode *left; 
    treeNode *right; 
}; 
typedef treeNode *Tree; 

int assignDepth(Tree &T, int depth) 
{ 
    if(T!=NULL) 
    { 
     depth = assignDepth(T->left, depth++); 
     T->depth = depth; 
     depth = assignDepth(T->right, depth++); 
    } 
    else //leaf 
     return depth--; 
} 

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

Может ли кто-нибудь указать мне в правильном направлении, пожалуйста? Это мой первый раз, когда я использую деревья, а рекурсия - не моя сильная сторона.

Ответ:

void treecoords(Tree &T, int depth) 
{ 
    static int count = -1; //set to -1 so the precrement before assignment doesn't give the wrong values 
    if(T!=NULL) 
    { 
     treecoords(T->left, depth+1); //depth decrements automatically once this function call is removed from the stack 
     count++; 
     T->x = count; 
      T->y = depth; 
     treecoords(T->right, depth+1); 
    } 
} 
+1

Спасибо всем, кто ответил на мой пост. Я понимаю, что теперь я думал об этом неправильно. Я уйду и попытаюсь исправить код, учитывая то, что вы сказали мне, и опубликовать мои окончательные результаты. Я не хочу просто использовать код someones без его полного понимания (хотя я ценю то, что вы отправили его для меня, спасибо). – xyzjace

+0

Это работает! Я сделал рекурсивный алгоритм, который в итоге совпадал с г-ном Купером. Это фактически часть более крупного алгоритма, который присваивает координатам x и y узлам дерева. Теперь алгоритм находится в исходном вопросе. – xyzjace

ответ

3

Вы надеваете»т нужно

else //leaf 
    return depth--; 

Вы также не хотите, чтобы увеличить переменную глубину, просто передать глубину + 1 к следующему Интерактивного.

Также нет необходимости возвращать значение.

Попробуйте это:

void assignDepth(Tree T, int depth) 
{ 
    if(T!=NULL) 
    { 
     assignDepth(T->left, depth+1); 
     T->depth = depth; 
     assignDepth(T->right, depth+1); 
    } 
} 
+0

Я не понимаю, почему нет, но все сказали удалить его, поэтому я и сделал. Рекурсия ломает мой разум. Спасибо :) – xyzjace

+0

Это помогает продумать, что происходит. В первой глубине вызова = 0 (или что-то еще), а T - корень дерева. Предполагая, что T не является NULL, функция вызывает себя в левом поддереве с глубиной + 1, присваивает глубину текущему (корневому) узлу, а затем вызывает себя в правом поддереве, снова с глубиной + 1. Это тот средний шаг, который присваивает значение параметра глубины узлу, поэтому нет необходимости возвращать значение в любом месте. –

+0

Это имеет смысл. Я немного запутался со значением, возвращающимся в рекурсию. Но я думаю, что я понял это сейчас. Очень ценю :) – xyzjace

2

Ну, для начала, вы используете после увеличения/уменьшения, вы, вероятно, имел в виду ++depth/--depth для правильного присвоения и еще вернется;

Кроме того, зачем передавать указатель в качестве ссылочной переменной?

+0

Я попробовал предсказание, как вы это предлагали, и оно добирается туда, но не совсем верно. Почему я должен использовать прецензию вместо публикации? Я думал, что это имеет значение только в порядке операций? Я использую ссылку на указатель, потому что так оно и работает.Нам дали очень краткое введение в указатели, затем упали в океан деревьев. Это была большая догадка и проверка, чтобы увидеть, когда компилятор прекратил бросать мне ошибки. – xyzjace

1
int assignDepth(Tree &T, int depth) 

Вы определили Tree как указатель на treeNode. Вам не нужно передавать его по ссылке. Вы можете изменить узел, на который все указали.

{ 
    if(T!=NULL) 
    { 
     depth = assignDepth(T->left, depth++); 

Постфиксная ++ гарантирует, что вы передаете оригинальный depth вниз. Это не то, что вы хотите. Приращение depth до этого, и забудьте о возврате его как результат функции.

T->depth = depth; 

Все в порядке.

 depth = assignDepth(T->right, depth++); 

Похожие, как и для предыдущего рекурсивного вызова, за исключением того, что здесь вы не должны изменять depth вообще, потому что он уже увеличивается.

} 
    else //leaf 
     return depth--; 

Вам не нужно возвращать информацию о глубине (или это неустановленное требование?).

} 

Приветствия & НТН.,

+0

Я прочитал все комментарии, чтобы убедиться, что ничего не пропущу. Спасибо :) – xyzjace

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

  2. В двух утверждениях:

    depth = assignDepth(T->left, depth++); 
    // and 
    depth = assignDepth(T->right, depth++); 
    

Вы неопределенное поведение от модификации depth дважды без промежуточной точки последовательности (хотя кажется, что там должно быть, есть не точка последовательности между правая и левая стороны задания).

+0

Я только понял, почему возвращаемое значение избыточно, когда я набирал это. Человек, я чувствую себя глупо. Благодаря :)! Не знаете, какие точки последовательности, извините. – xyzjace

+0

@ user475234: Я обсуждал даже упоминание об этом, поскольку исправление кода в противном случае также устранит эту проблему. За небольшим исключением, C в основном говорит, что вы можете только модифицировать определенную переменную один раз в данном операторе, и в этом случае вы делаете это дважды (один раз в инкремент, один раз в задании). –

1
  1. Почему вы возвращаетесь, когда узел NULL. В соответствии с вашей спецификацией вам не нужно возвращать какую-либо глубину.
  2. В другом случае вам просто нужно увеличить глубину и отправить вызов функции. Ниже моя версия кода

    недействительным assignDepth (Tree & T, глубина ИНТ) { если (T == NULL) возврата; прочее { T-> глубина = глубина; если (T-> left! = NULL) assignDepth (T-> left, depth + 1); if (T-> right! = NULL) assignDepth (T-> right, depth + 1); }}

+0

Это начинает иметь немного больше смысла. Теперь я понимаю, что когда рекурсия завершена, ей не нужно возвращать глубину, потому что, когда она выталкивает вызов функции из стека, глубина - это то же самое значение, которое было до того, как вы вызвали функцию. Спасибо д! – xyzjace

1

У меня есть несколько более сложная конструкция с различными типами узлов и сделал это, так я думал, что доля ID.

Если у вас есть дерево, которое варьируется в типе Node to Node (Binary, Unary и т. Д.), Стоит упростить традиционный метод, чтобы избежать неприятных встроенных IFs для проверки типа Nodes.

две функция:

  • 1: Из корня, проходит через каждый узел и проверить его расстояние до корня по recursivly называющего себя и добавления 1 для каждого родителя. Дайте каждому узлу переменную глубины, чтобы сохранить это.
  • 2: Из полного набора узлов в дереве выполните проверку MAX против каждой глубины узлов, наибольшее число будет равно глубине дерева.

Обработка этого способа удаляет явную проверку типов и просто подсчитывает узел независимо от того, имеет ли он один, два или сотни детей.

Надеюсь, это поможет кому-то!

Смежные вопросы