En un árbol de búsqueda binaria (BST), todas las claves en el subárbol izquierdo de una clave deben ser más pequeñas y todas las claves en el subárbol derecho deben ser mayores. Entonces, un Árbol de búsqueda binaria, por definición, tiene claves distintas.
¿Cómo permitir duplicados donde cada inserción inserta una clave más con un valor y cada eliminación elimina una ocurrencia?
Una solución simple es permitir las mismas teclas en el lado derecho (también podríamos elegir el lado izquierdo). Por ejemplo, considere la inserción de las claves 12, 10, 20, 9, 11, 10, 12, 12 en un Árbol de búsqueda binario vacío
- ¿Qué compañías necesitan algoritmos de flujo óptico fuertes?
- ¿Cuál es la mejor manera de entender la recursividad, especialmente en los árboles?
- ¿Es posible escribir un método que muestre todos los elementos en una lista enlazada circular?
- ¿Cuál es el futuro de la música generada por computadora?
- ¿Cómo podemos solucionar esto?
12
/ \
10 20
/ \ /
9 11 12
/ \
10 12
Una mejor solución es aumentar cada nodo de árbol para almacenar el conteo junto con campos regulares como clave, punteros izquierdo y derecho.
La inserción de las claves 12, 10, 20, 9, 11, 10, 12, 12 en un Árbol de búsqueda binario vacío crearía lo siguiente.
12 (3)
/ \
10 (2) 20 (1)
/ \
9 (1) 11 (1)
El recuento de una clave se muestra entre paréntesis
Este enfoque tiene las siguientes ventajas sobre el enfoque simple anterior.
1) La altura del árbol es pequeña independientemente del número de duplicados. Tenga en cuenta que la mayoría de las operaciones BST (buscar, insertar y eliminar) tienen una complejidad de tiempo como O (h) donde h es la altura de BST. Entonces, si podemos mantener la altura pequeña, obtenemos una menor cantidad de comparaciones clave.
2) Buscar, Insertar y Eliminar se vuelven más fáciles de hacer. Podemos usar los mismos algoritmos de inserción, búsqueda y eliminación con pequeñas modificaciones (ver el código a continuación).
3) Este enfoque también es adecuado para BST de equilibrio automático (Árbol AVL, ÁRBOL NEGRO ROJO, etc.). Estos árboles implican rotaciones, y una rotación puede violar la propiedad BST de la solución simple ya que una misma clave puede estar en el lado izquierdo o derecho después de la rotación.
A continuación se muestra la implementación en C del árbol de búsqueda binaria normal con recuento con cada clave. Básicamente, este código se toma del código para insertar y eliminar en BST. Los cambios realizados para manejar duplicados están resaltados, el resto del código es el mismo.
// C program to implement basic operations (search, insert and delete)
// on a BST that handles duplicates by storing count with every node
#include
#include
node
struct
{
key;
int
key;
int
count;
struct
node *left, *right;
};
// A utility function to create a new BST node
struct
node *newNode(int
item)
{
struct
node *temp = (struct
node *)malloc(sizeof(struct
node));
temp->key = item;
temp->left = temp->right = NULL;
temp->count = 1;
temp;
return
temp;
}
// A utility function to do inorder traversal of BST
void
inorder(struct
node *root)
inorder(struct
node *root)
{
if
(root != NULL)
{
inorder(root->left);
printf("%d(%d) ", root->key, root->count);
inorder(root->right);
}
}
/* A utility function to insert a new node with given key in BST */
struct
node* insert(struct
node* node, int
key)
{
/* If the tree is empty, return a new node */
if
(node == NULL) return
newNode(key);
// If key already exists in BST, icnrement count and return
if
(key == node->key)
{
(node->count)++;
node;
return
node;
}
/* Otherwise, recur down the tree */
if
(key key)
node->left = insert(node->left, key);
else
node->right = insert(node->right, key);
/* return the (unchanged) node pointer */
node;
return
node;
}
/* Given a non-empty binary search tree, return the node with
minimum key value found in that tree. Note that the entire
tree does not need to be searched. */
struct
node * minValueNode(struct
node* node)
{
struct
node* current = node;
/* loop down to find the leftmost leaf */
while
(current->left != NULL)
current = current->left;
current;
return
current;
}
/* Given a binary search tree and a key, this function
deletes a given key and returns root of modified tree */
struct
node* deleteNode(struct
node* root, int
key)
{
// base case
if
(root == NULL) return
root;
// If the key to be deleted is smaller than the
// root's key, then it lies in left subtree
if
(key key)
root->left = deleteNode(root->left, key);
// If the key to be deleted is greater than the root's key,
// then it lies in right subtree
else
if
(key > root->key)
root->right = deleteNode(root->right, key);
// if key is same as root's key
else
{
// If key is present more than once, simply decrement
// count and return
if
(root->count > 1)
{
(root->count)--;
return
root;
}
// ElSE, delete the node
// node with only one child or no child
if
(root->left == NULL)
{
struct
node *temp = root->right;
free(root);
temp;
return
temp;
}
else
if
(root->right == NULL)
{
struct
node *temp = root->left;
free(root);
temp;
return
temp;
}
// node with two children: Get the inorder successor (smallest
// in the right subtree)
struct
node* temp = minValueNode(root->right);
// Copy the inorder successor's content to this node
root->key = temp->key;
// Delete the inorder successor
root->right = deleteNode(root->right, temp->key);
}
return
root;
}
// Driver Program to test above functions
int
main()
{
/* Let us create following BST
12(3)
/ \
10(2) 20(1)
/ \
9(1) 11(1) */
struct
node *root = NULL;
root = insert(root, 12);
root = insert(root, 10);
root = insert(root, 20);
root = insert(root, 9);
root = insert(root, 11);
root = insert(root, 10);
root = insert(root, 12);
root = insert(root, 12);
printf("Inorder traversal of the given tree \n");
inorder(root);
printf("\nDelete 20\n");
root = deleteNode(root, 20);
printf("Inorder traversal of the modified tree \n");
inorder(root);
printf("\nDelete 12\n");
root = deleteNode(root, 12);
printf("Inorder traversal of the modified tree \n");
inorder(root);
printf("\nDelete 9\n");
root = deleteNode(root, 9);
printf("Inorder traversal of the modified tree \n");
inorder(root);
return
0;
}