
- DSA - Home
- DSA - Overview
- DSA - Environment Setup
- DSA - Algorithms Basics
- DSA - Asymptotic Analysis
- Data Structures
- DSA - Data Structure Basics
- DSA - Data Structures and Types
- DSA - Array Data Structure
- DSA - Skip List Data Structure
- Linked Lists
- DSA - Linked List Data Structure
- DSA - Doubly Linked List Data Structure
- DSA - Circular Linked List Data Structure
- Stack & Queue
- DSA - Stack Data Structure
- DSA - Expression Parsing
- DSA - Queue Data Structure
- DSA - Circular Queue Data Structure
- DSA - Priority Queue Data Structure
- DSA - Deque Data Structure
- Searching Algorithms
- DSA - Searching Algorithms
- DSA - Linear Search Algorithm
- DSA - Binary Search Algorithm
- DSA - Interpolation Search
- DSA - Jump Search Algorithm
- DSA - Exponential Search
- DSA - Fibonacci Search
- DSA - Sublist Search
- DSA - Hash Table
- Sorting Algorithms
- DSA - Sorting Algorithms
- DSA - Bubble Sort Algorithm
- DSA - Insertion Sort Algorithm
- DSA - Selection Sort Algorithm
- DSA - Merge Sort Algorithm
- DSA - Shell Sort Algorithm
- DSA - Heap Sort Algorithm
- DSA - Bucket Sort Algorithm
- DSA - Counting Sort Algorithm
- DSA - Radix Sort Algorithm
- DSA - Quick Sort Algorithm
- Matrices Data Structure
- DSA - Matrices Data Structure
- DSA - Lup Decomposition In Matrices
- DSA - Lu Decomposition In Matrices
- Graph Data Structure
- DSA - Graph Data Structure
- DSA - Depth First Traversal
- DSA - Breadth First Traversal
- DSA - Spanning Tree
- DSA - Topological Sorting
- DSA - Strongly Connected Components
- DSA - Biconnected Components
- DSA - Augmenting Path
- DSA - Network Flow Problems
- DSA - Flow Networks In Data Structures
- DSA - Edmonds Blossom Algorithm
- DSA - Maxflow Mincut Theorem
- Tree Data Structure
- DSA - Tree Data Structure
- DSA - Tree Traversal
- DSA - Binary Search Tree
- DSA - AVL Tree
- DSA - Red Black Trees
- DSA - B Trees
- DSA - B+ Trees
- DSA - Splay Trees
- DSA - Range Queries
- DSA - Segment Trees
- DSA - Fenwick Tree
- DSA - Fusion Tree
- DSA - Hashed Array Tree
- DSA - K-Ary Tree
- DSA - Kd Trees
- DSA - Priority Search Tree Data Structure
- Recursion
- DSA - Recursion Algorithms
- DSA - Tower of Hanoi Using Recursion
- DSA - Fibonacci Series Using Recursion
- Divide and Conquer
- DSA - Divide and Conquer
- DSA - Max-Min Problem
- DSA - Strassen's Matrix Multiplication
- DSA - Karatsuba Algorithm
- Greedy Algorithms
- DSA - Greedy Algorithms
- DSA - Travelling Salesman Problem (Greedy Approach)
- DSA - Prim's Minimal Spanning Tree
- DSA - Kruskal's Minimal Spanning Tree
- DSA - Dijkstra's Shortest Path Algorithm
- DSA - Map Colouring Algorithm
- DSA - Fractional Knapsack Problem
- DSA - Job Sequencing with Deadline
- DSA - Optimal Merge Pattern Algorithm
- Dynamic Programming
- DSA - Dynamic Programming
- DSA - Matrix Chain Multiplication
- DSA - Floyd Warshall Algorithm
- DSA - 0-1 Knapsack Problem
- DSA - Longest Common Sub-sequence Algorithm
- DSA - Travelling Salesman Problem (Dynamic Approach)
- Hashing
- DSA - Hashing Data Structure
- DSA - Collision In Hashing
- Disjoint Set
- DSA - Disjoint Set
- DSA - Path Compression And Union By Rank
- Heap
- DSA - Heap Data Structure
- DSA - Binary Heap
- DSA - Binomial Heap
- DSA - Fibonacci Heap
- Tries Data Structure
- DSA - Tries
- DSA - Standard Tries
- DSA - Compressed Tries
- DSA - Suffix Tries
- Treaps
- DSA - Treaps Data Structure
- Bit Mask
- DSA - Bit Mask In Data Structures
- Bloom Filter
- DSA - Bloom Filter Data Structure
- Approximation Algorithms
- DSA - Approximation Algorithms
- DSA - Vertex Cover Algorithm
- DSA - Set Cover Problem
- DSA - Travelling Salesman Problem (Approximation Approach)
- Randomized Algorithms
- DSA - Randomized Algorithms
- DSA - Randomized Quick Sort Algorithm
- DSA - Karger’s Minimum Cut Algorithm
- DSA - Fisher-Yates Shuffle Algorithm
- Miscellaneous
- DSA - Infix to Postfix
- DSA - Bellmon Ford Shortest Path
- DSA - Maximum Bipartite Matching
- DSA Useful Resources
- DSA - Questions and Answers
- DSA - Selection Sort Interview Questions
- DSA - Merge Sort Interview Questions
- DSA - Insertion Sort Interview Questions
- DSA - Heap Sort Interview Questions
- DSA - Bubble Sort Interview Questions
- DSA - Bucket Sort Interview Questions
- DSA - Radix Sort Interview Questions
- DSA - Cycle Sort Interview Questions
- DSA - Quick Guide
- DSA - Useful Resources
- DSA - Discussion
Fusion Tree
Fusion Tree is a part of advanced data structures which is used for maintaining the ordered set of elements.
On a finite universe, if each input integers has size less than 2w and if those numbers are non-negative, it implements an associative array on W-bit integers.
It uses the combination of a B-Tree and a hash table which help in reducing the time complexity of the operations like insertion, deletion and searching in the tree.
How Fusion Tree Works?
Following factors are considered while implementing a fusion tree:
- Bit manipulation : The tree extracts specific bits from stored integers and processes them in order to speed up the operations.
- Parallelism : It uses 64 or 128 bits machine words to compare and manipulate multiple keys at same time.
- Sketching : Sketching means summarizing integers into smaller representation (called as sketches) which can be used to compare the integers. It is done by extracting most important bits from the integers. that reduces the number of comparisons it usually requires to compare two integers.
- Precomputed Operations : It pre-computes the operations like min, max, successor and predecessor which are used frequently in the tree.
Representation of Fusion Tree
Fusion tree is represented as a B-tree of height logWn where n is the number of elements in the tree.
Here, W is the number of bits in the integer.
Each node can hold child point upto B+1 just like a B-tree where B is the maximum number of children a node can have.
Operations on Fusion Tree
Following are the operations that can be performed on a fusion tree:
- Insertion
- Deletion
- Searching
Implementation of Fusion Tree
Algorithm to Insert and Create Elements in Fusion Tree
2. Create a fusion tree with root node as NULL 3. Insert the elements in the tree 4. If the tree is empty, create a new node and insert the element in it 5. If the tree is not empty, find the appropriate node to insert the element 6. If the node is full, split the node and insert the element in the appropriate node 7. Repeat the steps 5 and 6 until all the elements are inserted
Code to Insert Elements in Fusion Tree
Now let's see how we can implement a fusion tree in C, C++, Java and Python:
#include <stdio.h> #include <stdlib.h> #define W 32 // Word size (number of bits in an integer) #define B 4 // Max number of keys per node struct node { int keys[B]; // Keys in the node struct node *child[B + 1]; // Child pointers (B+1 for B keys) int n; // Number of keys in the node int leaf; // 1 if the node is a leaf, 0 otherwise }; // Root of the tree struct node *root = NULL; // Function to create a new node struct node *createNode() { struct node *newNode = (struct node *)malloc(sizeof(struct node)); newNode->n = 0; newNode->leaf = 1; for (int i = 0; i <= B; i++) { newNode->child[i] = NULL; } return newNode; } // Split the child node if it is full void splitChild(struct node *parent, int i, struct node *fullChild) { struct node *halfChild = createNode(); halfChild->leaf = fullChild->leaf; halfChild->n = B / 2; // Move the last B/2 keys of fullChild to halfChild for (int j = 0; j < B / 2; j++) { halfChild->keys[j] = fullChild->keys[j + B / 2]; } // Move the child pointers of fullChild to halfChild if (fullChild->leaf == 0) { for (int j = 0; j < B / 2 + 1; j++) { halfChild->child[j] = fullChild->child[j + B / 2]; } } fullChild->n = B / 2; // Move the middle key from fullChild to parent for (int j = parent->n; j > i; j--) { parent->child[j + 1] = parent->child[j]; } parent->child[i + 1] = halfChild; for (int j = parent->n - 1; j >= i; j--) { parent->keys[j + 1] = parent->keys[j]; } parent->keys[i] = fullChild->keys[B / 2]; parent->n++; } // Insert a key into a node (when the node is not full) void insertNonFull(struct node *current, int key) { int i = current->n - 1; if (current->leaf) { // Find the position to insert the key while (i >= 0 && current->keys[i] > key) { current->keys[i + 1] = current->keys[i]; i--; } current->keys[i + 1] = key; current->n++; } else { // Find the correct child to insert the key while (i >= 0 && current->keys[i] > key) { i--; } i++; if (current->child[i]->n == B) { // If the child is full, split it splitChild(current, i, current->child[i]); if (current->keys[i] < key) { i++; } } insertNonFull(current->child[i], key); } } // Insert a key into the tree void insert(int key) { if (root == NULL) { root = createNode(); root->keys[0] = key; root->n = 1; } else { if (root->n == B) { // If root is full, split it struct node *newNode = createNode(); newNode->child[0] = root; root = newNode; splitChild(root, 0, newNode->child[0]); } insertNonFull(root, key); } } // Display the tree void display(struct node *root) { if (root == NULL) { return; } for (int i = 0; i < root->n; i++) { if (root->leaf == 0) { display(root->child[i]); } printf("%d ", root->keys[i]); } if (root->leaf == 0) { display(root->child[root->n]); } } // Main function int main() { insert(10); insert(20); insert(30); insert(40); printf("Fusion Tree keys: "); display(root); return 0; }
Output
Following is the output of the above code:
Fusion Tree keys: 10 20 30 40
// C++ Program to implement Fusion Tree #include <iostream> using namespace std; #define W 32 #define B 4 struct node { int keys[B]; struct node *child[B + 1]; int n; int leaf; }; struct node *root = NULL; struct node *createNode() { struct node *newNode = new node; newNode->n = 0; newNode->leaf = 1; for (int i = 0; i <= B; i++) { newNode->child[i] = NULL; } return newNode; } void splitChild(struct node *parent, int i, struct node *fullChild) { struct node *halfChild = createNode(); halfChild->leaf = fullChild->leaf; halfChild->n = B / 2; for (int j = 0; j < B / 2; j++) { halfChild->keys[j] = fullChild->keys[j + B / 2]; } if (fullChild->leaf == 0) { for (int j = 0; j < B / 2 + 1; j++) { halfChild->child[j] = fullChild->child[j + B / 2]; } } fullChild->n = B / 2; for (int j = parent->n; j > i; j--) { parent->child[j + 1] = parent->child[j]; } parent->child[i + 1] = halfChild; for (int j = parent->n - 1; j >= i; j--) { parent->keys[j + 1] = parent->keys[j]; } parent->keys[i] = fullChild->keys[B / 2]; parent->n++; } void insertNonFull(struct node *current, int key) { int i = current->n - 1; if (current->leaf) { while (i >= 0 && current->keys[i] > key) { current->keys[i + 1] = current->keys[i]; i--; } current->keys[i + 1] = key; current->n++; } else { while (i >= 0 && current->keys[i] > key) { i--; } i++; if (current->child[i]->n == B) { splitChild(current, i, current->child[i]); if (current->keys[i] < key) { i++; } } insertNonFull(current->child[i], key); } } void insert(int key) { if (root == NULL) { root = createNode(); root->keys[0] = key; root->n = 1; } else { if (root->n == B) { struct node *newNode = createNode(); newNode->child[0] = root; root = newNode; splitChild(root, 0, newNode->child[0]); } insertNonFull(root, key); } } void display(struct node *root) { if (root == NULL) { return; } for (int i = 0; i < root->n; i++) { if (root->leaf == 0) { display(root->child[i]); } cout << root->keys[i] << " "; } if (root->leaf == 0) { display(root->child[root->n]); } } int main() { insert(10); insert(20); insert(30); insert(40); cout << "Fusion Tree keys: "; display(root); return 0; }
Output
Following is the output of the above code:
Fusion Tree keys: 10 20 30 40
// Java Program to implement Fusion Tree public class Main { static final int W = 32; static final int B = 4; static class Node { int keys[] = new int[B]; Node child[] = new Node[B + 1]; int n; int leaf; } static Node root = null; static Node createNode() { Node newNode = new Node(); newNode.n = 0; newNode.leaf = 1; return newNode; } static void splitChild(Node parent, int i, Node fullChild) { Node halfChild = createNode(); halfChild.leaf = fullChild.leaf; halfChild.n = B / 2; // Move the second half of the keys to the new halfChild node for (int j = 0; j < B / 2; j++) { halfChild.keys[j] = fullChild.keys[j + B / 2]; } // Move the child pointers of fullChild to halfChild if (fullChild.leaf == 0) { for (int j = 0; j < B / 2 + 1; j++) { halfChild.child[j] = fullChild.child[j + B / 2]; } } // Update the number of keys in the fullChild node fullChild.n = B / 2; // Move the child pointers in the parent node for (int j = parent.n; j > i; j--) { parent.child[j + 1] = parent.child[j]; } parent.child[i + 1] = halfChild; // Move the middle key from fullChild to the parent node for (int j = parent.n - 1; j >= i; j--) { parent.keys[j + 1] = parent.keys[j]; } parent.keys[i] = fullChild.keys[B / 2]; parent.n++; } static void insertNonFull(Node current, int key) { int i = current.n - 1; // If the node is a leaf, insert the key if (current.leaf == 1) { while (i >= 0 && current.keys[i] > key) { current.keys[i + 1] = current.keys[i]; i--; } current.keys[i + 1] = key; current.n++; } else { // If the node is not a leaf, find the correct child and recurse while (i >= 0 && current.keys[i] > key) { i--; } i++; // If the child is full, split it if (current.child[i].n == B) { splitChild(current, i, current.child[i]); if (current.keys[i] < key) { i++; } } insertNonFull(current.child[i], key); } } static void insert(int key) { if (root == null) { root = createNode(); root.keys[0] = key; root.n = 1; } else { if (root.n == B) { Node newNode = createNode(); newNode.child[0] = root; root = newNode; splitChild(root, 0, newNode.child[0]); } insertNonFull(root, key); } } static void display(Node root) { if (root == null) { return; } // Print the keys in the current node for (int i = 0; i < root.n; i++) { if (root.leaf == 0) { display(root.child[i]); } System.out.print(root.keys[i] + " "); } // If the current node is not a leaf, display the children if (root.leaf == 0) { display(root.child[root.n]); } } public static void main(String[] args) { insert(10); insert(20); insert(30); insert(40); System.out.print("Fusion Tree keys: "); display(root); } }
Output
Following is the output of the above code:
Fusion Tree keys: 10 20 30 40
# Python Program to implement Fusion Tree W = 32 # Word size B = 4 # Branching factor class Node: def __init__(self): self.keys = [0] * B # Keys array self.child = [None] * (B + 1) # Child pointers array self.n = 0 # Number of keys self.leaf = 1 # Flag if leaf node root = None # Create a new node def createNode(): newNode = Node() newNode.n = 0 newNode.leaf = 1 return newNode # Split a full child node def splitChild(parent, i, fullChild): halfChild = createNode() halfChild.leaf = fullChild.leaf halfChild.n = B // 2 # Move half keys # Move second half of keys to halfChild for j in range(B // 2, B): halfChild.keys[j - B // 2] = fullChild.keys[j] # Move children if not leaf if not fullChild.leaf: for j in range(B // 2 + 1): halfChild.child[j] = fullChild.child[j + B // 2] fullChild.n = B // 2 # Update fullChild keys count # Shift parent's children and keys for j in range(parent.n, i, -1): parent.child[j + 1] = parent.child[j] parent.child[i + 1] = halfChild # Move parent's keys for j in range(parent.n - 1, i - 1, -1): parent.keys[j + 1] = parent.keys[j] parent.keys[i] = fullChild.keys[B // 2] parent.n += 1 # Insert into non-full node def insertNonFull(current, key): i = current.n - 1 if current.leaf: # Insert key into leaf node while i >= 0 and current.keys[i] > key: current.keys[i + 1] = current.keys[i] i -= 1 current.keys[i + 1] = key current.n += 1 else: # Find appropriate child while i >= 0 and current.keys[i] > key: i -= 1 i += 1 if current.child[i].n == B: splitChild(current, i, current.child[i]) # Split full child if current.keys[i] < key: i += 1 insertNonFull(current.child[i], key) # Insert a key into the tree def insert(key): global root if root is None: root = createNode() root.keys[0] = key root.n = 1 else: if root.n == B: newNode = createNode() newNode.child[0] = root root = newNode splitChild(root, 0, newNode.child[0]) insertNonFull(root, key) # Display the tree keys def display(root): for i in range(root.n): if root.leaf == 0: display(root.child[i]) print(root.keys[i], end=" ") if root.leaf == 0: display(root.child[root.n]) # Insert test values insert(10) insert(20) insert(30) insert(40) # Display Fusion Tree print("Fusion Tree keys:", end=" ") display(root)
Output
Following is the output of the above code:
Fusion Tree keys: 10 20 30 40
Search and Delete Operations in Fusion Tree
Search and delete operations in a fusion tree are similar to the insertion operation. You can implement these operations by modifying the above code.
Search operation is used to find the element in the tree and delete operation is used to delete the element from the tree.
Algorithm to Search and Delete Elements in Fusion Tree
Following are the steps to implement search and delete operations in a fusion tree:
2. Search the element in the tree 3. If the element is found, delete the element from the tree 4. If the element is not found, display the message "Element not found"
Code to Search and Delete Elements in Fusion Tree
Now let's see how we can implement search and delete operations in a fusion tree in C, C++, Java and Python:
#include <stdio.h> #include <stdlib.h> #define W 32 #define B 4 // The branching factor (maximum number of keys per node) struct node { int keys[B]; // Array to store keys struct node *child[B + 1]; // Array of child pointers int n; // Number of keys in the node int leaf; // Flag to check if it's a leaf node }; struct node *root = NULL; // Create a new node struct node* createNode() { struct node *newNode = (struct node*)malloc(sizeof(struct node)); newNode->n = 0; newNode->leaf = 1; return newNode; } // Split the child node void splitChild(struct node *parent, int i, struct node *fullChild) { struct node *halfChild = createNode(); halfChild->leaf = fullChild->leaf; halfChild->n = B / 2; // Move the second half of the keys to the new child for (int j = 0; j < B / 2; j++) { halfChild->keys[j] = fullChild->keys[j + B / 2]; } // Move the second half of the children if (!fullChild->leaf) { for (int j = 0; j < B / 2 + 1; j++) { halfChild->child[j] = fullChild->child[j + B / 2]; } } fullChild->n = B / 2; // Move the children of the parent to make space for (int j = parent->n; j > i; j--) { parent->child[j + 1] = parent->child[j]; } // Make room for the new child parent->child[i + 1] = halfChild; // Move the keys of the parent to make space for (int j = parent->n - 1; j >= i; j--) { parent->keys[j + 1] = parent->keys[j]; } // Move the middle key up to the parent parent->keys[i] = fullChild->keys[B / 2]; parent->n++; } // Insert the key into a non-full node void insertNonFull(struct node *node, int key) { int i = node->n - 1; if (node->leaf) { // Find the position to insert the key while (i >= 0 && node->keys[i] > key) { node->keys[i + 1] = node->keys[i]; i--; } node->keys[i + 1] = key; node->n++; } else { // Find the correct child to insert the key while (i >= 0 && node->keys[i] > key) { i--; } i++; if (node->child[i]->n == B) { splitChild(node, i, node->child[i]); if (node->keys[i] < key) { i++; } } insertNonFull(node->child[i], key); } } // Insert a key into the tree void insert(int key) { if (root == NULL) { root = createNode(); root->keys[0] = key; root->n = 1; } else { if (root->n == B) { struct node *newRoot = createNode(); newRoot->child[0] = root; root = newRoot; splitChild(root, 0, newRoot->child[0]); } insertNonFull(root, key); } } // Display the keys in the tree void display(struct node *root) { if (root != NULL) { for (int i = 0; i < root->n; i++) { if (!root->leaf) { display(root->child[i]); } printf("%d ", root->keys[i]); } if (!root->leaf) { display(root->child[root->n]); } } } // Search for a key in the tree void search(struct node *root, int key) { if (root != NULL) { for (int i = 0; i < root->n; i++) { if (root->keys[i] == key) { printf("Element %d found\n", key); return; } } for (int i = 0; i < root->n; i++) { if (key < root->keys[i]) { search(root->child[i], key); return; } } search(root->child[root->n], key); } } // Delete a key from the tree void delete(struct node *root, int key) { if (root != NULL) { int i; for (i = 0; i < root->n; i++) { if (root->keys[i] == key) { break; } } if (i < root->n) { for (int j = i; j < root->n - 1; j++) { root->keys[j] = root->keys[j + 1]; } root->n--; printf("Element %d deleted\n", key); } else { printf("Element %d not found\n", key); } } } int main() { insert(10); insert(20); insert(30); insert(40); printf("Fusion Tree keys: "); display(root); printf("\n"); search(root, 20); delete(root, 20); search(root, 20); printf("Fusion Tree keys after deletion: "); display(root); printf("\n"); return 0; }
Output
Following is the output of the above code:
Fusion Tree keys: 10 20 30 40 Element 20 found Element 20 deleted Element 20 not found Fusion Tree keys after deletion: 10 30 40
//C++ Program Search and Delete Elements in Fusion Tree #include <iostream> using namespace std; #define W 32 #define B 4 // Maximum number of keys in a node (B+1 children) struct node{ int keys[W]; struct node *child[W+1]; int n; int leaf; }; struct node *root = NULL; struct node *createNode(){ struct node *newNode = new node; newNode->n = 0; newNode->leaf = 1; return newNode; } // Split a full child node void splitChild(struct node *parent, int i, struct node *fullChild){ struct node *halfChild = createNode(); halfChild->leaf = fullChild->leaf; halfChild->n = B / 2; // Move second half of keys to the new child for (int j = 0; j < B / 2; j++){ halfChild->keys[j] = fullChild->keys[j + B / 2]; } if (!fullChild->leaf){ // Move second half of children to the new child for (int j = 0; j < B / 2 + 1; j++){ halfChild->child[j] = fullChild->child[j + B / 2]; } } fullChild->n = B / 2; // Move children of parent to make space for (int j = parent->n; j > i; j--){ parent->child[j + 1] = parent->child[j]; } parent->child[i + 1] = halfChild; // Move keys in parent to make space for (int j = parent->n - 1; j >= i; j--){ parent->keys[j + 1] = parent->keys[j]; } parent->keys[i] = fullChild->keys[B / 2]; parent->n++; } // Insert key into a non-full node void insertNonFull(struct node *node, int key){ int i = node->n - 1; if (node->leaf){ // Find position to insert the key while (i >= 0 && node->keys[i] > key){ node->keys[i + 1] = node->keys[i]; i--; } node->keys[i + 1] = key; node->n++; } else{ // Find child to insert into while (i >= 0 && node->keys[i] > key){ i--; } i++; if (node->child[i]->n == B){ splitChild(node, i, node->child[i]); if (node->keys[i] < key){ i++; } } insertNonFull(node->child[i], key); } } // Insert key into the tree void insert(int key){ if (root == NULL){ root = createNode(); root->keys[0] = key; root->n = 1; } else{ if (root->n == B){ struct node *newNode = createNode(); newNode->child[0] = root; root = newNode; splitChild(root, 0, newNode->child[0]); } insertNonFull(root, key); } } // Display the keys in the tree void display(struct node *root){ if (root != NULL){ for (int i = 0; i < root->n; i++){ if (root->leaf == 0){ display(root->child[i]); } cout << root->keys[i] << " "; } if (root->leaf == 0){ display(root->child[root->n]); } cout << endl; } } // Search the tree for a key void search(int key){ for (int i = 0; i < root->n; i++){ if (root->keys[i] == key){ cout << "Element " << key << "found " <<endl; return; } } cout << "Element " << key << " not found " << endl; } // Delete the element from the tree void deleteElement(int key){ for (int i = 0; i < root->n; i++){ if (root->keys[i] == key){ for (int j = i; j < root->n - 1; j++){ root->keys[j] = root->keys[j + 1]; } root->n--; cout << "Element " << key << " deleted " << endl; return; } } cout << "Element " << key << " not found " << endl; } int main(){ insert(10); insert(20); insert(30); insert(40); cout << "Fusion Tree keys: "; display(root); search(20); deleteElement(20); search(20); cout << "Fusion Tree after deletion: "; display(root); return 0; }
Output
Following is the output of the above code:
Fusion Tree keys: 10 20 30 40 Element found 20 Element deleted 20 Element not found 20 Fusion Tree after deletion: 10 30 40
//Java Program Search and Delete Elements in Fusion Tree public class Main{ static final int W = 32; static final int B = 4; // Maximum number of keys in a node (B+1 children) static class Node{ int keys[] = new int[W]; Node child[] = new Node[W + 1]; int n; int leaf; } static Node root = null; static Node createNode(){ Node newNode = new Node(); newNode.n = 0; newNode.leaf = 1; return newNode; } static void splitChild(Node parent, int i, Node fullChild){ Node halfChild = createNode(); halfChild.leaf = fullChild.leaf; halfChild.n = B / 2; // Move second half of keys to the new child for (int j = 0; j < B / 2; j++){ halfChild.keys[j] = fullChild.keys[j + B / 2]; } if (fullChild.leaf == 0){ // Move second half of children to the new child for (int j = 0; j < B / 2 + 1; j++){ halfChild.child[j] = fullChild.child[j + B / 2]; } } fullChild.n = B / 2; // Move children of parent to make space for (int j = parent.n; j > i; j--){ parent.child[j + 1] = parent.child[j]; } parent.child[i + 1] = halfChild; // Move keys in parent to make space for (int j = parent.n - 1; j >= i; j--){ parent.keys[j + 1] = parent.keys[j]; } parent.keys[i] = fullChild.keys[B / 2]; parent.n++; } static void insertNonFull(Node node, int key){ int i = node.n - 1; if (node.leaf == 1){ // Find the right position for the key while (i >= 0 && node.keys[i] > key){ node.keys[i + 1] = node.keys[i]; i--; } node.keys[i + 1] = key; node.n++; } else{ // Find the child to insert into while (i >= 0 && node.keys[i] > key){ i--; } i++; if (node.child[i].n == B){ splitChild(node, i, node.child[i]); if (node.keys[i] < key){ i++; } } insertNonFull(node.child[i], key); } } static void insert(int key){ if (root == null){ root = createNode(); root.keys[0] = key; root.n = 1; } else{ if (root.n == B){ Node newNode = createNode(); newNode.child[0] = root; root = newNode; splitChild(root, 0, newNode.child[0]); } insertNonFull(root, key); } } static void display(Node node){ if (node != null){ for (int i = 0; i < node.n; i++){ if (node.leaf == 0){ display(node.child[i]); } System.out.print(node.keys[i] + " "); } if (node.leaf == 0){ display(node.child[node.n]); } } } static void search(int key){ for (int i = 0; i < root.n; i++){ if (root.keys[i] == key){ System.out.println("Element " + key +" found "); return; } } System.out.println("Element " + key + " not found "); } static void delete(int key){ for (int i = 0; i < root.n; i++){ if (root.keys[i] == key){ for (int j = i; j < root.n - 1; j++){ root.keys[j] = root.keys[j + 1]; } root.n--; System.out.println("Element " + key + " deleted "); return; } } System.out.println("Element " + key + " not found "); } public static void main(String[] args){ insert(10); insert(20); insert(30); insert(40); System.out.print("Tree after insertions: "); display(root); System.out.println(); search(20); delete(20); search(20); System.out.print("Tree after deletion: "); display(root); } }
Output
Following is the output of the above code:
Tree after insertions: 10 20 30 40 Element 20 found Element 20 deleted Element 20 not found Tree after deletion: 10 30 40
# Python Program Search and Delete Elements in Fusion Tree W = 32 B = 4 # Maximum number of keys in a node (B+1 children) class Node: def __init__(self): self.keys = [0] * W self.child = [None] * (W + 1) self.n = 0 self.leaf = 1 root = None def createNode(): newNode = Node() newNode.n = 0 newNode.leaf = 1 return newNode def splitChild(parent, i, fullChild): halfChild = createNode() halfChild.leaf = fullChild.leaf halfChild.n = B // 2 # Move second half of keys to the new child for j in range(B // 2): halfChild.keys[j] = fullChild.keys[j + B // 2] if not fullChild.leaf: # Move second half of children for j in range(B // 2 + 1): halfChild.child[j] = fullChild.child[j + B // 2] fullChild.n = B // 2 # Move children of parent to make space for j in range(parent.n, i, -1): parent.child[j + 1] = parent.child[j] parent.child[i + 1] = halfChild # Move keys in parent to make space for j in range(parent.n - 1, i - 1, -1): parent.keys[j + 1] = parent.keys[j] parent.keys[i] = fullChild.keys[B // 2] parent.n += 1 def insertNonFull(node, key): i = node.n - 1 if node.leaf: # Find the right position for the key while i >= 0 and node.keys[i] > key: node.keys[i + 1] = node.keys[i] i -= 1 node.keys[i + 1] = key node.n += 1 else: # Find the child to insert into while i >= 0 and node.keys[i] > key: i -= 1 i += 1 if node.child[i].n == B: splitChild(node, i, node.child[i]) if node.keys[i] < key: i += 1 insertNonFull(node.child[i], key) def insert(key): global root if root is None: root = createNode() root.keys[0] = key root.n = 1 else: if root.n == B: newNode = createNode() newNode.child[0] = root root = newNode splitChild(root, 0, newNode.child[0]) insertNonFull(root, key) def display(root): if root: for i in range(root.n): if root.leaf == 0: display(root.child[i]) print(root.keys[i], end=" ") if root.leaf == 0: display(root.child[root.n]) def search(key): global root # Search the element in the tree for i in range(root.n): if root.keys[i] == key: print("Element", key, "found ") return print("Element", key, "not found ") def delete(key): global root # Delete the element from the tree for i in range(root.n): if root.keys[i] == key: for j in range(i, root.n - 1): root.keys[j] = root.keys[j + 1] root.n -= 1 print("Element",key, "deleted " ) return print("Element",key, "not found " ) # Inserting keys insert(10) insert(20) insert(30) insert(40) # Display tree print("Fusion Tree keys: ") display(root) # Search and delete operations search(20) delete(20) search(20) # Display tree after deletion print("Fusion Tree keys after deletion: ") display(root)
Output
Following is the output of the above code:
Fusion Tree keys: 10 20 30 40 Element 20 found Element 20 deleted Element 20 not found Fusion Tree keys after deletion: 10 30 40
Time Complexity of Fusion Tree
Time complexity of the operations on a fusion tree is as follows:
- Insertion: O(logWn)
- Deletion: O(logWn)
- Searching: O(logWn)
Here, n is the number of elements in the tree and W is the word size.
Applications of Fusion Tree
Fusion trees are used in various applications where we need to store a large number of elements and perform operations like insertion, deletion, and searching efficiently. Some of the applications of fusion trees are:
- Database indexing
- File systems
- Geographic information systems
- Network routing
- Computer graphics
These are some of the applications where fusion trees are used to store and manage large datasets efficiently.
Conclusion
In this chapter, we learned about fusion trees, a data structure that is used to store a large number of elements efficiently. We discussed the structure of a fusion tree, its operations like insertion, deletion, and searching, and the time complexity of these operations. We also saw how to implement fusion trees in C, C++, Java, and Python and perform search and delete operations on them. We also discussed the applications of fusion trees in various fields.