0% found this document useful (0 votes)
35 views12 pages

2-3 Trees

A 2-3 tree is a balanced search tree with nodes that can be either 2-nodes (one key, two children) or 3-nodes (two keys, three children), ensuring efficient operations with logarithmic height. Insertion and deletion operations maintain the tree's balance through splitting and merging nodes, with specific procedures for handling node overflow and underflow. The document also includes a C program that demonstrates the implementation of a 2-3 tree, including key insertion, deletion, and in-order traversal.

Uploaded by

vinita sharma
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
35 views12 pages

2-3 Trees

A 2-3 tree is a balanced search tree with nodes that can be either 2-nodes (one key, two children) or 3-nodes (two keys, three children), ensuring efficient operations with logarithmic height. Insertion and deletion operations maintain the tree's balance through splitting and merging nodes, with specific procedures for handling node overflow and underflow. The document also includes a C program that demonstrates the implementation of a 2-3 tree, including key insertion, deletion, and in-order traversal.

Uploaded by

vinita sharma
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 12

2-3 Trees –

In a 2-3 tree, insertion and deletion operations involve maintaining the structure of
the tree to ensure it remains balanced and retains its properties. The key properties
of a 2-3 tree are:

1. 2-Node: A node with one key and two children. The left child has values less than
the key, and the right child has values greater than the key.
2. 3-Node: A node with two keys and three children. The left child has values less
than the first key, the middle child has values between the first and second keys,
and the right child has values greater than the second key.

The tree is balanced, meaning that all paths from the root to any leaf have the same
length. This balance is maintained through split and merge operations during
insertions and deletions. The 2-3 tree guarantees a logarithmic height, providing
efficient search, insert, and delete operations with a time complexity of O(log n).

In summary, a 2-3 tree is a balanced search tree with nodes having either one key
and two children (2-node) or two keys and three children (3-node), ensuring
efficient operations and maintaining balance during updates.

1. 2-Node: A node with one key and two children.


2. 3-Node: A node with two keys and three children.

Here's a high-level overview of the theory behind insertion and deletion operations
in a 2-3 tree:

Insertion Operation:

1. Search for the Appropriate Node:


 Traverse the tree to find the leaf node where the new key should be inserted.
 If a 3-node is encountered, split it into two 2-nodes.
2. Insertion into a Leaf Node:
 If the leaf node is a 2-node, insert the new key.
 If the leaf node is a 3-node, split it into a temporary 4-node and then split the
4-node into two 2-nodes. Promote the middle key to the parent.
3. Propagation of Changes:
 If the parent becomes a 3-node after the insertion, apply the same process
recursively.
 If the root becomes a 3-node, create a new root with the middle key.

Deletion Operation:

1. Search for the Node to Delete:


 Traverse the tree to find the node containing the key to be deleted.
2. Deletion from a Leaf Node:
 If the node is a 2-node, simply delete the key.
 If the node is a 3-node, replace the key to be deleted with its in-order
successor and recursively delete the in-order successor.
3. Propagation of Changes:
 If underflow occurs (i.e., a node becomes a 1-node after deletion), borrow a
key from a sibling or merge nodes.
 Propagate changes up the tree, ensuring that all nodes remain balanced and
meet the 2-3 tree properties.
4. Adjustment in Parent Nodes:
 While propagating changes up the tree, handle the cases where a parent node
becomes underfilled or a 1-node.
5. Root Adjustment:
 If the root becomes a 1-node after deletion, replace it with its child.

Key Points:

During insertion and deletion, nodes are split or merged to maintain a balanced
structure.
Propagation of changes ensures that all ancestor nodes are updated to maintain the
properties of a 2-3 tree.
Rotations, borrowing keys, and merging nodes are common techniques to balance the
tree during insertions and deletions.

These operations guarantee that the 2-3 tree remains balanced and efficient for
search, insertion, and deletion, with a logarithmic height.
2-3 Program---

#include <stdio.h>

#include <stdlib.h>

struct Node {

int keys[2];

struct Node* child[3];

int keyCount;

};

// Function to create a new node

struct Node* createNode(int key) {

struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));

newNode->keys[0] = key;

newNode->keyCount = 1;

for (int i = 0; i < 3; i++) {

newNode->child[i] = NULL;

return newNode;

}
// Function to insert a key into the 2-3 tree

