2015-11-20 6 views
0

У меня возникли проблемы с пониманием рекурсивных функций, связанных с обходом предзаказов, по порядку и по порядку. У меня есть некоторые сведения о рекурсии (но, по общему признанию, это не мой сильный костюм). Кажется, что все называют себя дважды, сначала делая звонок с левым ребенком корня, а затем с правильным ребенком. Но как это возможно? Разве вызов функции preOrder с левым дочерним элементом не вернет поток управления в начало, а следующий вызов никогда не будет выполнен?Непонимание понимания рекурсивных функций обхода дерева

void preOrder (Node* root) 
{ 
    if (root == NULL) return; 
    cout<<root->val<<", "; 
    preOrder(root->left); 
    preOrder(root->right); 
} 

ответ

1

Не будет ли вызов функции PREORDER с левым ребенком вернуть поток управления обратно к вершине, и следующий вызов не будет выполнен?

Конечно нет. Рекурсивный вызов работает так же, как и любой другой вызов функции: после завершения функции элемент управления возвращается в место вызова. «Место» означает не только точку в коде, но и точку в стеке вызовов, что означает, что снова доступен тот же набор переменных. Так же, как после возвращения из любой другой функции.

Например, если у вас есть дерево

 A 
    /\ 
     X Y 

и вы называете preorder на A узле, то он первым печатает A содержимое, а затем вызывает preorder на X и по возвращении он вернулся в preorder(A), так он продолжает звонить по телефону preorder по телефону Y.

0

Preorder: Обработать узел, переходят к левому ребенку, перейти к правому ребенку

void preorder(Node *root) 
{ 
    if (root == NULL) //<- Check if the currently passed node is empty 
     return; //<- if it is, return from the function back down the stack 

    cout << root->val << ", "; //<- if it wasn't empty, print its value 

    if (root->left != NULL) //<- check if the node to the left is empty 
     preorder(root->left); //<- if not recurse to the left child 

    if (root->right != NULL) //<- check if the node to the right is empty 
     preorder(root->right); //<- if not recurse to the right child 
} 

Симметричного: шаг влево, обрабатывает узел, перемещаются вправо

void inorder(Node *root) 
{ 
    if (root == NULL) 
     return; 

    if (root->left != NULL) //<- check if the node to the left is empty 
      inorder(root->left); //<- if not recurse to the left child 

    cout << root->val << ", "; 

    if (root->right != NULL) //<- check if the node to the right is empty 
      inorder(root->right); //<- if not recurse to the right child 
} 

Postorder: Переход к левому узлу, перейти к правый узел, процесс узел

void postorder(Node *root) 
{ 
    if (root == NULL) 
     return; 

    if (root->left != NULL) //<- check if the node to the left is empty 
      postorder(root->left); //<- if not recurse to the left child 

    if (root->right != NULL) //<- check if the node to the right is empty 
      postorder(root->right); //<- if not recurse to the right child 

    cout << root->val << ", " 
} 
+0

1. Не вызывайте произвольный узел «root». 2. Если вы проверите * внутри * функцию для аргумента, являющегося 'NULL', вам не нужно проверять ее * перед * рекурсивным вызовом на указатели' left' и 'right'. Конечно, это избавляет вас от недействительных вызовов от несуществующих детей листьев, но OTOH добавляет накладные расходы на тестирование на всех внутренних узлах. – CiaPan

+0

@CiaPan нулевое тестирование узла для простого возврата, если для возможности корня источника может быть пустым. –

+0

Я знаю, для чего. Я просто указал, что тестирование 'if (node-> left)' before 'postorder (node-> left)' излишне, потому что функция снова проверит его после вызова. – CiaPan

0
void preorder(node *p) { 
    if(p) { 
    cout << p->val <<"\n"; 
    preorder(p->left); 
    preorder(p->right); 
    } 
} 
+0

Прохладный, thx. Вы заметили, что это 2 года? – ohbrobig

+0

Добро пожаловать в переполнение стека! Этот вопрос ищет * объяснение *, а не просто для рабочего кода. Ваш ответ не дает понимания исследователю и может быть удален. Пожалуйста, отредактируйте, чтобы объяснить, что вызывает наблюдаемые симптомы. –

+0

Добро пожаловать в переполнение стека! Хотя этот фрагмент кода может быть решением, [включая объяснение] (// meta.stackexchange.com/questions/114762/explaining-entirely-code-based-answers) действительно помогает улучшить качество вашего сообщения. Помните, что вы отвечаете на вопрос читателей в будущем, и эти люди могут не знать причин вашего предложения кода. – milo526

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

  • Нет связанных вопросов^_^