resueltos recorrido preorden imprimir ejercicios ejemplos codigo busqueda binarios binario arboles arbol python algorithm binary-tree breadth-first-search

python - preorden - recorrido de arboles binarios ejercicios resueltos



Impresión de BFS(árbol binario) en orden de nivel con_formateado específico_ (12)

Para empezar, esta pregunta no es una falsificación de esta , sino que se basa en ella.

Tomando el árbol en esa pregunta como ejemplo,

1 / / 2 3 / / / 4 5 6

¿Cómo modificarías tu programa para imprimirlo así?

1 2 3 4 5 6

en lugar del general

1 2 3 4 5 6

Básicamente, estoy buscando intuiciones sobre la forma más eficiente de hacerlo: tengo un método que consiste en adjuntar el resultado a una lista y luego recorrerlo en bucle. Una forma más eficiente podría ser almacenar el último elemento en cada nivel a medida que se abre, e imprimir una nueva línea después.

Ideas?


¿por qué no mantener la cola en espera y verificar cuándo se procesan todos los nodos del nivel actual?

public void printLevel(Node n) { Queue<Integer> q = new ArrayBlockingQueue<Integer>(); Node sentinal = new Node(-1); q.put(n); q.put(sentinal); while(q.size() > 0) { n = q.poll(); System.out.println(n.value + " "); if (n == sentinal && q.size() > 0) { q.put(sentinal); //push at the end again for next level System.out.println(); } if (q.left != null) q.put(n.left); if (q.right != null) q.put(n.right); } }


Aquí mi código imprime el nivel del árbol por nivel, así como al revés

int counter=0;// to count the toatl no. of elments in the tree void tree::print_treeupsidedown_levelbylevel(int *array) { int j=2; int next=j; int temp=0; while(j<2*counter) { if(array[j]==0) break; while(array[j]!=-1) { j++; } for(int i=next,k=j-1 ;i<k; i++,k--) { temp=array[i]; array[i]=array[k]; array[k]=temp; } next=j+1; j++; } for(int i=2*counter-1;i>=0;i--) { if(array[i]>0) printf("%d ",array[i]); if(array[i]==-1) printf("/n"); } } void tree::BFS() { queue<node *>p; node *leaf=root; int array[2*counter]; for(int i=0;i<2*counter;i++) array[i]=0; int count=0; node *newline=new node; //this node helps to print a tree level by level newline->val=0; newline->left=NULL; newline->right=NULL; newline->parent=NULL; p.push(leaf); p.push(newline); while(!p.empty()) { leaf=p.front(); if(leaf==newline) { printf("/n"); p.pop(); if(!p.empty()) p.push(newline); array[count++]=-1; } else { cout<<leaf->val<<" "; array[count++]=leaf->val; if(leaf->left!=NULL) { p.push(leaf->left); } if(leaf->right!=NULL) { p.push(leaf->right); } p.pop(); } } delete newline; print_treeupsidedown_levelbylevel(array); }

Aquí en mi código, la función BFS imprime el nivel del árbol por nivel, que también llena los datos en una matriz int para imprimir el árbol al revés. (Tenga en cuenta que se utiliza un poco de intercambio al imprimir el árbol al revés, lo que ayuda a lograr nuestro objetivo). Si el intercambio no se realiza entonces para un árbol como

8 / / 1 12 / / 5 9 / / 4 7 / 6

o / p será

6 7 4 9 5 12 1 8

pero el o / p tiene que ser

6 4 7 5 9 1 12 8

esta es la razón por la que se necesitaba el intercambio de parte en esa matriz.


Creo que lo que espera es imprimir los nodos en cada nivel separados por un espacio o una coma y los niveles se separan por una nueva línea. Así es como codificaría el algoritmo. Sabemos que cuando hacemos una búsqueda de amplitud en un gráfico o árbol e insertamos los nodos en una cola, todos los nodos en la cola que salgan estarán al mismo nivel que el anterior o un nuevo nivel que sea el nivel primario + 1 y nada más.

Entonces, cuando esté en un nivel, siga imprimiendo los valores de los nodos y tan pronto como encuentre que el nivel del nodo aumenta en 1, inserte una nueva línea antes de comenzar a imprimir todos los nodos a ese nivel.

Este es mi código que no usa mucha memoria y solo se necesita la cola para todo.

Asumiendo que el árbol comienza desde la raíz.

queue = [(root, 0)] # Store the node along with its level. prev = 0 while queue: node, level = queue.pop(0) if level == prev: print(node.val, end = "") else: print() print(node.val, end = "") if node.left: queue.append((node.left, level + 1)) if node.right: queue.append((node.right, level + 1)) prev = level

Al final, todo lo que necesita es la cola para todo el procesamiento.


El siguiente código imprimirá cada nivel de árbol binario en una nueva línea:

from binarytree import Node, show root = Node(1) root.left = Node(2) root.right = Node(3) root.left.left = Node(4) root.right.left = Node(5) root.right.right = Node(6) show(root)


Esta es la primera búsqueda de amplitud, por lo que puede usar una cola y hacer esto recursivamente de una manera simple y compacta ...

# built-in data structure we can use as a queue from collections import deque def print_level_order(head, queue = deque()): if head is None: return print head.data [queue.append(node) for node in [head.left, head.right] if node] if queue: print_level_order(queue.popleft(), queue)


Mi solución es similar a la de Alex Martelli, pero separo el recorrido de la estructura de datos del procesamiento de la estructura de datos. Puse la carne del código en iterLayers para mantener printByLayer corto y dulce.

from collections import deque class Node: def __init__(self, val, lc=None, rc=None): self.val = val self.lc = lc self.rc = rc def iterLayers(self): q = deque() q.append(self) def layerIterator(layerSize): for i in xrange(layerSize): n = q.popleft() if n.lc: q.append(n.lc) if n.rc: q.append(n.rc) yield n.val while (q): yield layerIterator(len(q)) def printByLayer(self): for layer in self.iterLayers(): print '' ''.join([str(v) for v in layer]) root = Node(1, Node(2, Node(4, Node(7))), Node(3, Node(5), Node(6))) root.printByLayer()

que imprime lo siguiente cuando se ejecuta:

1 2 3 4 5 6 7


Para aquellos que simplemente están interesados ​​en visualizar árboles binarios (y no tanto en la teoría detrás de la búsqueda de amplitud), hay una función de show en el paquete binarytree . Aplicado al ejemplo dado en la pregunta,

1__ / / 2 3 / / / 4 5 6

que imprime

public void printbylevel(node root){ int counter = 0, level = 0; Queue<node> qu = new LinkedList<node>(); qu.add(root); level = 1; if(root.child1 != null)counter++; if(root.child2 != null)counter++; while(!qu.isEmpty()){ node temp = qu.remove(); level--; System.out.print(temp.val); if(level == 0 ){ System.out.println(); level = counter; counter = 0; } if(temp.child1 != null){ qu.add(temp.child1); counter++; } if(temp.child2 != null){ qu.add(temp.child2); counter++; } } }


Solo construye un nivel a la vez, por ejemplo:

class Node(object): def __init__(self, value, left=None, right=None): self.value = value self.left = left self.right = right def traverse(rootnode): thislevel = [rootnode] while thislevel: nextlevel = list() for n in thislevel: print n.value, if n.left: nextlevel.append(n.left) if n.right: nextlevel.append(n.right) print thislevel = nextlevel t = Node(1, Node(2, Node(4, Node(7))), Node(3, Node(5), Node(6))) traverse(t)

Edición : si está interesado en obtener un pequeño ahorro en la memoria "auxiliar" máxima consumida (nunca teniendo simultáneamente todo este nivel y el siguiente nivel en dicha memoria "auxiliar"), por supuesto puede usar collection.deque lugar de list , y consuma el nivel actual a medida que popleft (a través de popleft ) en lugar de simplemente hacer un bucle. La idea de crear un nivel a la vez (a medida que consume --o iterar en-- el anterior) permanece intacta - cuando necesita distinguir niveles, es más directo que usar una única información adicional de deque más grande ( como la profundidad, o el número de nodos que quedan en un nivel dado).

Sin embargo, una lista que solo se agrega a (y está en bucle, en lugar de "consumida") es bastante más eficiente que un deque (y si push_back soluciones en C ++, de manera similar, un std :: vector con solo push_back para construirlo, y un bucle para luego usarlo, es más eficiente que un std :: deque). Dado que todo lo que se produce ocurre primero, luego toda la iteración (o consumo), una alternativa interesante si la memoria está estrechamente restringida podría ser utilizar una lista de todos modos para representar cada nivel, luego .reverse antes de comenzar a consumirla (con llamadas .pop ) - No tengo grandes árboles alrededor para verificar por medición, pero sospecho que este enfoque aún sería más rápido (y en realidad consumiría menos memoria) que deque (suponiendo que la implementación subyacente de la lista [[o std :: vector]] en realidad recicla la memoria después de algunas llamadas a pop [[o pop_back ]] - y con la misma suposición de deque, por supuesto ;-).


Suena como el primer paso para mí.

El primer recorrido se implementa con una queue . Aquí, simplemente inserte en la cola un token especial que indique que se debe imprimir una nueva línea. Cada vez que se encuentra el token, imprima una nueva línea y vuelva a insertarlo en la cola (al final, esa es la definición de una cola).

Inicie el algoritmo con una cola que contenga la raíz seguida del token especial de nueva línea.


Una versión que no requiere almacenamiento extra:

std::deque<Node> bfs; bfs.push_back(start); int nodesInThisLayer = 1; int nodesInNextLayer = 0; while (!bfs.empty()) { Node front = bfs.front(); bfs.pop_front(); for (/*iterate over front''s children*/) { ++nodesInNextLayer; nodes.push_back(child); } std::cout << node.value; if (0 == --nodesInThisLayer) { std::cout << std::endl; nodesInThisLayer = nodesInNextLayer; nodesInNextLayer = 0; } else { std::cout << " "; } }

PD, perdón por el código C ++, no soy muy fluido en Python todavía.


Una versión simple basada en Bread First Search, este código es aplicable para gráficos en general y también puede usarse para árboles binarios.

def printBfsLevels(graph,start): queue=[start] path=[] currLevel=1 levelMembers=1 height=[(0,start)] childCount=0 print queue while queue: visNode=queue.pop(0) if visNode not in path: if levelMembers==0: levelMembers=childCount childCount=0 currLevel=currLevel+1 queue=queue+graph.get(visNode,[]) if levelMembers > 0: levelMembers=levelMembers-1 for node in graph.get(visNode,[]): childCount=childCount+1 height.append((currLevel,node)) path=path+[visNode] prevLevel=None for v,k in sorted(height): if prevLevel!=v: if prevLevel!=None: print "/n" prevLevel=v print k, return height g={1: [2, 3,6], 2: [4, 5], 3: [6, 7],4:[8,9,13]} printBfsLevels(g,1) >>> [1] 1 2 3 6 4 5 6 7 8 9 13 >>>

Otra versión basada en Recursión, que es específica de árbol binario

class BinTree: "Node in a binary tree" def __init__(self,val,leftChild=None,rightChild=None,root=None): self.val=val self.leftChild=leftChild self.rightChild=rightChild self.root=root if not leftChild and not rightChild: self.isExternal=True def getChildren(self,node): children=[] if node.isExternal: return [] if node.leftChild: children.append(node.leftChild) if node.rightChild: children.append(node.rightChild) return children @staticmethod def createTree(tupleList): "Creates a Binary tree Object from a given Tuple List" Nodes={} root=None for item in treeRep: if not root: root=BinTree(item[0]) root.isExternal=False Nodes[item[0]]=root root.root=root root.leftChild=BinTree(item[1],root=root) Nodes[item[1]]=root.leftChild root.rightChild=BinTree(item[2],root=root) Nodes[item[2]]=root.rightChild else: CurrentParent=Nodes[item[0]] CurrentParent.isExternal=False CurrentParent.leftChild=BinTree(item[1],root=root) Nodes[item[1]]=CurrentParent.leftChild CurrentParent.rightChild=BinTree(item[2],root=root) Nodes[item[2]]=CurrentParent.rightChild root.nodeDict=Nodes return root def printBfsLevels(self,levels=None): if levels==None: levels=[self] nextLevel=[] for node in levels: print node.val, for node in levels: nextLevel.extend(node.getChildren(node)) print ''/n'' if nextLevel: node.printBfsLevels(nextLevel) ## 1 ## 2 3 ## 4 5 6 7 ## 8 treeRep = [(1,2,3),(2,4,5),(3,6,7),(4,8,None)] tree= BinTree.createTree(treeRep) tree.printBfsLevels() >>> 1 2 3 4 5 6 7 8 None


class TNode: def __init__(self, data, left=None, right=None): self.data = data self.left = left self.right = right class BST: def __init__(self, root): self._root = root def bfs(self): list = [self._root] while len(list) > 0: print [e.data for e in list] list = [e.left for e in list if e.left] + / [e.right for e in list if e.right] bst = BST(TNode(1, TNode(2, TNode(4), TNode(5)), TNode(3, TNode(6), TNode(7)))) bst.bfs()