struct Node* insert(struct Node* root, int key) {

if (root == NULL) {

return createNode(key);

// Insert the key in the appropriate subtree

if (key < root->keys[0]) {

root->child[0] = insert(root->child[0], key);

} else if (root->keyCount == 1 || (key > root->keys[0] && key < root->keys[1]))


{

root->child[1] = insert(root->child[1], key);

} else {

root->child[2] = insert(root->child[2], key);

// Check and handle node overflow

if (root->keyCount == 2) {

struct Node* temp = createNode(root->keys[1]);

temp->child[0] = root->child[1];

temp->child[1] = root->child[2];

root->child[1] = temp;

root->child[2] = NULL;
root->keys[1] = 0;

root->keyCount = 1;

return temp;

return root;

// Function to print the 2-3 tree in-order

void inOrderTraversal(struct Node* root) {

if (root != NULL) {

inOrderTraversal(root->child[0]);

printf("%d ", root->keys[0]);

inOrderTraversal(root->child[1]);

if (root->keyCount == 2) {

printf("%d ", root->keys[1]);

inOrderTraversal(root->child[2]);

// Function to free memory allocated for the 2-3 tree

void freeTree(struct Node* root) {


if (root != NULL) {

freeTree(root->child[0]);

freeTree(root->child[1]);

freeTree(root->child[2]);

free(root);

// Function to find the minimum key in a 2-3 tree

int findMinKey(struct Node* root) {

while (root->child[0] != NULL) {

root = root->child[0];

return root->keys[0];

// Function to delete a key from the 2-3 tree

struct Node* deleteKey(struct Node* root, int key) {

if (root == NULL) {

return NULL;

if (key < root->keys[0]) {


root->child[0] = deleteKey(root->child[0], key);

} else if (key > root->keys[0] && (root->keyCount == 1 || key < root->keys[1]))


{

root->child[1] = deleteKey(root->child[1], key);

} else if (root->keyCount == 2 && key > root->keys[1]) {

root->child[2] = deleteKey(root->child[2], key);

} else {

if (root->keyCount == 1 || root->child[1] == NULL) {

root->keys[0] = 0;

root->keyCount = 0;

if (root->child[0] == NULL) {

free(root);

return NULL;

} else {

struct Node* temp = root->child[0];

free(root);

return temp;

} else {

int minKey = findMinKey(root->child[2]);

root->keys[0] = minKey;

root->child[2] = deleteKey(root->child[2], minKey);


}

if (root->child[1] == NULL) {

if (root->child[2]->keyCount == 2) {

root->child[1] = root->child[2]->child[0];

root->child[2]->child[0] = NULL;

root->keys[0] = root->child[2]->keys[0];

root->child[2]->keys[0] = root->child[2]->keys[1];

root->child[2]->keys[1] = 0;

root->child[2]->keyCount = 1;

} else if (root->child[0]->keyCount == 2) {

root->child[2] = root->child[1];

root->child[1] = root->child[0]->child[2];

root->child[0]->child[2] = NULL;

root->keys[0] = root->child[0]->keys[1];

root->child[0]->keys[1] = 0;

root->child[0]->keyCount = 1;

} else if (root->child[2]->keyCount == 1) {

root->child[2] = NULL;

root->keys[0] = root->child[0]->keys[1];
root->child[0]->keys[1] = 0;

root->child[0]->keyCount = 1;

return root;

int main() {

struct Node* root = NULL;

// Insert keys into the 2-3 tree

root = insert(root, 10);

printf("2-3 Tree after insertion of 10: ");

inOrderTraversal(root);

printf("\n");

root = insert(root, 5);

printf("2-3 Tree after insertion of 5: ");

inOrderTraversal(root);

printf("\n");

root = insert(root, 15);


printf("2-3 Tree after insertion of 15: ");

inOrderTraversal(root);

printf("\n");

root = insert(root, 3);

printf("2-3 Tree after insertion of 3: ");

inOrderTraversal(root);

printf("\n");

root = insert(root, 7);

printf("2-3 Tree after insertion of 7: ");

inOrderTraversal(root);

printf("\n");

root = insert(root, 12);

printf("2-3 Tree after insertion of 12: ");

inOrderTraversal(root);

printf("\n");

root = insert(root, 18);

printf("2-3 Tree after insertion of 18: ");

inOrderTraversal(root);

printf("\n");
// Delete a key from the 2-3 tree

root = deleteKey(root, 7);

printf("2-3 Tree after deletion of 7: ");

inOrderTraversal(root);

printf("\n");

// Free memory allocated for the 2-3 tree

freeTree(root);

return 0;

Output====================================

This output demonstrates the 2-3 tree after each insertion and the tree after the
deletion of the key '7'. The in-order traversal of the tree is displayed at each step.

2-3 Tree after insertion of 10: 10

2-3 Tree after insertion of 5: 5 10

2-3 Tree after insertion of 15: 5 10 15

2-3 Tree after insertion of 3: 3 5 10 15

2-3 Tree after insertion of 7: 3 5 7 10 15

2-3 Tree after insertion of 12: 3 5 7 10 12 15

2-3 Tree after insertion of 18: 3 5 7 10 12 15 18


2-3 Tree after deletion of 7: 3 5 10 12 15 18

You might also like