¿Cómo puede encontrar sucesores y predecesores en un árbol de búsqueda binario en orden?

Podemos usar la propiedad El árbol de búsqueda binaria (BST) para encontrar el sucesor y predecesor de un nodo en un BST.

Encontrar el nodo sucesor de un nodo dado:

Aquí hay dos casos:

1. El nodo tiene un subárbol derecho.
Si el nodo dado tiene un subárbol derecho, entonces, mediante la propiedad BST, la siguiente clave más grande debe estar en el subárbol derecho. Como todas las claves en un subárbol derecho son más grandes que la clave del nodo dado, el sucesor debe ser la más pequeña de todas las claves en el subárbol derecho.

2. El nodo no tiene un subárbol derecho.
En este caso, tendremos que buscar el árbol, ya que ese es el único lugar donde podemos encontrar la siguiente clave más grande. No tiene sentido mirar el subárbol izquierdo, ya que se garantiza que todas las claves en el subárbol izquierdo serán más pequeñas que la clave en el árbol dado.

Cuando miramos hacia arriba desde el nodo dado, puede haber dos casos: primero, el nodo actual es el hijo izquierdo de su padre. En este caso, el padre es el nodo sucesor. Esto se debe a que el padre siempre viene después en el orden transversal si ha terminado con el subárbol izquierdo (arraigado en el nodo actual).
En segundo lugar, el nodo actual es el hijo derecho del padre. Este es un caso interesante. En este caso, a medida que sigue subiendo por la cadena de antepasados, encontrará valores más pequeños si sube, pero valores más grandes si va hacia la derecha. El nodo sucesor será el primer nodo en la cadena ancestral que encuentre en la cadena derecha.

Aquí está el código Java para encontrar el sucesor de un nodo dado. Esto supone una clase TreeNode que representa nodos en el BST:

árbol estático público findSuccessor (nodo TreeNode)
{
if (nodo == nulo)
volver nulo;

if (node.getRight ()! = null)
return findMinimum (node.getRight ());

TreeNode y = node.getParent ();
TreeNode x = nodo;
while (y! = null && x == y.getRight ())
{
x = y;
y = y.getParent ();
}
// Intuición: a medida que atravesamos el árbol hacia la izquierda, atravesamos valores más pequeños
// El primer nodo a la derecha es el siguiente número más grande
volver y;
}

Encontrar el nodo predecesor sigue una lógica simétrica. Aquí está el código Java para eso:

árbol estático público findPredecessor (nodo TreeNode)
{
if (nodo == nulo)
volver nulo;

if (node.getLeft ()! = null)
return findMaximum (node.getLeft ());

TreeNode parent = node.getParent ();

TreeNode y = padre;
TreeNode x = nodo;
while (y! = null && x == y.getLeft ())
{
x = y;
y = y.getParent ();
}

volver y;
}

He escrito un extenso tutorial sobre BST aquí: http: //exceptional-code.blogspot…

Tengo este código para encontrar el sucesor en orden de un BST, estoy seguro de que podrá realizar un par de cambios triviales para cambiarlo a un predecesor en orden al comprender esta solución iterativa.

Supuesto que hice: los nodos están vinculados desde el padre —-> hijo y no hay ningún enlace entre el hijo y el padre.

Aquí está el código, que supongo que es bastante fácil de entender.

  #include "stdafx.h"
 #incluye "iostream"
 #include "vector"
 usando el espacio de nombres estándar;
 // estructura que construí para el árbol de búsqueda binaria
 struct bst {
	 int val;
	 bst * enlace [2];  // enlace [0] -> hijo izquierdo, enlace [1] -> hijo derecho
	 bst (int x) {
		 val = x;
		 enlace [0] = NULL;
		 enlace [1] = NULL;
	 }
 };

 Solución de clase {
 público:
	 vector  nodos;
	 bst * transversal (bst * cabeza, bst * nodo) {
		 int dir;

		 // Este ciclo while encuentra el valor del nodo cuyo sucesor se debe encontrar.
		 while (head-> val! = node-> val && head) {
			 dir = cabeza-> val  val;  // viaja a la izquierda si head-> val  val, viaja a la derecha de lo contrario.
			 node.push_back (cabeza);  // empuja los nodos hacia una matriz o una pila con la que te encuentras mientras recorres el árbol.
			 cabeza = cabeza-> enlace [dir]; 
		 }
		 // verifica si el "nodo" tiene un hijo secundario o un subárbol derecho.
		 if (nodo-> enlace [1]) {  
			 nodo = nodo-> enlace [1];  // atravesar al niño derecho.
			 while (node-> link [0]) {// encuentra el nodo más a la izquierda del subárbol derecho o subárbol derecho.
				 nodo = nodo-> enlace [0];
			 }
			 nodo de retorno;  // devuelve el sucesor en orden.
		 }
		 / * Si "nodo" no tiene un subárbol correcto, 
		 encontrar el nodo inmediato en el orden del nodo visitado más recientemente
		 cuyo valor es mayor que "nodo-> val" 
		 * /
		 más {
			 for (int i = node.size () - 1; i> = 0; i--) {
				 if (nodos [i] -> val> nodo-> val)   
					 nodos de retorno [i]; 
			 }
		 }
		 devuelve NULL;  // Este caso ocurre solo cuando el nodo de entrada es el nodo más a la derecha del árbol de búsqueda binario, en cuyo caso no existe una solución y devuelve NULL.
	 }
 };
 int main ()
 {
	 bst * head = nuevo bst (20);
	 head-> link [0] = nuevo bst (8);
	 head-> link [1] = nuevo bst (22);
	 head-> link [0] -> link [0] = nuevo bst (4);
	 head-> link [0] -> link [1] = nuevo bst (12);
	 head-> link [0] -> link [1] -> link [0] = nuevo bst (10);
	 head-> link [0] -> link [1] -> link [1] = nuevo bst (14);
	 Solución s;
	 bst * nodo = cabeza-> enlace [1];
	 head = s.traverse (cabeza, nodo);
	 cout << cabeza-> val;
	 devuelve 0;
 }

