recorrido programar partir nodo eliminar ejemplos construir construccion codigo busqueda binarios binario arboles arbol binary-tree traversal non-recursive

binary tree - programar - Recorrido de orden de post de árbol binario sin recursión.



eliminar nodo arbol binario c++ (24)

La lógica del recorrido del orden de los postes sin utilizar recursión.

En el Postorder traversal al pedido, el orden de procesamiento es de left-right-current . Por lo tanto, primero debemos visitar la sección izquierda antes de visitar otras partes. Intentaremos atravesar el árbol lo más a la izquierda posible para cada nodo del árbol. Para cada nodo actual, si el hijo derecho está presente, empújelo en la pila antes de empujar el nodo actual mientras que la raíz no sea NULL / None. Ahora saque un nodo de la pila y verifique si existe o no el hijo derecho de ese nodo. Si existe, verifique si es el mismo que el elemento superior o no. Si son iguales, entonces indica que aún no hemos terminado con la parte derecha, por lo tanto, antes de procesar el nodo actual, debemos procesar la parte correcta y, para ello, abrir el elemento superior (elemento secundario derecho) y empujar el nodo actual hacia la pila. . En cada momento nuestra cabeza es el elemento reventado. Si el elemento actual no es lo mismo que la parte superior y la cabeza no es NULA, hemos terminado con la sección derecha e izquierda, por lo que ahora podemos procesar el nodo actual. Tenemos que repetir los pasos anteriores hasta que la pila esté vacía.

def Postorder_iterative(head): if head is None: return None sta=stack() while True: while head is not None: if head.r: sta.push(head.r) sta.push(head) head=head.l if sta.top is -1: break head = sta.pop() if head.r is not None and sta.top is not -1 and head.r is sta.A[sta.top]: x=sta.pop() sta.push(head) head=x else: print(head.val,end = '' '') head=None print()

¿Cuál es el algoritmo para hacer un recorrido de orden posterior de un árbol binario SIN usar la recursión?


// la versión java con bandera

public static <T> void printWithFlag(TreeNode<T> root){ if(null == root) return; Stack<TreeNode<T>> stack = new Stack<TreeNode<T>>(); stack.add(root); while(stack.size() > 0){ if(stack.peek().isVisit()){ System.out.print(stack.pop().getValue() + " "); }else{ TreeNode<T> tempNode = stack.peek(); if(tempNode.getRight()!=null){ stack.add(tempNode.getRight()); } if(tempNode.getLeft() != null){ stack.add(tempNode.getLeft()); } tempNode.setVisit(true); } } }


1.1 Crear una pila vacía

2.1 Hacer lo siguiente, mientras que la raíz no es NULL

a) Push root''s right child and then root to stack. b) Set root as root''s left child.

2.2 Pop un elemento de la pila y lo establece como raíz.

a) If the popped item has a right child and the right child is at top of stack, then remove the right child from stack, push the root back and set root as root''s right child. b) Else print root''s data and set root as NULL.

2.3 Repita los pasos 2.1 y 2.2 mientras la pila no está vacía.


Aquí está la implementación de Java con dos pilas

public static <T> List<T> iPostOrder(BinaryTreeNode<T> root) { if (root == null) { return Collections.emptyList(); } List<T> result = new ArrayList<T>(); Deque<BinaryTreeNode<T>> firstLevel = new LinkedList<BinaryTreeNode<T>>(); Deque<BinaryTreeNode<T>> secondLevel = new LinkedList<BinaryTreeNode<T>>(); firstLevel.push(root); while (!firstLevel.isEmpty()) { BinaryTreeNode<T> node = firstLevel.pop(); secondLevel.push(node); if (node.hasLeftChild()) { firstLevel.push(node.getLeft()); } if (node.hasRightChild()) { firstLevel.push(node.getRight()); } } while (!secondLevel.isEmpty()) { result.add(secondLevel.pop().getData()); } return result; }

Aquí están las pruebas unitarias.

@Test public void iterativePostOrderTest() { BinaryTreeNode<Integer> bst = BinaryTreeUtil.<Integer>fromInAndPostOrder(new Integer[]{4,2,5,1,6,3,7}, new Integer[]{4,5,2,6,7,3,1}); assertThat(BinaryTreeUtil.iPostOrder(bst).toArray(new Integer[0]), equalTo(new Integer[]{4,5,2,6,7,3,1})); }


