Отпечатване на листови възли в двоично дърво отдясно наляво?

Търся отговор за това:

Намерете псевдо кода за отпечатване на листовите възли в двоично дърво отдясно наляво.

Ще се радвам да чуя някои идеи. Подсказка (не пълно решение, разбира се) или връзка към сродна тема, която може да ми помогне да разбера този проблем, би била полезна.


person ronnie    schedule 10.05.2013    source източник


Отговори (9)


Извършете първо обхождане на дървото в дълбочина, като първо обработвате десните поддървета и отпечатвате само листовите възли.

Най-лесният начин да реализирате това е с рекурсивна функция.

void printLeafNodes(BinaryTreeNode* treePtr) {
  if(treePtr.leftChild == null && treePtr.rightChild == null) {
    //This is a leaf node; print its value
  } else {
    //Recurse on right subtree
    if(treePtr.rightChild != null) {
      printLeafNodes(treePtr.rightChild);
    }
    //Recurse on left subtree
    if(treePtr.leftChild != null) {
      printLeafNodes(treePtr.leftChild);
    }
  }
}

Тази страница е доста полезна за визуализиране на решението: Tree Traversal.

person Sildoreth    schedule 10.05.2013

void in(node* root){
if(root)
    {   
        if(!root->left && !root->right)
              cout<<root->data<<endl;
        in(root->left);
        in(root->right);
    } }

Можете да направите нещо подобно (код на C++).

Идеята зад този код е, направете обхождане по ред/последващо обхождане и проверете дали левите и десните деца са NULL или не. Ако е Null, това означава, че е листов възел.

person SevenDante    schedule 14.08.2017

Ще трябва да използвате рекурсивен метод, като започнете с предаване на метода на възела от най-високо ниво на двоично дърво.

В псевдокода предполагам, че всеки възел е дефиниран с "десни" и "леви" членове, които сами по себе си са възли и свойство "име", за да отпечатате нещо за възела. Методът може да изглежда така, на конкретен език, тъй като казахте псевдокод:

function processNode(parent) {
    if(parent.right = null AND parent.left = null)
        print parent.name
    if(parent.right <> null)
        processNode(parent.right)
    if(parent.left <> null)
        processNode(parent.left)
}

Тогава ще започнете с:

processNode(topNode)
person Tombala    schedule 10.05.2013
comment
Този код ще отпечата нелистови възли и ще отпечата листови възли два пъти. - person Sildoreth; 10.05.2013
comment
Виждам как щеше да се отпечата два пъти. Фиксирана. - person Tombala; 10.05.2013
comment
благодаря ви много момчета! наистина оценявам вашето време и усилия! - person ronnie; 10.05.2013

  1. Извършете обхождане в ред и добавете само листни възли към списъка с посетени възли.
  2. Обърнете списъка.

Or

Всъщност, когато създавате списъка в стъпка едно, продължете да добавяте възел в началото и го оставете да сочи към предишен възел (вместо предишен възел да сочи към нов възел).

person Rohit Sachan    schedule 11.01.2016

Отпечатайте листови възли, докато извършвате обхождане на реда на ниво в обратен ред, като изключите възлите, които не са листа.

person user8066942    schedule 25.05.2017

Направете Inoder/Preorder/postorder Но първо за Right Child След това отидете на ляво Child

void postOrder(Node* root)
{
if(root==NULL)
return;
postOrder(root->right);
postOrder(root->left);
if(root->left==NULL && root->right==NULL)
cout << root->data <<" ";
}
person Rajender Kumar    schedule 21.06.2017

Предполага се, че знаете как да обхождате двоично дърво в ред, като използвате рекурсия.

void visit(Node node) {
     if(node.hasLeft()) {
         visit(node.getLeft());
     }
     handleValue(node.value); // print or whatever
     if(node.hasRight()) {
         visit(node.getRight());
     }
}

Ще забележите, че когато правите това, вие вече обработвате листата в ред отляво надясно, в допълнение към обработката на възли, които не са листа.

За да посетите отдясно наляво, просто обърнете реда на изразите -- така че посетете надясно, след това обработете стойността, след това посетете наляво.

За да отпечатате само листови възли, просто трябва да поставите израз if около handleValue, като му кажете да извежда само ако възелът е лист. Възелът е лист, ако няма нито ляв, нито десен дъщерен възел.

person slim    schedule 15.08.2017

код на python

def Reverse_print(self):
    if self.right:
        self.right.Reverse_print()
    print(self.data),
    if self.left:
        self.left.Reverse_print()

това е рекурсия, върви винаги надясно, докато няма надясно, след това накрая надясно, връща се обратно към корена, отпечатва го, след това отпечатва наляво, така че всъщност вие печатате от най-голямата стойност до най-ниската, след това обратно и така същото нещо, след това обратно и така същото нещо, после обратно и така същото нещо
бла...блаа..блаа

person mo.khashab    schedule 12.06.2018

Знам, че възкресявам стара тема, но мисля, че това може да помогне на другите, които гледат тази тема. Ако говорите за въпрос за интервю, мисля, че рекурсивният отговор е само малка част от отговора и интервюиращият ще иска да чуе и итеративния подход. Обхождането отдясно наляво (отпечатване) не е обичайно преминаване преди/след/в ред, описано в wiki. Основната идея тук е, че трябва да отидете надясно толкова дълго, колкото можете и да започнете да печатате първо от най-десния възел, след това от неговия родител и едва след това от лявото поддърво.

Рекурсивно:

printRightToLeft(Node root){
  if (root == null)
     return;

  // You can check root.right and root.left for null before calling the
  // printRightToLeft function to avoid pushing unneeded data to recursion
  // call stack.

  printRightToLeft(root.right);
  if (root.right == null && root.left == null)
     print(root);
  printRightToLeft(root.left);
}

Итеративно:

printRightToLeft(Node root){
  if (root == null)
    return;

  Stack s = new Stack();
  s.push(root);

  while(!s.isEmpty()){
    Node n = s.top();

    if (n.right != null && !n.visited){
      s.push(n.right);
      n.visited = true;
    } else {
      s.pop();

      if (n.right == null && n.left == null)
         print(n);

      if (n.left != null)
         s.push(n.left);
    }
}
person MikeL    schedule 17.05.2013
comment
Изглежда, че не сте разбрали въпроса. Предполага се, че се отпечатват само листовите възли. - person Sildoreth; 27.04.2017
comment
@Sildoreth, ти си абсолютно прав за неразбирането на печатната част и това може лесно да бъде поправено, но основната ми гледна точка беше, че за въпроси като тези за интервю винаги е добра практика да се споменава не само рекурсивното решение, но и итерируемо един също (и обратното) - person MikeL; 27.04.2017
comment
Рекурсивното решение не се нуждае от Node.visited -- защо версията Stack го прави? - person slim; 15.08.2017
comment
Итеративното решение се нуждае от посетена индикация за възела, така че когато върнете възела от стека, който вече сте посетили и от който сте тръгнали надясно, няма да тръгнете отново надясно, а да поемете по левия път. Рекурсивното решение не се нуждае от него, тъй като във всеки възел то разделя рекурсията на дясното крило и лявото крило, без да се връща обратно към възела, така че индикацията не е необходима. - person MikeL; 16.08.2017
comment
Има и други начини да постигнете това, без да добавяте поле към Node и без алгоритъмът да променя Nodes, докато върви. Единият вариант е да имате стек от Object, да поставите String или Node в стека и да решите какво да правите въз основа на instanceof. Друг е да създадете Task клас и да използвате Stack<Task>. - person slim; 21.08.2017