El elemento mínimo en un BST se encuentra recorriendo el lado izquierdo del árbol hasta llegar a un nodo que no tiene un hijo izquierdo. Del mismo modo, el elemento máximo se encuentra recorriendo el lado derecho del árbol hasta llegar a un nodo que no tiene un hijo derecho.

Con eso en mente, el predecesor en orden de un nodo es el nodo máximo en el hijo izquierdo del nodo. Si no queda hijo secundario, entonces no hay predecesor si el nodo es el nodo raíz o si el nodo padre es mayor que el nodo. De lo contrario, el predecesor en orden es el nodo padre.

Del mismo modo, el sucesor de orden de un nodo es el nodo mínimo en el elemento secundario derecho del nodo. Si no hay un hijo correcto, entonces no hay sucesor si el nodo es el nodo raíz o si el nodo padre es menor que el nodo. De lo contrario, el sucesor en orden de un nodo es el nodo padre.

Aquí hay un código bastante simple para encontrar sucesores en orden: sucesor en orden de un nodo en un árbol binario.

El código anterior no utiliza ningún puntero principal. Funciona para cualquier árbol binario y NO solo para el árbol de búsqueda binaria. Si utiliza la propiedad de BST, puede simplificarse aún más.

El predecesor sigue una lógica similar.

  nodo * nextInorderSuccessor (nodo * raíz, nodo * tofind) {
	 if (! root ||! tofind) return;

	 // si un nodo tiene un hijo correcto
	 // bucle al hijo más a la izquierda (del hijo derecho)
	 // si no hay ninguno, devuelve el niño correcto
	 // si no hay un hijo adecuado (2 situaciones):
	 // si el nodo actual se deja hijo del padre: devuelve el padre (el padre es NULL para la raíz)
	 // más si el niño correcto devuelve abuelo
     nodo * sucesor = NULL;
	 if (tofind-> right) {
		 sucesor = tofind-> right;
		 while (sucesor-> izquierda) {
			 sucesor = sucesor-> izquierda;
		 }
	 }
	 más {
		 // este es un hallazgo modificado en el nodo "tofind"
		 // donde cuando el nodo a encontrar es más pequeño que
		 // es el nodo padre, el puntero sucesor es 
		 // actualizado para apuntar al padre
		 while (raíz) {
			 if (tofind-> data  data) {
				 sucesor = raíz;
				 raíz = raíz-> izquierda;
			 }
			 si no (tofind-> data> root-> data) {
				 raíz = raíz-> derecha;
			 }
			 más {
				 descanso;
			 }
		 }
	 }
     volver sucesor;
 } 

Invierta la lógica para encontrar predecesor.

He agregado una publicación de blog donde uso sucesor y predecesor de un nodo en BST.

Sucesor:
La idea básica es que cada vez que giramos a la izquierda en BST en un nodo, ese nodo es candidato a sucesor.

Predecesor:
Cada vez que giramos a la derecha un nodo, ese nodo es candidato para el predecesor.
Una vez que llegamos al nodo y este ha dejado el subárbol, la mayoría del nodo derecho del subárbol izquierdo sería el predecesor en orden.

Para el código, consulte http://algorithmsandme.in/2016/0

El sucesor y predecesor en un árbol de búsqueda binario se explica bien aquí:

Sucesor de orden en el árbol de búsqueda binaria.

La solución sucesora de pedido se explica bien en este enlace.

Ordene predecesor y sucesor para una clave dada en BST – GeeksforGeeks y considere todas las referencias para una mejor comprensión

Debo escribir un programa que sea capaz de encontrar un predecesor de un número dado en la programación C. No sé escribir código Java. ¿Hay alguien que pueda ayudarme con la programación C.

No podemos simplemente clasificar los elementos del bst y luego encontrar el sucesor de orden … el elemento justo al lado. El elemento dado será su sucesor de orden.