Aquí está la versión con una pila y sin una bandera visitada:

private void postorder(Node head) { if (head == null) { return; } LinkedList<Node> stack = new LinkedList<Node>(); stack.push(head); while (!stack.isEmpty()) { Node next = stack.peek(); boolean finishedSubtrees = (next.right == head || next.left == head); boolean isLeaf = (next.left == null && next.right == null); if (finishedSubtrees || isLeaf) { stack.pop(); System.out.println(next.value); head = next; } else { if (next.right != null) { stack.push(next.right); } if (next.left != null) { stack.push(next.left); } } } }


Aquí está también una versión de Python:

class Node: def __init__(self,data): self.data = data self.left = None self.right = None def postOrderIterative(root): if root is None : return s1 = [] s2 = [] s1.append(root) while(len(s1)>0): node = s1.pop() s2.append(node) if(node.left!=None): s1.append(node.left) if(node.right!=None): s1.append(node.right) while(len(s2)>0): node = s2.pop() print(node.data) root = Node(1) root.left = Node(2) root.right = Node(3) root.left.left = Node(4) root.left.right = Node(5) root.right.left = Node(6) root.right.right = Node(7) postOrderIterative(root)

Aquí está la salida:


Aquí estoy pegando diferentes versiones en c # (.net) para referencia: (para el recorrido iterativo en orden puede referirse a: Ayúdeme a entender Inorder Traversal sin usar la recursión )

  1. wiki ( http://en.wikipedia.org/wiki/Post-order%5Ftraversal#Implementations ) (elegante)
  2. Otra versión de pila única (n. ° 1 y n. ° 2: básicamente utiliza el hecho de que en el recorrido posterior al pedido se visita el nodo secundario derecho antes de visitar el nodo real; por lo tanto, simplemente confiamos en la verificación de que si el hijo derecho de la parte superior de la pila es de hecho el El último nodo de recorrido de la orden de la publicación ha sido visitado.
  3. Uso de la versión de Dos pilas (ref: http://www.geeksforgeeks.org/iterative-postorder-traversal/ ) (más fácil: básicamente, el revés transversal de la orden posterior no es más que el transversal previo a la orden con un simple retoque que primero se visita el nodo derecho, y luego nodo izquierdo)
  4. Usando la bandera de visitante (fácil)
  5. Pruebas unitarias

~

public string PostOrderIterative_WikiVersion() { List<int> nodes = new List<int>(); if (null != this._root) { BinaryTreeNode lastPostOrderTraversalNode = null; BinaryTreeNode iterativeNode = this._root; Stack<BinaryTreeNode> stack = new Stack<BinaryTreeNode>(); while ((stack.Count > 0)//stack is not empty || (iterativeNode != null)) { if (iterativeNode != null) { stack.Push(iterativeNode); iterativeNode = iterativeNode.Left; } else { var stackTop = stack.Peek(); if((stackTop.Right != null) && (stackTop.Right != lastPostOrderTraversalNode)) { //i.e. last traversal node is not right element, so right sub tree is not //yet, traversed. so we need to start iterating over right tree //(note left tree is by default traversed by above case) iterativeNode = stackTop.Right; } else { //if either the iterative node is child node (right and left are null) //or, stackTop''s right element is nothing but the last traversal node //(i.e; the element can be popped as the right sub tree have been traversed) var top = stack.Pop(); Debug.Assert(top == stackTop); nodes.Add(top.Element); lastPostOrderTraversalNode = top; } } } } return this.ListToString(nodes); }

Aquí está el recorrido de la orden posterior con una pila (mi versión)

public string PostOrderIterative() { List<int> nodes = new List<int>(); if (null != this._root) { BinaryTreeNode lastPostOrderTraversalNode = null; BinaryTreeNode iterativeNode = null; Stack<BinaryTreeNode> stack = new Stack<BinaryTreeNode>(); stack.Push(this._root); while(stack.Count > 0) { iterativeNode = stack.Pop(); if ((iterativeNode.Left == null) && (iterativeNode.Right == null)) { nodes.Add(iterativeNode.Element); lastPostOrderTraversalNode = iterativeNode; //make sure the stack is not empty as we need to peek at the top //for ex, a tree with just root node doesn''t have to enter loop //and also node Peek() will throw invalidoperationexception //if it is performed if the stack is empty //so, it handles both of them. while(stack.Count > 0) { var stackTop = stack.Peek(); bool removeTop = false; if ((stackTop.Right != null) && //i.e. last post order traversal node is nothing but right node of //stacktop. so, all the elements in the right subtree have been visted //So, we can pop the top element (stackTop.Right == lastPostOrderTraversalNode)) { //in other words, we can pop the top if whole right subtree is //traversed. i.e. last traversal node should be the right node //as the right node will be traverse once all the subtrees of //right node has been traversed removeTop = true; } else if( //right subtree is null (stackTop.Right == null) && (stackTop.Left != null) //last traversal node is nothing but the root of left sub tree node && (stackTop.Left == lastPostOrderTraversalNode)) { //in other words, we can pop the top of stack if right subtree is null, //and whole left subtree has been traversed removeTop = true; } else { break; } if(removeTop) { var top = stack.Pop(); Debug.Assert(stackTop == top); lastPostOrderTraversalNode = top; nodes.Add(top.Element); } } } else { stack.Push(iterativeNode); if(iterativeNode.Right != null) { stack.Push(iterativeNode.Right); } if(iterativeNode.Left != null) { stack.Push(iterativeNode.Left); } } } } return this.ListToString(nodes); }

Utilizando dos pilas

public string PostOrderIterative_TwoStacksVersion() { List<int> nodes = new List<int>(); if (null != this._root) { Stack<BinaryTreeNode> postOrderStack = new Stack<BinaryTreeNode>(); Stack<BinaryTreeNode> rightLeftPreOrderStack = new Stack<BinaryTreeNode>(); rightLeftPreOrderStack.Push(this._root); while(rightLeftPreOrderStack.Count > 0) { var top = rightLeftPreOrderStack.Pop(); postOrderStack.Push(top); if(top.Left != null) { rightLeftPreOrderStack.Push(top.Left); } if(top.Right != null) { rightLeftPreOrderStack.Push(top.Right); } } while(postOrderStack.Count > 0) { var top = postOrderStack.Pop(); nodes.Add(top.Element); } } return this.ListToString(nodes); }

Con la bandera visitada en C # (.net):

public string PostOrderIterative() { List<int> nodes = new List<int>(); if (null != this._root) { BinaryTreeNode iterativeNode = null; Stack<BinaryTreeNode> stack = new Stack<BinaryTreeNode>(); stack.Push(this._root); while(stack.Count > 0) { iterativeNode = stack.Pop(); if(iterativeNode.visted) { //reset the flag, for further traversals iterativeNode.visted = false; nodes.Add(iterativeNode.Element); } else { iterativeNode.visted = true; stack.Push(iterativeNode); if(iterativeNode.Right != null) { stack.Push(iterativeNode.Right); } if(iterativeNode.Left != null) { stack.Push(iterativeNode.Left); } } } } return this.ListToString(nodes); }

Las definiciones:

class BinaryTreeNode { public int Element; public BinaryTreeNode Left; public BinaryTreeNode Right; public bool visted; } string ListToString(List<int> list) { string s = string.Join(", ", list); return s; }

Pruebas unitarias

[TestMethod] public void PostOrderTests() { int[] a = { 13, 2, 18, 1, 5, 17, 20, 3, 6, 16, 21, 4, 14, 15, 25, 22, 24 }; BinarySearchTree bst = new BinarySearchTree(); foreach (int e in a) { string s1 = bst.PostOrderRecursive(); string s2 = bst.PostOrderIterativeWithVistedFlag(); string s3 = bst.PostOrderIterative(); string s4 = bst.PostOrderIterative_WikiVersion(); string s5 = bst.PostOrderIterative_TwoStacksVersion(); Assert.AreEqual(s1, s2); Assert.AreEqual(s2, s3); Assert.AreEqual(s3, s4); Assert.AreEqual(s4, s5); bst.Add(e); bst.Delete(e); bst.Add(e); s1 = bst.PostOrderRecursive(); s2 = bst.PostOrderIterativeWithVistedFlag(); s3 = bst.PostOrderIterative(); s4 = bst.PostOrderIterative_WikiVersion(); s5 = bst.PostOrderIterative_TwoStacksVersion(); Assert.AreEqual(s1, s2); Assert.AreEqual(s2, s3); Assert.AreEqual(s3, s4); Assert.AreEqual(s4, s5); } Debug.WriteLine(string.Format("PostOrderIterative: {0}", bst.PostOrderIterative())); Debug.WriteLine(string.Format("PostOrderIterative_WikiVersion: {0}", bst.PostOrderIterative_WikiVersion())); Debug.WriteLine(string.Format("PostOrderIterative_TwoStacksVersion: {0}", bst.PostOrderIterative_TwoStacksVersion())); Debug.WriteLine(string.Format("PostOrderIterativeWithVistedFlag: {0}", bst.PostOrderIterativeWithVistedFlag())); Debug.WriteLine(string.Format("PostOrderRecursive: {0}", bst.PostOrderRecursive())); }


Aquí hay un enlace que proporciona otras dos soluciones sin usar ninguna bandera visitada.

http://www.leetcode.com/2010/10/binary-tree-post-order-traversal.html

Obviamente, esta es una solución basada en pila debido a la falta de puntero principal en el árbol. (No necesitaríamos una pila si hay un puntero padre).

Primero empujaríamos el nodo raíz a la pila. Mientras que la pila no está vacía, seguimos empujando el elemento secundario izquierdo del nodo desde la parte superior de la pila. Si el hijo izquierdo no existe, empujamos a su hijo derecho. Si es un nodo hoja, procesamos el nodo y lo sacamos de la pila.

También utilizamos una variable para realizar un seguimiento de un nodo atravesado previamente. El propósito es determinar si el recorrido es descendente / ascendente del árbol, y también podemos saber si asciende de izquierda a derecha.

Si ascendemos el árbol desde la izquierda, no querríamos empujar a su hijo izquierdo nuevamente a la pila y deberíamos continuar ascendiendo por el árbol si su hijo derecho existe. Si ascendemos el árbol desde la derecha, deberíamos procesarlo y sacarlo de la pila.

Procesamos el nodo y lo sacamos de la pila en estos 3 casos:

  1. El nodo es un nodo de hoja (sin hijos)
  2. Simplemente cruzamos el árbol desde la izquierda y no existe ningún niño de la derecha.
  3. Simplemente cruzamos el árbol desde la derecha.

Aquí hay una muestra de wikipedia :

nonRecursivePostorder(rootNode) nodeStack.push(rootNode) while (! nodeStack.empty()) currNode = nodeStack.peek() if ((currNode.left != null) and (currNode.left.visited == false)) nodeStack.push(currNode.left) else if ((currNode.right != null) and (currNode.right.visited == false)) nodeStack.push(currNode.right) else print currNode.value currNode.visited := true nodeStack.pop()


Aquí hay una solución en C ++ que no requiere ningún almacenamiento para la contabilidad en el árbol.
En su lugar, utiliza dos pilas. Uno para ayudarnos a atravesar y otro para almacenar los nodos para que podamos hacer un recorrido transversal de ellos.

std::stack<Node*> leftStack; std::stack<Node*> rightStack; Node* currentNode = m_root; while( !leftStack.empty() || currentNode != NULL ) { if( currentNode ) { leftStack.push( currentNode ); currentNode = currentNode->m_left; } else { currentNode = leftStack.top(); leftStack.pop(); rightStack.push( currentNode ); currentNode = currentNode->m_right; } } while( !rightStack.empty() ) { currentNode = rightStack.top(); rightStack.pop(); std::cout << currentNode->m_value; std::cout << "/n"; }


Así que puedes usar una pila para hacer un recorrido de orden posterior.

private void PostOrderTraversal(Node pos) { Stack<Node> stack = new Stack<Node>(); do { if (pos==null && (pos=stack.peek().right)==null) { for (visit(stack.peek()); stack.pop()==(stack.isEmpty()?null:stack.peek().right); visit(stack.peek())) {} } else if(pos!=null) { stack.push(pos); pos=pos.left; } } while (!stack.isEmpty()); }


Dos métodos para realizar un recorrido de orden posterior sin recursión:

1. Uso de un HashSet de nodos visitados y una pila para realizar un seguimiento:

private void postOrderWithoutRecursion(TreeNode root) { if (root == null || root.left == null && root.right == null) { return; } Stack<TreeNode> stack = new Stack<>(); Set<TreeNode> visited = new HashSet<>(); while (!stack.empty() || root != null) { if (root != null) { stack.push(root); visited.add(root); root = root.left; } else { root = stack.peek(); if (root.right == null || visited.contains(root.right)) { System.out.print(root.val+" "); stack.pop(); root = null; } else { root = root.right; } } } }


Complejidad del tiempo: O (n)
Complejidad del espacio: O (2n)

2. Usando el método de alteración de árboles:

private void postOrderWithoutRecursionAlteringTree(TreeNode root) { if (root == null || root.left == null && root.right == null) { return; } Stack<TreeNode> stack = new Stack<>(); while (!stack.empty() || root != null) { if (root != null) { stack.push(root); root = root.left; } else { root = stack.peek(); if (root.right == null) { System.out.print(root.val+" "); stack.pop(); root = null; } else { TreeNode temp = root.right; root.right = null; root = temp; } } } }


Complejidad del tiempo: O (n)
Complejidad del espacio: O (n)

Clase TreeNode:

public class TreeNode { public int val; public TreeNode left; public TreeNode right; public TreeNode(int x) { val = x; } }


Es muy agradable ver tantos enfoques enérgicos para este problema. Muy inspirador por cierto!

Encontré este tema buscando una solución iterativa simple para eliminar todos los nodos en mi implementación de árbol binario. Probé algunos de ellos, e intenté algo similar encontrado en otras partes de la Red, pero ninguno de ellos fue realmente de mi agrado.

La cuestión es que estoy desarrollando un módulo de indexación de base de datos para un propósito muy específico (indexación de Bitcoin Blockchain), y mis datos se almacenan en el disco, no en la RAM. Cambio las páginas según sea necesario, haciendo mi propia gestión de memoria. Es más lento, pero lo suficientemente rápido para el propósito, y al tener almacenamiento en el disco en lugar de RAM, no tengo ninguna orientación religiosa contra el desperdicio de espacio (los discos duros son baratos).

Por esa razón, mis nodos en mi árbol binario tienen punteros principales. Ese es (todo) el espacio extra del que estoy hablando. Necesito a los padres porque necesito recorrer tanto el ascenso como el descenso a través del árbol para diversos propósitos.

Teniendo eso en mente, rápidamente escribí un pequeño fragmento de pseudocódigo sobre cómo podría hacerse, es decir, un nudo transversal de post-orden que elimina nodos sobre la marcha. Está implementado y probado, y se convirtió en parte de mi solución. Y es bastante rápido también.

El problema es que se pone realmente REALMENTE simple cuando los nodos tienen punteros principales y, además, ya que puedo anular el vínculo de los padres al nodo "recién salido".

Aquí está el pseudocódigo para la eliminación iterativa posterior a la orden:

Node current = root; while (current) { if (current.left) current = current.left; // Dive down left else if (current.right) current = current.right; // Dive down right else { // Node "current" is a leaf, i.e. no left or right child Node parent = current.parent; // assuming root.parent == null if (parent) { // Null out the parent''s link to the just departing node if (parent.left == current) parent.left = null; else parent.right = null; } delete current; current = parent; } } root = null;

Si está interesado en un enfoque más teórico para codificar colecciones complejas (como mi árbol binario, que en realidad es un árbol rojo-negro de auto-equilibrio), revise estos enlaces:

http://opendatastructures.org/versions/edition-0.1e/ods-java/6_2_BinarySearchTree_Unbala.html http://opendatastructures.org/versions/edition-0.1e/ods-java/9_2_RedBlackTree_Simulated_.html https://www.cs.auckland.ac.nz/software/AlgAnim/red_black.html

Feliz codificación :-)

Søren Fog http://iprotus.eu/


Estaba buscando un fragmento de código que funcione bien y que sea fácil de personalizar. Los árboles roscados no son "simples". La solución de doble pila requiere memoria O (n). La solución LeetCode y la solución de tcb tienen controles adicionales y ...

Aquí hay un algoritmo clásico traducido a C que funcionó para mí:

void postorder_traversal(TreeNode *p, void (*visit)(TreeNode *)) { TreeNode *stack[40]; // simple C stack, no overflow check TreeNode **sp = stack; TreeNode *last_visited = NULL; for (; p != NULL; p = p->left) *sp++ = p; while (sp != stack) { p = sp[-1]; if (p->right == NULL || p->right == last_visited) { visit(p); last_visited = p; sp--; } else { for (p = p->right; p != NULL; p = p->left) *sp++ = p; } } }

En mi humilde opinión, este algoritmo es más fácil de seguir que un pseudocódigo de wikipedia.org / Tree_traversal con buen rendimiento y legible. Para detalles gloriosos, vea las respuestas a los ejercicios de árbol binario en el Volumen 1 de Knuth.


Este es el enfoque que utilizo para el recorrido iterativo, posterior al pedido. Me gusta este enfoque porque:

  1. Solo maneja una única transición por ciclo de bucle, por lo que es fácil de seguir.
  2. Una solución similar funciona para los recorridos en orden y pre-orden.

Código:

enum State {LEFT, RIGHT, UP, CURR} public void iterativePostOrder(Node root) { Deque<Node> parents = new ArrayDeque<>(); Node curr = root; State state = State.LEFT; while(!(curr == root && state == State.UP)) { switch(state) { case LEFT: if(curr.left != null) { parents.push(curr); curr = curr.left; } else { state = RIGHT; } break; case RIGHT: if(curr.right != null) { parents.push(curr); curr = curr.right; state = LEFT; } else { state = CURR; } break; case CURR: System.out.println(curr); state = UP; break; case UP: Node child = curr; curr = parents.pop(); state = child == curr.left ? RIGHT : CURR; break; default: throw new IllegalStateException(); } } }

Explicación:

Puedes pensar en los pasos como este:

  1. Prueba a la izquierda
    • si existe el nodo izquierdo: intente IZQUIERDA otra vez
    • si el nodo izquierdo no existe: pruebe a la DERECHA
  2. Prueba a la derecha
    • Si existe un nodo derecho: intente IZQUIERDA desde allí
    • Si no existe ningún derecho, estás en una hoja: Probar CURR
  3. Prueba CURR
    • Imprimir nodo actual
    • Todos los nodos a continuación han sido ejecutados (orden posterior): Prueba UP
  4. Pruebalo
    • Si el nodo es root, no hay UP, entonces EXIT
    • Si viene por la izquierda, intente a la derecha
    • Si viene por la derecha, pruebe el CURR

No he agregado la clase de nodo como no es particularmente relevante ni ningún caso de prueba, lo que los deja como ejercicio para el lector, etc.

void postOrderTraversal(node* root) { if(root == NULL) return; stack<node*> st; st.push(root); //store most recent ''visited'' node node* prev=root; while(st.size() > 0) { node* top = st.top(); if((top->left == NULL && top->right == NULL)) { prev = top; cerr<<top->val<<" "; st.pop(); continue; } else { //we can check if we are going back up the tree if the current //node has a left or right child that was previously outputted if((top->left == prev) || (top->right== prev)) { prev = top; cerr<<top->val<<" "; st.pop(); continue; } if(top->right != NULL) st.push(top->right); if(top->left != NULL) st.push(top->left); } } cerr<<endl; }

tiempo de ejecución O (n): todos los nodos deben visitarse Y espacio O (n): para la pila, el peor de los casos es una lista de una sola línea vinculada


Por favor vea esta implementación completa de Java. Simplemente copia el código y pégalo en tu compilador. Funcionará bien.

import java.util.LinkedList; import java.util.Queue; import java.util.Stack; class Node { Node left; String data; Node right; Node(Node left, String data, Node right) { this.left = left; this.right = right; this.data = data; } public String getData() { return data; } } class Tree { Node node; //insert public void insert(String data) { if(node == null) node = new Node(null,data,null); else { Queue<Node> q = new LinkedList<Node>(); q.add(node); while(q.peek() != null) { Node temp = q.remove(); if(temp.left == null) { temp.left = new Node(null,data,null); break; } else { q.add(temp.left); } if(temp.right == null) { temp.right = new Node(null,data,null); break; } else { q.add(temp.right); } } } } public void postorder(Node node) { if(node == null) return; postorder(node.left); postorder(node.right); System.out.print(node.getData()+" --> "); } public void iterative(Node node) { Stack<Node> s = new Stack<Node>(); while(true) { while(node != null) { s.push(node); node = node.left; } if(s.peek().right == null) { node = s.pop(); System.out.print(node.getData()+" --> "); if(node == s.peek().right) { System.out.print(s.peek().getData()+" --> "); s.pop(); } } if(s.isEmpty()) break; if(s.peek() != null) { node = s.peek().right; } else { node = null; } } } } class Main { public static void main(String[] args) { Tree t = new Tree(); t.insert("A"); t.insert("B"); t.insert("C"); t.insert("D"); t.insert("E"); t.postorder(t.node); System.out.println(); t.iterative(t.node); System.out.println(); } }


Profundidad primero, orden posterior, no recursiva, sin pila

Cuando tienes padre:

node_t { left, right parent } traverse(node_t rootNode) { bool backthreading = false node_t node = rootNode while(node <> 0) if (node->left <> 0) and backthreading = false then node = node->left continue endif >>> process node here <<< if node->right <> 0 then lNode = node->right backthreading = false else node = node->parent backthreading = true endif endwhile


Python con 1 pila y sin bandera:

def postorderTraversal(self, root): ret = [] if not root: return ret stack = [root] current = None while stack: previous = current current = stack.pop() if previous and ((previous is current) or (previous is current.left) or (previous is current.right)): ret.append(current.val) else: stack.append(current) if current.right: stack.append(current.right) if current.left: stack.append(current.left) return ret

Y lo que es mejor es con declaraciones similares, para que el recorrido también funcione.

def inorderTraversal(self, root): ret = [] if not root: return ret stack = [root] current = None while stack: previous = current current = stack.pop() if None == previous or previous.left is current or previous.right is current: if current.right: stack.append(current.right) stack.append(current) if current.left: stack.append(current.left) else: ret.append(current.val) return ret


import java.util.Stack; class Practice { public static void main(String arr[]) { Practice prc = new Practice(); TreeNode node1 = (prc).new TreeNode(1); TreeNode node2 = (prc).new TreeNode(2); TreeNode node3 = (prc).new TreeNode(3); TreeNode node4 = (prc).new TreeNode(4); TreeNode node5 = (prc).new TreeNode(5); TreeNode node6 = (prc).new TreeNode(6); TreeNode node7 = (prc).new TreeNode(7); node1.left = node2; node1.right = node3; node2.left = node4; node2.right = node5; node3.left = node6; node3.right = node7; postOrderIteratively(node1); } public static void postOrderIteratively(TreeNode root) { Stack<Entry> stack = new Stack<Entry>(); Practice prc = new Practice(); stack.push((prc).new Entry(root, false)); while (!stack.isEmpty()) { Entry entry = stack.pop(); TreeNode node = entry.node; if (entry.flag == false) { if (node.right == null && node.left == null) { System.out.println(node.data); } else { stack.push((prc).new Entry(node, true)); if (node.right != null) { stack.push((prc).new Entry(node.right, false)); } if (node.left != null) { stack.push((prc).new Entry(node.left, false)); } } } else { System.out.println(node.data); } } } class TreeNode { int data; int leafCount; TreeNode left; TreeNode right; public TreeNode(int data) { this.data = data; } public int getLeafCount() { return leafCount; } public void setLeafCount(int leafCount) { this.leafCount = leafCount; } public TreeNode getLeft() { return left; } public void setLeft(TreeNode left) { this.left = left; } public TreeNode getRight() { return right; } public void setRight(TreeNode right) { this.right = right; } @Override public String toString() { return "" + this.data; } } class Entry { Entry(TreeNode node, boolean flag) { this.node = node; this.flag = flag; } TreeNode node; boolean flag; @Override public String toString() { return node.toString(); } } }


/** * This code will ensure holding of chain(links) of nodes from the root to till the level of the tree. * The number of extra nodes in the memory (other than tree) is height of the tree. * I haven''t used java stack instead used this ParentChain. * This parent chain is the link for any node from the top(root node) to till its immediate parent. * This code will not require any altering of existing BinaryTree (NO flag/parent on all the nodes). * * while visiting the Node 11; ParentChain will be holding the nodes 9 -> 8 -> 7 -> 1 where (-> is parent) * * 1 / / / / / / / / / / / / / / / / 2 7 / / / / / / / / / / / / 3 6 8 / / / / / / 4 5 9 / / 10 11 * * @author ksugumar * */ public class InOrderTraversalIterative { public static void main(String[] args) { BTNode<String> rt; String[] dataArray = {"1","2","3","4",null,null,"5",null,null,"6",null,null,"7","8","9","10",null,null,"11",null,null,null,null}; rt = BTNode.buildBTWithPreOrder(dataArray, new Counter(0)); BTDisplay.printTreeNode(rt); inOrderTravesal(rt); } public static void postOrderTravesal(BTNode<String> root) { ParentChain rootChain = new ParentChain(root); rootChain.Parent = new ParentChain(null); while (root != null) { //Going back to parent if(rootChain.leftVisited && rootChain.rightVisited) { System.out.println(root.data); //Visit the node. ParentChain parentChain = rootChain.Parent; rootChain.Parent = null; //Avoid the leak rootChain = parentChain; root = rootChain.root; continue; } //Traverse Left if(!rootChain.leftVisited) { rootChain.leftVisited = true; if (root.left != null) { ParentChain local = new ParentChain(root.left); //It is better to use pool to reuse the instances. local.Parent = rootChain; rootChain = local; root = root.left; continue; } } //Traverse RIGHT if(!rootChain.rightVisited) { rootChain.rightVisited = true; if (root.right != null) { ParentChain local = new ParentChain(root.right); //It is better to use pool to reuse the instances. local.Parent = rootChain; rootChain = local; root = root.right; continue; } } } } class ParentChain { BTNode<String> root; ParentChain Parent; boolean leftVisited = false; boolean rightVisited = false; public ParentChain(BTNode<String> node) { this.root = node; } @Override public String toString() { return root.toString(); } }


import java.util.Stack; public class IterativePostOrderTraversal extends BinaryTree { public static void iterativePostOrderTraversal(Node root){ Node cur = root; Node pre = root; Stack<Node> s = new Stack<Node>(); if(root!=null) s.push(root); System.out.println("sysout"+s.isEmpty()); while(!s.isEmpty()){ cur = s.peek(); if(cur==pre||cur==pre.left ||cur==pre.right){// we are traversing down the tree if(cur.left!=null){ s.push(cur.left); } else if(cur.right!=null){ s.push(cur.right); } if(cur.left==null && cur.right==null){ System.out.println(s.pop().data); } }else if(pre==cur.left){// we are traversing up the tree from the left if(cur.right!=null){ s.push(cur.right); }else if(cur.right==null){ System.out.println(s.pop().data); } }else if(pre==cur.right){// we are traversing up the tree from the right System.out.println(s.pop().data); } pre=cur; } } public static void main(String args[]){ BinaryTree bt = new BinaryTree(); Node root = bt.generateTree(); iterativePostOrderTraversal(root); } }


void display_without_recursion(struct btree **b) { deque< struct btree* > dtree; if(*b) dtree.push_back(*b); while(!dtree.empty() ) { struct btree* t = dtree.front(); cout << t->nodedata << " " ; dtree.pop_front(); if(t->right) dtree.push_front(t->right); if(t->left) dtree.push_front(t->left); } cout << endl; }


void postorder_stack(Node * root){ stack ms; ms.top = -1; if(root == NULL) return ; Node * temp ; push(&ms,root); Node * prev = NULL; while(!is_empty(ms)){ temp = peek(ms); /* case 1. We are nmoving down the tree. */ if(prev == NULL || prev->left == temp || prev->right == temp){ if(temp->left) push(&ms,temp->left); else if(temp->right) push(&ms,temp->right); else { /* If node is leaf node */ printf("%d ", temp->value); pop(&ms); } } /* case 2. We are moving up the tree from left child */ if(temp->left == prev){ if(temp->right) push(&ms,temp->right); else printf("%d ", temp->value); } /* case 3. We are moving up the tree from right child */ if(temp->right == prev){ printf("%d ", temp->value); pop(&ms); } prev = temp; } }