Advance Data Structures
Advance Data Structures
/
i
|
r
/
t
|
h
|
e
|
r
|
e
root
\ \
a
b
|
|
n
y
| \ |
s y e
|
w
|
e
|
r
{
// Input keys (use only 'a' through 'z' and lower case)
char keys[][8] = {"the", "a", "there", "answer", "any", "by", "bye", "their"};
trie_t trie;
char output[][32] = {"Not present in trie", "Present in trie"};
initialize(&trie);
// Construct trie
for(int i = 0; i < ARRAY_SIZE(keys); i++)
{
insert(&trie, keys[i]);
}
// Search for different keys
printf("%s --- %s\n", "the", output[search(&trie, "the")] );
printf("%s --- %s\n", "these", output[search(&trie, "these")] );
printf("%s --- %s\n", "their", output[search(&trie, "their")] );
printf("%s --- %s\n", "thaw", output[search(&trie, "thaw")] );
return 0;
}
Source
http://www.geeksforgeeks.org/trie-insert-and-search/
Trie | (Delete)
In the previous post on trie we have described how to insert and search
a node in trie. Here is an algorithm how to delete a node from trie.
During delete operation we delete the key in bottom up manner using
recursion. The following are possible conditions when deleting key from
trie,
1
Key may not be there in trie. Delete operation should not modify
trie.
2
3
4
Key present as unique key (no part of key contains another key
(prefix), nor the key itself is prefix of another key in trie). Delete all
the nodes.
Key is prefix key of another long key in trie. Unmark the leaf node.
Key present in trie, having atleast one other key as prefix key.
Delete nodes from end of key until first leaf node of longest prefix
key.
trie_node_t *getNode(void)
{
trie_node_t *pNode = NULL;
pNode = (trie_node_t *)malloc(sizeof(trie_node_t));
if( pNode )
{
int i;
pNode->value = 0;
for(i = 0; i < ALPHABET_SIZE; i++)
{
pNode->children[i] = NULL;
}
}
return pNode;
}
void initialize(trie_t *pTrie)
{
pTrie->root = getNode();
pTrie->count = 0;
}
void insert(trie_t *pTrie, char key[])
{
int level;
int length = strlen(key);
int index;
trie_node_t *pCrawl;
pTrie->count++;
pCrawl = pTrie->root;
for( level = 0; level < length; level++ )
{
index = INDEX(key[level]);
if( pCrawl->children[index] )
{
// Skip current node
pCrawl = pCrawl->children[index];
}
else
{
}
bool deleteHelper(trie_node_t *pNode, char key[], int level, int len)
{
if( pNode )
{
// Base case
if( level == len )
{
if( pNode->value )
{
// Unmark leaf node
pNode->value = 0;
// If empty, node to be deleted
if( isItFreeNode(pNode) )
{
return true;
}
return false;
}
}
else // Recursive case
{
int index = INDEX(key[level]);
if( deleteHelper(pNode->children[index], key, level+1, len) )
{
// last node marked, delete it
FREE(pNode->children[index]);
// recursively climb up, and delete eligible nodes
return ( !leafNode(pNode) && isItFreeNode(pNode) );
}
}
}
return false;
}
void deleteKey(trie_t *pTrie, char key[])
{
int len = strlen(key);
if( len > 0 )
{
deleteHelper(pTrie->root, key, 0, len);
}
}
int main()
{
char keys[][8] = {"she", "sells", "sea", "shore", "the", "by", "sheer"};
trie_t trie;
initialize(&trie);
for(int i = 0; i < ARRAY_SIZE(keys); i++)
{
insert(&trie, keys[i]);
}
deleteKey(&trie, keys[0]);
printf("%s %s\n", "she", search(&trie, "she") ? "Present in trie" : "Not
present in trie");
return 0;
}
Source
http://www.geeksforgeeks.org/trie-delete/
Category: Trees Tags: Advance Data Structures
Post navigation
Understanding volatile qualifier in C Find a Fixed Point in a given
array
Writing code in comment? Please use code.geeksforgeeks.org,
generate link and share the link here.
C implementation
Following is the C implementation for AVL Tree Insertion. The following
C implementation uses the recursive BST insert to insert a new node.
In the recursive BST insert, after insertion, we get pointers to all
}
/* return the (unchanged) node pointer */
return node;
}
// A utility function to print preorder traversal of the tree.
// The function also prints height of every node
void preOrder(struct node *root)
{
if(root != NULL)
{
printf("%d ", root->key);
preOrder(root->left);
preOrder(root->right);
}
}
/* Drier program to test above function*/
int main()
{
struct node *root = NULL;
/* Constructing tree given in the above figure */
root = insert(root, 10);
root = insert(root, 20);
root = insert(root, 30);
root = insert(root, 40);
root = insert(root, 50);
root = insert(root, 25);
/* The constructed AVL Tree would be
30
/ \
20 40
/ \
\
10 25 50
*/
printf("Pre order traversal of the constructed AVL tree is \n");
preOrder(root);
return 0;
}
Output:
Pre order traversal of the constructed AVL tree is
30 20 10 25 40 50
Time Complexity: The rotation operations (left and right rotate) take
constant time as only few pointers are being changed there. Updating
the height and getting the balance factor also take constant time. So
the time complexity of AVL insert remains same as BST insert which is
O(h) where h is height of the tree. Since AVL tree is balanced, the
height is O(Logn). So time complexity of AVL insert is O(Logn).
The AVL tree and other self balancing search trees like Red Black are
useful to get all basic operations done in O(Logn) time. The AVL trees
are more balanced compared to Red Black Trees, but they may cause
more rotations during insertion and deletion. So if your application
involves many frequent insertions and deletions, then Red Black trees
should be preferred. And if the insertions and deletions are less
frequent and search is more frequent operation, then AVL tree should
be preferred over Red Black Tree.
Following is the post for delete.
AVL Tree | Set 2 (Deletion)
Following are some previous posts that have used self-balancing search
trees.
Median in a stream of integers (running integers)
Maximum of all subarrays of size k
Count smaller elements on right side
References:
IITD Video Lecture on AVL Tree Introduction
IITD Video Lecture on AVL Tree Insertion and Deletion
Please write comments if you find anything incorrect, or you want to
share more information about the topic discussed above.
Source
http://www.geeksforgeeks.org/avl-tree-set-1-insertion/
/\
T2 T3
/\
T1 T2
*/
printf("\nPre order traversal after deletion of 10 \n");
preOrder(root);
return 0;
}
Output:
Pre
91
Pre
10
Time Complexity: The rotation operations (left and right rotate) take
constant time as only few pointers are being changed there. Updating
the height and getting the balance factor also take constant time. So
the time complexity of AVL delete remains same as BST delete which is
O(h) where h is height of the tree. Since AVL tree is balanced, the
height is O(Logn). So time complexity of AVL delete is O(Logn).
References:
IITD Video Lecture on AVL Tree Insertion and Deletion
Please write comments if you find anything incorrect, or you want to
share more information about the topic discussed above.
Source
http://www.geeksforgeeks.org/avl-tree-set-2-deletion/
Category: Trees Tags: Advance Data Structures
Post navigation
Vertical Sum in a given Binary Tree Operating Systems | Set 5
Writing code in comment? Please use code.geeksforgeeks.org,
generate link and share the link here.
.3.2 The frequency of the new word inserted is greater than the
frequency of the word stored in the head of min heap. Replace &
update the fields. Make sure to update the corresponding min heap
index of the word to be replaced in Trie with -1 as the word is no
longer in min heap.
4. Finally, Min Heap will have the k most frequent words of all words
present in given file. So we just need to print all words present in Min
Heap.
// A program to find k most frequent words in a file
#include <stdio.h>
#include <string.h>
#include <ctype.h>
# define MAX_CHARS 26
# define MAX_WORD_SIZE 30
// A Trie node
struct TrieNode
{
bool isEnd; // indicates end of word
unsigned frequency; // the number of occurrences of a word
int indexMinHeap; // the index of the word in minHeap
TrieNode* child[MAX_CHARS]; // represents 26 slots each for 'a' to 'z'.
};
// A Min Heap node
struct MinHeapNode
{
TrieNode* root; // indicates the leaf node of TRIE
unsigned frequency; // number of occurrences
char* word; // the actual word stored
};
// A Min Heap
struct MinHeap
{
unsigned capacity; // the total size a min heap
int count; // indicates the number of slots filled.
MinHeapNode* array; // represents the collection of minHeapNodes
};
// A utility function to create a new Trie node
TrieNode* newTrieNode()
{
// Allocate memory for Trie Node
TrieNode* trieNode = new TrieNode;
0
0
0
0
].
].
].
].
root->indexMinHeap = -1;
root = *root;
root->indexMinHeap = 0;
frequency = (*root)->frequency;
(*root)->frequency = 1;
}
// Insert in min heap also
insertInMinHeap( minHeap, root, dupWord );
}
}
// add a word to Trie & min heap. A wrapper over the insertUtil
void insertTrieAndHeap(const char *word, TrieNode** root, MinHeap*
minHeap)
{
insertUtil( root, minHeap, word, word );
}
// A utility function to show results, The min heap
// contains k most frequent words so far, at any time
void displayMinHeap( MinHeap* minHeap )
{
int i;
// print top K word with frequency
for( i = 0; i < minHeap->count; ++i )
{
printf( "%s : %d\n", minHeap->array[i].word,
minHeap->array[i].frequency );
}
}
// The main funtion that takes a file as input, add words to heap
// and Trie, finally shows result from heap
void printKMostFreq( FILE* fp, int k )
{
// Create a Min Heap of Size k
MinHeap* minHeap = createMinHeap( k );
// Create an empty Trie
TrieNode* root = NULL;
// A buffer to store one word at a time
char buffer[MAX_WORD_SIZE];
// Read words one by one from file. Insert the word in Trie and Min Heap
while( fscanf( fp, "%s", buffer ) != EOF )
insertTrieAndHeap(buffer, &root, minHeap);
// The Min Heap will have the k most frequent words, so print Min Heap
nodes
displayMinHeap( minHeap );
}
// Driver program to test above functions
int main()
{
int k = 5;
FILE *fp = fopen ("file.txt", "r");
if (fp == NULL)
printf ("File doesn't exist ");
else
printKMostFreq (fp, k);
return 0;
}
Output:
your : 3
well : 3
and : 4
to : 4
Geeks : 6
Source
http://www.geeksforgeeks.org/find-the-k-most-frequent-words-from-afile/
Post navigation
Dynamic Programming | Set 22 (Box Stacking Problem) Sort numbers
stored on different machines
Writing code in comment? Please use code.geeksforgeeks.org,
generate link and share the link here.
Output:
10 30 35 40 45 50 60 70 80 100
Source
http://www.geeksforgeeks.org/sort-numbers-stored-on-differentmachines/
Post navigation
Find the k most frequent words from a file Microsoft Interview | Set 7
ReferencePage(
ReferencePage(
ReferencePage(
ReferencePage(
ReferencePage(
ReferencePage(
q,
q,
q,
q,
q,
q,
hash,
hash,
hash,
hash,
hash,
hash,
1);
2);
3);
1);
4);
5);
Output:
5413
Source
http://www.geeksforgeeks.org/implement-lru-cache/
Category: Linked Lists Tags: Advance Data Structures, Advanced Data
Structures, Queue
Post navigation
Microsoft Interview | Set 7 Median of two sorted arrays of different
sizes
Writing code in comment? Please use code.geeksforgeeks.org,
generate link and share the link here.
Input:
{0, 1, 0, 0,
{1, 0, 1,
{0, 1, 0,
{1, 1, 1,
Output:
01001
10110
11100
1}
1, 0}
0, 1}
0, 0}
Method 1 (Simple)
A simple approach is to check each row with all processed rows. Print
the first row. Now, starting from the second row, for each row, compare
the row with already processed rows. If the row matches with any of
the processed rows, dont print it. If the current row doesnt match with
any row, print it.
Time complexity: O( ROW^2 x COL )
Auxiliary Space: O( 1 )
Method 2 (Use Binary Search Tree)
Find the decimal equivalent of each row and insert it into BST. Each
node of the BST will contain two fields, one field for the decimal value,
other for row number. Do not insert a node if it is duplicated. Finally,
traverse the BST and print the corresponding rows.
Time complexity: O( ROW x COL + ROW x log( ROW ) )
Auxiliary Space: O( ROW )
This method will lead to Integer Overflow if number of columns is large.
Method 3 (Use Trie data structure)
Since the matrix is boolean, a variant of Trie data structure can be
used where each node will be having two children one for 0 and other
for 1. Insert each row in the Trie. If the row is already there, dont print
the row. If row is not there in Trie, insert it in Trie and print it.
Below is C implementation of method 3.
//Given a binary matrix of M X N of integers, you need to return only unique
rows of binary array
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#define ROW 4
#define COL 5
// A Trie node
typedef struct Node
{
bool isEndOfCol;
struct Node *child[2]; // Only two children needed for 0 and 1
} Node;
}
// The main function that prints all unique rows in a
// given matrix.
void findUniqueRows( int (*M)[COL] )
{
Node* root = NULL; // create an empty Trie
int i;
// Iterate through all rows
for ( i = 0; i < ROW; ++i )
// insert row to TRIE
if ( insert(&root, M, i, 0) )
// unique row found, print it
printRow( M, i );
}
// Driver program to test above functions
int main()
{
int M[ROW][COL] = {{0, 1, 0, 0, 1},
{1, 0, 1, 1, 0},
{0, 1, 0, 0, 1},
{1, 0, 1, 0, 0}
};
findUniqueRows( M );
return 0;
}
Source
http://www.geeksforgeeks.org/print-unique-rows/
Category: Arrays Tags: Advance Data Structures, Advanced Data
Structures
Post navigation
Median of two sorted arrays of different sizes Microsoft Interview |
Set 8
Writing code in comment? Please use code.geeksforgeeks.org,
generate link and share the link here.
#define NO_OF_CHARS 26
// Structure to represent list node for indexes of words in
// the given sequence. The list nodes are used to connect
// anagrams at leaf nodes of Trie
struct IndexNode
{
int index;
struct IndexNode* next;
};
// Structure to represent a Trie Node
struct TrieNode
{
bool isEnd; // indicates end of word
struct TrieNode* child[NO_OF_CHARS]; // 26 slots each for 'a' to 'z'
struct IndexNode* head; // head of the index list
};
if (*root == NULL)
*root = newTrieNode();
if (*word != '\0')
insert( &( (*root)->child[tolower(*word) - 'a'] ), word+1, index );
else // If end of the word reached
{
// Insert index of this word to end of index linked list
if ((*root)->isEnd)
{
IndexNode* pCrawl = (*root)->head;
while( pCrawl->next )
pCrawl = pCrawl->next;
pCrawl->next = newIndexNode(index);
}
else // If Index list is empty
{
(*root)->isEnd = 1;
(*root)->head = newIndexNode(index);
}
}
}
// This function traverses the built trie. When a leaf node is reached,
// all words connected at that leaf node are anagrams. So it traverses
// the list at leaf node and uses stored index to print original words
void printAnagramsUtil(struct TrieNode* root, char *wordArr[])
{
if (root == NULL)
return;
// If a lead node is reached, print all anagrams using the indexes
// stored in index linked list
if (root->isEnd)
{
// traverse the list
IndexNode* pCrawl = root->head;
while (pCrawl != NULL)
{
printf( "%s \n", wordArr[ pCrawl->index ] );
pCrawl = pCrawl->next;
}
}
for (int i = 0; i < NO_OF_CHARS; ++i)
printAnagramsUtil(root->child[i], wordArr);
}
// The main function that prints all anagrams together. wordArr[] is input
// sequence of words.
Output:
cat
tac
act
dog
god
gdo
Source
http://www.geeksforgeeks.org/given-a-sequence-of-words-print-allanagrams-together-set-2/
Category: Strings Tags: Advance Data Structures
Post navigation
Given a sequence of words, print all anagrams together | Set 1
[TopTalent.in] Interview with Arun Dobriyal who landed a job at
Facebook, Palo Alto
Writing code in comment? Please use code.geeksforgeeks.org,
generate link and share the link here.
Please note that above steps are just to manually create a Suffix Tree.
We will be discussing actual algorithm and implementation in a
separate post.
How to search a pattern in the built suffix tree?
We have discussed above how to build a Suffix Tree which is needed
as a preprocessing step in pattern searching. Following are abstract
steps to search a pattern in the built Suffix Tree.
1) Starting from the first character of the pattern and root of Suffix
Tree, do following for every character.
..a) For the current character of pattern, if there is an edge from the
current node of suffix tree, follow the edge.
..b) If there is no edge, print pattern doesnt exist in text and
return.
2) If all characters of pattern have been processed, i.e., there is a path
from root for characters of the given pattern, then print Pattern
found.
Let us consider the example pattern as nan to see the searching
process. Following diagram shows the path followed for searching
nan or nana.
Source
http://www.geeksforgeeks.org/pattern-searching-set-8-suffix-treeintroduction/
One of the advantage of using ternary search trees over tries is that
ternary search trees are a more space efficient (involve only three
pointers per node as compared to 26 in standard tries). Further,
ternary search trees can be used any time a hashtable would be used
to store strings.
Tries are suitable when there is a proper distribution of words over the
alphabets so that spaces are utilized most efficiently. Otherwise ternary
search trees are better. Ternary search trees are efficient to use(in
terms of space) when the strings to be stored share a common prefix.
Applications of ternary search trees:
1. Ternary search trees are efficient for queries like Given a word, find
the next word in dictionary(near-neighbor lookups) or Find all
telephone numbers starting with 9342 or typing few starting
characters in a web browser displays all website names with this
prefix(Auto complete feature).
2. Used in spell checks: Ternary search trees can be used as a
dictionary to store all the words. Once the word is typed in an editor,
the word can be parallely searched in the ternary search tree to check
for correct spelling.
Implementation:
Following is C implementation of ternary search tree. The operations
implemented are, search, insert and traversal.
// C program to demonstrate Ternary Search Tree (TST) insert, travese
// and search operations
#include <stdio.h>
#include <stdlib.h>
#define MAX 50
// A node of ternary search tree
struct Node
{
char data;
// True if this character is last character of one of the words
unsigned isEndOfString: 1;
struct Node *left, *eq, *right;
};
// A utility function to create a new ternary search tree node
struct Node* newNode(char data)
{
struct Node* temp = (struct Node*) malloc(sizeof( struct Node ));
temp->data = data;
temp->isEndOfString = 0;
temp->left = temp->eq = temp->right = NULL;
return temp;
}
// Function to insert a new word in a Ternary Search Tree
void insert(struct Node** root, char *word)
{
// Base Case: Tree is empty
if (!(*root))
*root = newNode(*word);
// If current character of word is smaller than root's character,
// then insert this word in left subtree of root
if ((*word) < (*root)->data)
insert(&( (*root)->left ), word);
// If current character of word is greate than root's character,
// then insert this word in right subtree of root
else if ((*word) > (*root)->data)
insert(&( (*root)->right ), word);
// If current character of word is same as root's character,
else
{
if (*(word+1))
insert(&( (*root)->eq ), word+1);
// the last character of the word
else
(*root)->isEndOfString = 1;
}
}
// A recursive function to traverse Ternary Search Tree
void traverseTSTUtil(struct Node* root, char* buffer, int depth)
{
if (root)
{
// First traverse the left subtree
traverseTSTUtil(root->left, buffer, depth);
// Store the character of this node
buffer[depth] = root->data;
if (root->isEndOfString)
{
buffer[depth+1] = '\0';
printf( "%s\n", buffer);
}
// Traverse the subtree using equal pointer (middle subtree)
traverseTSTUtil(root->eq, buffer, depth + 1);
// Finally Traverse the right subtree
traverseTSTUtil(root->right, buffer, depth);
}
}
// The main function to traverse a Ternary Search Tree.
// It mainly uses traverseTSTUtil()
void traverseTST(struct Node* root)
{
char buffer[MAX];
traverseTSTUtil(root, buffer, 0);
}
// Function to search a given word in TST
int searchTST(struct Node *root, char *word)
{
if (!root)
return 0;
if (*word < (root)->data)
return searchTST(root->left, word);
else if (*word > (root)->data)
return searchTST(root->right, word);
else
{
if (*(word+1) == '\0')
return root->isEndOfString;
return searchTST(root->eq, word+1);
}
}
// Driver program to test above functions
int main()
{
struct Node *root = NULL;
insert(&root,
insert(&root,
insert(&root,
insert(&root,
"cat");
"cats");
"up");
"bug");
Output:
Following is traversal of ternary search tree
bug
cat
cats
up
Following are search results for cats, bu and cat respectively
Found
Not Found
Found
Reference:
http://en.wikipedia.org/wiki/Ternary_search_tree
This article is compiled by Aashish Barnwaland reviewed by
GeeksforGeeks team. Please write comments if you find anything
incorrect, or you want to share more information about the topic
discussed above.
Source
http://www.geeksforgeeks.org/ternary-search-tree/
Category: Trees Tags: Advance Data Structures, Advanced Data
Structures
Post navigation
[TopTalent.in] Exclusive Interview with Ravi Kiran from BITS, Pilani
who got placed in Google, Microsoft and Facebook Amazon Interview |
Set 17
Writing code in comment? Please use code.geeksforgeeks.org,
generate link and share the link here.
What if the number of query and updates are equal? Can we perform
both the operations in O(log n) time once given the array? We
can use a Segment Tree to do both operations in O(Logn) time.
Representation of Segment trees
1. Leaf Nodes are the elements of the input array.
2. Each internal node represents some merging of the leaf nodes. The
merging may be different for different problems. For this problem,
merging is sum of leaves under a node.
An array representation of tree is used to represent Segment Trees. For
each node at index i, the left child is at index 2*i+1, right child at
2*i+2 and the parent is at
Update a value
Like tree construction and query operations, update can also be done
recursively. We are given an index which needs to updated. Let dif be
the value to be added. We start from root of the segment tree, and add
dif to all nodes which have given index in their range. If a node
doesnt have given index in its range, we dont make any changes to
that node.
Implementation:
Following is implementation of segment tree. The program implements
construction of segment tree for any given array. It also implements
query and update operations.
// Program to show segment tree operations like construction, query and
update
#include <stdio.h>
#include <math.h>
// A utility function to get the middle index from corner indexes.
int getMid(int s, int e) { return s + (e -s)/2; }
/* A recursive function to get the sum of values in given range of the array.
The following are parameters for this function.
st
si
{
printf("Invalid Input");
return;
}
// Get the difference between new value and old value
int diff = new_val - arr[i];
// Update the value in array
arr[i] = new_val;
// Update the values of nodes in segment tree
updateValueUtil(st, 0, n-1, i, diff, 0);
}
// Return sum of elements in range from index qs (quey start) to
// qe (query end). It mainly uses getSumUtil()
int getSum(int *st, int n, int qs, int qe)
{
// Check for erroneous input values
if (qs < 0 || qe > n-1 || qs > qe)
{
printf("Invalid Input");
return -1;
}
return getSumUtil(st, 0, n-1, qs, qe, 0);
}
// A recursive function that constructs Segment Tree for array[ss..se].
// si is index of current node in segment tree st
int constructSTUtil(int arr[], int ss, int se, int *st, int si)
{
// If there is one element in array, store it in current node of
// segment tree and return
if (ss == se)
{
st[si] = arr[ss];
return arr[ss];
}
// If there are more than one elements, then recur for left and
// right subtrees and store the sum of values in this node
int mid = getMid(ss, se);
st[si] = constructSTUtil(arr, ss, mid, st, si*2+1) +
constructSTUtil(arr, mid+1, se, st, si*2+2);
return st[si];
}
Output:
Sum of values in given range = 15
Updated sum of values in given range = 22
Time Complexity:
Time Complexity for tree construction is O(n). There are total 2n-1
Source
http://www.geeksforgeeks.org/segment-tree-set-1-sum-of-given-range/
Category: Trees Tags: Advance Data Structures, Advanced Data
Structures, SegmentTree
Post navigation
Amazon Interview | Set 17 Works Applications Co., Ltd. Japan
Interview | Set 1
Writing code in comment? Please use code.geeksforgeeks.org,
generate link and share the link here.
length 1), and then call the same procedure on both halves, and for
each such segment, we store the minimum value in a segment tree
node.
All levels of the constructed segment tree will be completely filled
except the last level. Also, the tree will be a Full Binary Tree because
we always divide segments in two halves at every level. Since the
constructed tree is always full binary tree with n leaves, there will be n1 internal nodes. So total number of nodes will be 2*n 1.
Height of the segment tree will be
. Since the tree is
represented using array and relation between parent and child indexes
must be maintained, size of memory allocated for segment tree will be
.
Query for minimum value of given range
Once the tree is constructed, how to do range minimum query using
the constructed segment tree. Following is algorithm to get the
minimum.
// qs --> query start index, qe --> query end index
int RMQ(node, qs, qe)
{
if range of node is within qs and qe
return value in node
else if range of node is completely outside qs and qe
return INFINITE
else
return min( RMQ(node's left child, qs, qe), RMQ(node's right child, qs, qe) )
}
Implementation:
// Program for range minimum query using segment tree
#include <stdio.h>
#include <math.h>
#include <limits.h>
// A utility function to get minimum of two numbers
int minVal(int x, int y) { return (x < y)? x: y; }
// A utility function to get the middle index from corner indexes.
int getMid(int s, int e) { return s + (e -s)/2; }
/* A recursive function to get the minimum value in a given range of array
indexes. The following are parameters for this function.
st
Output:
Minimum of values in range [1, 5] is = 2
Time Complexity:
Time Complexity for tree construction is O(n). There are total 2n-1
Source
http://www.geeksforgeeks.org/segment-tree-set-1-range-minimumquery/
Category: Trees Tags: Advance Data Structures, Advanced Data
Structures
Post navigation
[TopTalent.in] Interview with Sujeet Gholap, placed in Microsoft,
Google, Samsung, Goldman Sachs & Tower Research How to measure
time taken by a function in C?
Writing code in comment? Please use code.geeksforgeeks.org,
generate link and share the link here.
int maxHeapIndex;
struct LNode *next, *prev;
};
// Structure for a doubly linked list
struct List
{
struct LNode *head;
};
// Structure for min heap
struct MinHeap
{
int size;
int capacity;
struct LNode* *array;
};
// Structure for max heap
struct MaxHeap
{
int size;
int capacity;
struct LNode* *array;
};
// The required data structure
struct MyDS
{
struct MinHeap* minHeap;
struct MaxHeap* maxHeap;
struct List* list;
};
// Function to swap two integers
void swapData(int* a, int* b)
{ int t = *a; *a = *b; *b = t; }
// Function to swap two List nodes
void swapLNode(struct LNode** a, struct LNode** b)
{ struct LNode* t = *a; *a = *b; *b = t; }
// A utility function to create a new List node
struct LNode* newLNode(int data)
{
struct LNode* node =
(struct LNode*) malloc(sizeof(struct LNode));
node->minHeapIndex = node->maxHeapIndex = -1;
node->data = data;
&minHeap->array[index]);
// Fix the heap downward
minHeapify(minHeap, smallest);
}
}
// The standard maxHeapify function. The only thing it does extra
// is swapping indexes of heaps inside the List
void maxHeapify(struct MaxHeap* maxHeap, int index)
{
int largest, left, right;
largest = index;
left = 2 * index + 1;
right = 2 * index + 2;
if ( maxHeap->array[left] &&
left < maxHeap->size &&
maxHeap->array[left]->data > maxHeap->array[largest]->data
)
largest = left;
if ( maxHeap->array[right] &&
right < maxHeap->size &&
maxHeap->array[right]->data > maxHeap->array[largest]->data
)
largest = right;
if (largest != index)
{
// First swap indexes inside the List using address
// of List nodes
swapData(&maxHeap->array[largest]->maxHeapIndex,
&maxHeap->array[index]->maxHeapIndex);
// Now swap pointers to List nodes
swapLNode(&maxHeap->array[largest],
&maxHeap->array[index]);
// Fix the heap downward
maxHeapify(maxHeap, largest);
}
}
// Standard function to insert an item in Min Heap
void insertMinHeap(struct MinHeap* minHeap, struct LNode* temp)
{
if (isMinHeapFull(minHeap))
return;
++minHeap->size;
int i = minHeap->size - 1;
while (i && temp->data < minHeap->array[(i - 1) / 2]->data )
{
minHeap->array[i] = minHeap->array[(i - 1) / 2];
minHeap->array[i]->minHeapIndex = i;
i = (i - 1) / 2;
}
minHeap->array[i] = temp;
minHeap->array[i]->minHeapIndex = i;
}
// Standard function to insert an item in Max Heap
void insertMaxHeap(struct MaxHeap* maxHeap, struct LNode* temp)
{
if (isMaxHeapFull(maxHeap))
return;
++maxHeap->size;
int i = maxHeap->size - 1;
while (i && temp->data > maxHeap->array[(i - 1) / 2]->data )
{
maxHeap->array[i] = maxHeap->array[(i - 1) / 2];
maxHeap->array[i]->maxHeapIndex = i;
i = (i - 1) / 2;
}
maxHeap->array[i] = temp;
maxHeap->array[i]->maxHeapIndex = i;
}
return myDS->maxHeap->array[0]->data;
}
// A utility function to remove an item from linked list
void removeLNode(struct List* list, struct LNode** temp)
{
if (hasOnlyOneLNode(list))
list->head = NULL;
else if (!(*temp)->prev) // first node
{
list->head = (*temp)->next;
(*temp)->next->prev = NULL;
}
// any other node including last
else
{
(*temp)->prev->next = (*temp)->next;
// last node
if ((*temp)->next)
(*temp)->next->prev = (*temp)->prev;
}
free(*temp);
*temp = NULL;
}
// Function to delete maximum value stored in the main data structure
void deleteMax(struct MyDS* myDS)
{
MinHeap *minHeap = myDS->minHeap;
MaxHeap *maxHeap = myDS->maxHeap;
if (isMaxHeapEmpty(maxHeap))
return;
struct LNode* temp = maxHeap->array[0];
// delete the maximum item from maxHeap
maxHeap->array[0] =
maxHeap->array[maxHeap->size - 1];
--maxHeap->size;
maxHeap->array[0]->maxHeapIndex = 0;
maxHeapify(maxHeap, 0);
// remove the item from minHeap
minHeap->array[temp->minHeapIndex] = minHeap->array[minHeap->size
- 1];
--minHeap->size;
minHeap->array[temp->minHeapIndex]->minHeapIndex = temp>minHeapIndex;
minHeapify(minHeap, temp->minHeapIndex);
insertMaxHeap(myDS->maxHeap, temp);
}
// Driver program to test above functions
int main()
{
struct MyDS *myDS = createMyDS(10);
// Test Case #1
/*Insert(myDS, 10);
Insert(myDS, 2);
Insert(myDS, 32);
Insert(myDS, 40);
Insert(myDS, 5);*/
// Test Case #2
Insert(myDS, 10);
Insert(myDS, 20);
Insert(myDS, 30);
Insert(myDS, 40);
Insert(myDS, 50);
printf("Maximum = %d \n", findMax(myDS));
printf("Minimum = %d \n\n", findMin(myDS));
deleteMax(myDS); // 50 is deleted
printf("After deleteMax()\n");
printf("Maximum = %d \n", findMax(myDS));
printf("Minimum = %d \n\n", findMin(myDS));
deleteMin(myDS); // 10 is deleted
printf("After deleteMin()\n");
printf("Maximum = %d \n", findMax(myDS));
printf("Minimum = %d \n\n", findMin(myDS));
Delete(myDS, 40); // 40 is deleted
printf("After Delete()\n");
printf("Maximum = %d \n", findMax(myDS));
printf("Minimum = %d \n", findMin(myDS));
return 0;
}
Output:
Maximum = 50
Minimum = 10
After deleteMax()
Maximum = 40
Minimum = 10
After deleteMin()
Maximum = 40
Minimum = 20
After Delete()
Maximum = 30
Minimum = 20
Source
http://www.geeksforgeeks.org/a-data-structure-question/
Category: Misc Tags: Advance Data Structures, Advanced Data
Structures
Post navigation
The Ubiquitous Binary Search | Set 1 Find the first circular tour that
visits all petrol pumps
Writing code in comment? Please use code.geeksforgeeks.org,
generate link and share the link here.
equal to the disk block size. Since h is low for B-Tree, total disk
accesses for most of the operations are reduced significantly compared
to balanced Binary Search Trees like AVL Tree, Red Black Tree, ..etc.
Properties of B-Tree
1) All leaves are at same level.
2) A B-Tree is defined by the term minimum degree t. The value of t
depends upon disk block size.
3) Every node except root must contain at least t-1 keys. Root may
contain minimum 1 key.
4) All nodes (including root) may contain at most 2t 1 keys.
5) Number of children of a node is equal to the number of keys in it
plus 1.
6) All keys of a node are sorted in increasing order. The child between
two keys k1 and k2 contains all keys in range from k1 and k2.
7) B-Tree grows and shrinks from root which is unlike Binary Search
Tree. Binary Search Trees grow downward and also shrink from
downward.
8) Like other balanced Binary Search Trees, time complexity to search,
insert and delete is O(Logn).
Following is an example B-Tree of minimum degree 3. Note that in
practical B-Trees, the value of minimum degree is much more than 3.
Search
Search is similar to search in Binary Search Tree. Let the key to be
searched be k. We start from root and recursively traverse down. For
every visited non-leaf node, if the node has key, we simply return the
node. Otherwise we recur down to the appropriate child (The child
which is just before the first greater key) of the node. If we reach a leaf
node and dont find k in the leaf node, we return NULL.
Traverse
Traversal is also similar to Inorder traversal of Binary Tree. We start
from the leftmost child, recursively print the leftmost child, then repeat
the same process for remaining children and keys. In the end,
recursively print the rightmost child.
// C++ implemntation of search() and traverse() methods
#include<iostream>
using namespace std;
// A BTree node
class BTreeNode
{
int *keys; // An array of keys
int t;
// Minimum degree (defines the range for number of keys)
BTreeNode **C; // An array of child pointers
int n;
// Current number of keys
bool leaf; // Is true when node is leaf. Otherwise false
public:
BTreeNode(int _t, bool _leaf); // Constructor
// A function to traverse all nodes in a subtree rooted with this node
void traverse();
// A function to search a key in subtree rooted with this node.
BTreeNode *search(int k); // returns NULL if k is not present.
// Make BTree friend of this so that we can access private members of this
// class in BTree functions
friend class BTree;
};
// A BTree
class BTree
{
BTreeNode *root; // Pointer to root node
int t; // Minimum degree
public:
// Constructor (Initializes tree as empty)
BTree(int _t)
{ root = NULL; t = _t; }
// function to traverse the tree
void traverse()
{ if (root != NULL) root->traverse(); }
// function to search a key in this tree
BTreeNode* search(int k)
{ return (root == NULL)? NULL : root->search(k); }
};
// Constructor for BTreeNode class
BTreeNode::BTreeNode(int _t, bool _leaf)
{
// Copy the given minimum degree and leaf property
t = _t;
leaf = _leaf;
// Allocate memory for maximum number of possible keys
// and child pointers
keys = new int[2*t-1];
C = new BTreeNode *[2*t];
// Initialize the number of keys as 0
n = 0;
}
// Function to traverse all nodes in a subtree rooted with this node
void BTreeNode::traverse()
{
// There are n keys and n+1 children, travers through n keys
// and first n children
int i;
for (i = 0; i < n; i++)
{
// If this is not leaf, then before printing key[i],
// traverse the subtree rooted with child C[i].
if (leaf == false)
C[i]->traverse();
cout << " " << keys[i];
}
// Print the subtree rooted with last child
if (leaf == false)
C[i]->traverse();
}
// Function to search key k in subtree rooted with this node
BTreeNode *BTreeNode::search(int k)
{
// Find the first key greater than or equal to k
int i = 0;
while (i < n && k > keys[i])
i++;
// If the found key is equal to k, return this node
if (keys[i] == k)
return this;
// If key is not found here and this is a leaf node
if (leaf == true)
return NULL;
// Go to the appropriate child
return C[i]->search(k);
Source
http://www.geeksforgeeks.org/b-tree-set-1-introduction-2/
Let us now insert 20, 30, 40 and 50. They all will be inserted in root
because maximum number of keys a node can accommodate is 2*t 1
which is 5.
Let us now insert 60. Since root node is full, it will first split into two,
then 60 will be inserted into the appropriate child.
Let us now insert 70 and 80. These new keys will be inserted into the
appropriate leaf without any split.
Let us now insert 90. This insertion will cause a split. The middle key
will go up to the parent.
// A BTree
class BTree
{
BTreeNode *root; // Pointer to root node
int t; // Minimum degree
public:
// Constructor (Initializes tree as empty)
BTree(int _t)
{ root = NULL; t = _t; }
// function to traverse the tree
void traverse()
{ if (root != NULL) root->traverse(); }
// function to search a key in this tree
BTreeNode* search(int k)
{ return (root == NULL)? NULL : root->search(k); }
// The main function that inserts a new key in this B-Tree
void insert(int k);
};
// Constructor for BTreeNode class
BTreeNode::BTreeNode(int t1, bool leaf1)
{
// Copy the given minimum degree and leaf property
t = t1;
leaf = leaf1;
// Allocate memory for maximum number of possible keys
// and child pointers
keys = new int[2*t-1];
C = new BTreeNode *[2*t];
// Initialize the number of keys as 0
n = 0;
}
// Function to traverse all nodes in a subtree rooted with this node
void BTreeNode::traverse()
{
// There are n keys and n+1 children, travers through n keys
// and first n children
int i;
for (i = 0; i < n; i++)
{
// If this is not leaf, then before printing key[i],
// traverse the subtree rooted with child C[i].
if (leaf == false)
C[i]->traverse();
cout << " " << keys[i];
}
// Print the subtree rooted with last child
if (leaf == false)
C[i]->traverse();
}
// Function to search key k in subtree rooted with this node
BTreeNode *BTreeNode::search(int k)
{
// Find the first key greater than or equal to k
int i = 0;
while (i < n && k > keys[i])
i++;
// If the found key is equal to k, return this node
if (keys[i] == k)
return this;
// If key is not found here and this is a leaf node
if (leaf == true)
return NULL;
// Go to the appropriate child
return C[i]->search(k);
}
// The main function that inserts a new key in this B-Tree
void BTree::insert(int k)
{
// If tree is empty
if (root == NULL)
{
// Allocate memory for root
root = new BTreeNode(t, true);
root->keys[0] = k; // Insert key
root->n = 1; // Update number of keys in root
}
else // If tree is not empty
{
// If root is full, then tree grows in height
if (root->n == 2*t-1)
{
// Allocate memory for new root
BTreeNode *s = new BTreeNode(t, false);
// new key and move all greater keys one space ahead
for (int j = n-1; j >= i; j--)
keys[j+1] = keys[j];
// Copy the middle key of y to this node
keys[i] = y->keys[t-1];
// Increment count of keys in this node
n = n + 1;
}
// Driver program to test above functions
int main()
{
BTree t(3); // A B-Tree with minium degree 3
t.insert(10);
t.insert(20);
t.insert(5);
t.insert(6);
t.insert(12);
t.insert(30);
t.insert(7);
t.insert(17);
cout << "Traversal of the constucted tree is ";
t.traverse();
int k = 6;
(t.search(k) != NULL)? cout << "\nPresent" : cout << "\nNot Present";
k = 15;
(t.search(k) != NULL)? cout << "\nPresent" : cout << "\nNot Present";
return 0;
}
Output:
Traversal of the constucted tree is 5 6 7 10 12 17 20 30
Present
Not Present
References:
Introduction to Algorithms 3rd Edition by Clifford Stein, Thomas H.
Cormen, Charles E. Leiserson, Ronald L. Rivest
http://www.cs.utexas.edu/users/djimenez/utsa/cs3343/lecture17.html
Please write comments if you find anything incorrect, or you want to
share more information about the topic discussed above.
Source
http://www.geeksforgeeks.org/b-tree-set-1-insert-2/
Solution
We build a Trie of all dictionary words. Once the Trie is built, traverse
through it using characters of input string. If prefix matches a
dictionary word, store current length and look for a longer match.
Finally, return the longest match.
Following is Java implementation of the above solution based.
import java.util.HashMap;
// Trie Node, which stores a character and the children in a HashMap
class TrieNode {
public TrieNode(char ch) {
value = ch;
children = new HashMap<>();
bIsEnd = false;
}
public HashMap<Character,TrieNode> getChildren() { return children; }
public char getValue()
public void setIsEnd(boolean val)
public boolean isEnd()
{ return value;
}
{ bIsEnd = val;
{ return bIsEnd; }
System.out.println(dict.getMatchingPrefix(input));
input = "are";
System.out.print(input + ": ");
System.out.println(dict.getMatchingPrefix(input));
input = "arex";
System.out.print(input + ": ");
System.out.println(dict.getMatchingPrefix(input));
input = "basemexz";
System.out.print(input + ": ");
System.out.println(dict.getMatchingPrefix(input));
input = "xyz";
System.out.print(input + ": ");
System.out.println(dict.getMatchingPrefix(input));
}
}
Output:
caterer: cater
basement: basement
are: are
arex: are
basemexz: base
xyz:
Source
http://www.geeksforgeeks.org/longest-prefix-matching-a-trie-basedsolution-in-java/
Category: Trees Tags: Advance Data Structures, Java
We sketch how deletion works with various cases of deleting keys from
a B-tree.
1. If the key k is in node x and x is a leaf, delete the key k from x.
2. If the key k is in node x and x is an internal node, do the following.
a) If the child y that precedes k in node x has at least t keys, then
find the predecessor k0 of k in the sub-tree rooted at y. Recursively
delete k0, and replace k by k0 in x. (We can find k0 and delete it in a
single downward pass.)
b) If y has fewer than t keys, then, symmetrically, examine the child
z that follows k in node x. If z has at least t keys, then find the
successor k0 of k in the subtree rooted at z. Recursively delete k0, and
replace k by k0 in x. (We can find k0 and delete it in a single downward
pass.)
c) Otherwise, if both y and z have only t-1 keys, merge k and all of z
into y, so that x loses both k and the pointer to z, and y now contains
2t-1 keys. Then free z and recursively delete k from y.
3. If the key k is not present in internal node x, determine the root
x.c(i) of the appropriate subtree that must contain k, if k is in the tree
at all. If x.c(i) has only t-1 keys, execute step 3a or 3b as necessary to
guarantee that we descend to a node containing at least t keys. Then
finish by recursing on the appropriate child of x.
a) If x.c(i) has only t-1 keys but has an immediate sibling with at
least t keys, give x.c(i) an extra key by moving a key from x down into
x.c(i), moving a key from x.c(i) s immediate left or right sibling up into
x, and moving the appropriate child pointer from the sibling into x.c(i).
b) If x.c(i) and both of x.c(i)s immediate siblings have t-1 keys,
merge x.c(i) with one sibling, which involves moving a key from x down
into the new merged node to become the median key for that node.
Since most of the keys in a B-tree are in the leaves, deletion operations
are most often used to delete keys from leaves. The recursive delete
procedure then acts in one downward pass through the tree, without
having to back up. When deleting a key in an internal node, however,
the procedure makes a downward pass through the tree but may have
to return to the node from which the key was deleted to replace the
key with its predecessor or successor (cases 2a and 2b).
The following figures from CLRS book explain the deletion porcess.
Implementation:
Following is C++ implementation of deletion process.
/* The following program performs deletion on a B-Tree. It contains functions
specific for deletion along with all the other functions provided in the
previous articles on B-Trees. See http://www.geeksforgeeks.org/b-tree-set-1introduction-2/
for previous article.
The deletion function has been compartmentalized into 8 functions for ease
of understanding and clarity
The following functions are exclusive for deletion
In class BTreeNode:
1) remove
2) removeFromLeaf
3) removeFromNonLeaf
4) getPred
5) getSucc
6) borrowFromPrev
7) borrowFromNext
8) merge
9) findKey
In class BTree:
1) remove
The removal of a key from a B-Tree is a fairly complicated process. The
program handles
all the 6 different cases that might arise while removing a key.
Testing: The code has been tested using the B-Tree provided in the CLRS
book( included
in the main function ) along with other cases.
Reference: CLRS3 - Chapter 18 - (499-502)
It is advised to read the material in CLRS before taking a look at the code. */
#include<iostream>
using namespace std;
// A BTree node
class BTreeNode
{
int *keys; // An array of keys
int t;
// Minimum degree (defines the range for number of keys)
BTreeNode **C; // An array of child pointers
int n;
// Current number of keys
bool leaf; // Is true when node is leaf. Otherwise false
public:
BTreeNode(int _t, bool _leaf); // Constructor
leaf = leaf1;
// Allocate memory for maximum number of possible keys
// and child pointers
keys = new int[2*t-1];
C = new BTreeNode *[2*t];
// Initialize the number of keys as 0
n = 0;
}
// A utility function that returns the index of the first key that is
// greater than or equal to k
int BTreeNode::findKey(int k)
{
int idx=0;
while (idx<n && keys[idx] < k)
++idx;
return idx;
}
// A function to remove the key k from the sub-tree rooted with this node
void BTreeNode::remove(int k)
{
int idx = findKey(k);
// The key to be removed is present in this node
if (idx < n && keys[idx] == k)
{
// If the node is a leaf node - removeFromLeaf is called
// Otherwise, removeFromNonLeaf function is called
if (leaf)
removeFromLeaf(idx);
else
removeFromNonLeaf(idx);
}
else
{
// If this node is a leaf node, then the key is not present in tree
if (leaf)
{
cout << "The key "<< k <<" is does not exist in the tree\n";
return;
}
// The key to be removed is present in the sub-tree rooted with this node
// The flag indicates whether the key is present in the sub-tree rooted
C[idx]->remove(pred);
}
// If the child C[idx] has less that t keys, examine C[idx+1].
// If C[idx+1] has atleast t keys, find the successor 'succ' of k in
// the subtree rooted at C[idx+1]
// Replace k by succ
// Recursively delete succ in C[idx+1]
else if (C[idx+1]->n >= t)
{
int succ = getSucc(idx);
keys[idx] = succ;
C[idx+1]->remove(succ);
}
// If both C[idx] and C[idx+1] has less that t keys,merge k and all of
C[idx+1]
// into C[idx]
// Now C[idx] contains 2t-1 keys
// Free C[idx+1] and recursively delete k from C[idx]
else
{
merge(idx);
C[idx]->remove(k);
}
return;
}
// A function to get predecessor of keys[idx]
int BTreeNode::getPred(int idx)
{
// Keep moving to the right most node until we reach a leaf
BTreeNode *cur=C[idx];
while (!cur->leaf)
cur = cur->C[cur->n];
// Return the last key of the leaf
return cur->keys[cur->n-1];
}
int BTreeNode::getSucc(int idx)
{
// Keep moving the left most node starting from C[idx+1] until we reach a
leaf
BTreeNode *cur = C[idx+1];
while (!cur->leaf)
cur = cur->C[0];
{
for(int i=child->n; i>=0; --i)
child->C[i+1] = child->C[i];
}
// Setting child's first key equal to keys[idx-1] from the current node
child->keys[0] = keys[idx-1];
// Moving sibling's last child as C[idx]'s first child
if (!leaf)
child->C[0] = sibling->C[sibling->n];
// Moving the key from the sibling to the parent
// This reduces the number of keys in the sibling
keys[idx-1] = sibling->keys[sibling->n-1];
child->n += 1;
sibling->n -= 1;
return;
}
// A function to borrow a key from the C[idx+1] and place
// it in C[idx]
void BTreeNode::borrowFromNext(int idx)
{
BTreeNode *child=C[idx];
BTreeNode *sibling=C[idx+1];
// keys[idx] is inserted as the last key in C[idx]
child->keys[(child->n)] = keys[idx];
// Sibling's first child is inserted as the last child
// into C[idx]
if (!(child->leaf))
child->C[(child->n)+1] = sibling->C[0];
//The first key from sibling is inserted into keys[idx]
keys[idx] = sibling->keys[0];
// Moving all keys in sibling one step behind
for (int i=1; i<sibling->n; ++i)
sibling->keys[i-1] = sibling->keys[i];
// Moving the child pointers one step behind
if (!sibling->leaf)
{
for(int i=1; i<=sibling->n; ++i)
sibling->C[i-1] = sibling->C[i];
}
// Increasing and decreasing the key count of C[idx] and C[idx+1]
// respectively
child->n += 1;
sibling->n -= 1;
return;
}
// A function to merge C[idx] with C[idx+1]
// C[idx+1] is freed after merging
void BTreeNode::merge(int idx)
{
BTreeNode *child = C[idx];
BTreeNode *sibling = C[idx+1];
// Pulling a key from the current node and inserting it into (t-1)th
// position of C[idx]
child->keys[t-1] = keys[idx];
// Copying the keys from C[idx+1] to C[idx] at the end
for (int i=0; i<sibling->n; ++i)
child->keys[i+t] = sibling->keys[i];
// Copying the child pointers from C[idx+1] to C[idx]
if (!child->leaf)
{
for(int i=0; i<=sibling->n; ++i)
child->C[i+t] = sibling->C[i];
}
// Moving all keys after idx in the current node one step before // to fill the gap created by moving keys[idx] to C[idx]
for (int i=idx+1; i<n; ++i)
keys[i-1] = keys[i];
// Moving the child pointers after (idx+1) in the current node one
// step before
for (int i=idx+2; i<=n; ++i)
C[i-1] = C[i];
// Updating the key count of child and the current node
child->n += sibling->n+1;
n--;
// Freeing the memory occupied by sibling
delete(sibling);
return;
}
// The main function that inserts a new key in this B-Tree
void BTree::insert(int k)
{
// If tree is empty
if (root == NULL)
{
// Allocate memory for root
root = new BTreeNode(t, true);
root->keys[0] = k; // Insert key
root->n = 1; // Update number of keys in root
}
else // If tree is not empty
{
// If root is full, then tree grows in height
if (root->n == 2*t-1)
{
// Allocate memory for new root
BTreeNode *s = new BTreeNode(t, false);
// Make old root as child of new root
s->C[0] = root;
// Split the old root and move 1 key to the new root
s->splitChild(0, root);
// New root has two children now. Decide which of the
// two children is going to have new key
int i = 0;
if (s->keys[0] < k)
i++;
s->C[i]->insertNonFull(k);
// Change root
root = s;
}
else // If root is not full, call insertNonFull for root
root->insertNonFull(k);
}
}
// A utility function to insert a new key in this node
// The assumption is, the node must be non-full when this
// function is called
void BTreeNode::insertNonFull(int k)
{
// Initialize index as index of rightmost element
int i = n-1;
z->keys[j] = y->keys[j+t];
// Copy the last t children of y to z
if (y->leaf == false)
{
for (int j = 0; j < t; j++)
z->C[j] = y->C[j+t];
}
// Reduce the number of keys in y
y->n = t - 1;
// Since this node is going to have a new child,
// create space of new child
for (int j = n; j >= i+1; j--)
C[j+1] = C[j];
// Link the new child to this node
C[i+1] = z;
// A key of y will move to this node. Find location of
// new key and move all greater keys one space ahead
for (int j = n-1; j >= i; j--)
keys[j+1] = keys[j];
// Copy the middle key of y to this node
keys[i] = y->keys[t-1];
// Increment count of keys in this node
n = n + 1;
}
// Function to traverse all nodes in a subtree rooted with this node
void BTreeNode::traverse()
{
// There are n keys and n+1 children, travers through n keys
// and first n children
int i;
for (i = 0; i < n; i++)
{
// If this is not leaf, then before printing key[i],
// traverse the subtree rooted with child C[i].
if (leaf == false)
C[i]->traverse();
cout << " " << keys[i];
}
// Print the subtree rooted with last child
if (leaf == false)
C[i]->traverse();
}
// Function to search key k in subtree rooted with this node
BTreeNode *BTreeNode::search(int k)
{
// Find the first key greater than or equal to k
int i = 0;
while (i < n && k > keys[i])
i++;
// If the found key is equal to k, return this node
if (keys[i] == k)
return this;
// If key is not found here and this is a leaf node
if (leaf == true)
return NULL;
// Go to the appropriate child
return C[i]->search(k);
}
void BTree::remove(int k)
{
if (!root)
{
cout << "The tree is empty\n";
return;
}
// Call the remove function for root
root->remove(k);
// If the root node has 0 keys, make its first child as the new root
// if it has a child, otherwise set root as NULL
if (root->n==0)
{
BTreeNode *tmp = root;
if (root->leaf)
root = NULL;
else
root = root->C[0];
// Free the old root
delete tmp;
}
return;
}
t.remove(4);
cout << "Traversal of tree after removing 4\n";
t.traverse();
cout << endl;
t.remove(2);
cout << "Traversal of tree after removing 2\n";
t.traverse();
cout << endl;
t.remove(16);
cout << "Traversal of tree after removing 16\n";
t.traverse();
cout << endl;
return 0;
}
Output:
Traversal of tree constructed is
1 2 3 4 5 6 7 10 11 12 13 14 15 16 17 18 19 20 21 22 24 25 26
Traversal of tree after removing 6
1 2 3 4 5 7 10 11 12 13 14 15 16 17 18 19 20 21 22 24 25 26
Traversal of tree after removing 13
1 2 3 4 5 7 10 11 12 14 15 16 17 18 19 20 21 22 24 25 26
Traversal of tree after removing 7
1 2 3 4 5 10 11 12 14 15 16 17 18 19 20 21 22 24 25 26
Traversal of tree after removing 4
1 2 3 5 10 11 12 14 15 16 17 18 19 20 21 22 24 25 26
Traversal of tree after removing 2
1 3 5 10 11 12 14 15 16 17 18 19 20 21 22 24 25 26
Traversal of tree after removing 16
1 3 5 10 11 12 14 15 17 18 19 20 21 22 24 25 26
Source
http://www.geeksforgeeks.org/b-tree-set-3delete/
Category: Trees Tags: Advance Data Structures, Advanced Data
Structures
Post navigation
Radix Sort Dynamic Programming | Set 36 (Maximum Product
Cutting)
Writing code in comment? Please use code.geeksforgeeks.org,
generate link and share the link here.
T1, T2 and T3 are subtrees of the tree rooted with y (on left side) or x
(on right side)
y
x
/\
Zig (Right Rotation)
/ \
x T3 - - - - - ->
T1 y
/\
3) Node has both parent and grandparent. There can be following subcases.
........3.a) Zig-Zig and Zag-Zag Node is left child of parent and parent is also
left child of grand parent (Two right rotations) OR node is right child of its
parent and parent is also right child of grand parent (Two Left Rotations).
Zig-Zig (Left Left Case):
G
P
X
/\
/ \
/\
P T4 rightRotate(G) X
G
rightRotate(P) T1 P
/\
============> / \ / \ ============>
X T3
T1 T2 T3 T4
T2 G
/\
/\
T1 T2
T3 T4
/\
........3.b) Zig-Zag and Zag-Zig Node is left child of parent and parent
is right child of grand parent (Left Rotation followed by right rotation)
OR node is right child of its parent and parent is left child of grand
parent (Right Rotation followed by left rotation).
Zig-Zag (Left Right Case):
G
G
X
/\
/ \
/ \
P T4 leftRotate(P) X
T4 rightRotate(G) P
G
/ \
============> / \
============> / \ / \
T1 X
P T3
T1 T2 T3 T4
/\
/\
T2 T3
T1 T2
Zag-Zig (Right Left Case):
G
G
/ \
/ \
T1 P rightRotate(P) T1 X
/ \ =============>
X T4
T2 P
/\
/\
T2 T3
T3 T4
/ \
leftRotate(P) G
P
/ \ ============> / \ / \
T1 T2 T3 T4
Example:
100
100
[20]
/ \
/ \
\
50 200
50 200
50
/
search(20) /
search(20)
/ \
40
======>
[20]
========>
/
1. Zig-Zig \
2. Zig-Zig
\
\
30
at 40
30
at 100
40 200
/
\
[20]
40
30 100
The important thing to note is, the search or splay operation not only
brings the searched key to root, but also balances the BST. For example
in above case, height of BST is reduced by 1.
Implementation:
// The code is adopted from http://goo.gl/SDH9hH
#include<stdio.h>
#include<stdlib.h>
// An AVL tree node
struct node
{
int key;
struct node *left, *right;
};
/* Helper function that allocates a new node with the given key and
NULL left and right pointers. */
struct node* newNode(int key)
{
struct node* node = (struct node*)malloc(sizeof(struct node));
node->key = key;
node->left = node->right = NULL;
return (node);
}
// A utility function to right rotate subtree rooted with y
// See the diagram given above.
struct node *rightRotate(struct node *x)
{
struct node *y = x->left;
x->left = y->right;
y->right = x;
return y;
}
// A utility function to left rotate subtree rooted with x
// See the diagram given above.
struct node *leftRotate(struct node *x)
{
struct node *y = x->right;
x->right = y->left;
y->left = x;
return y;
}
// This function brings the key at root if key is present in tree.
// If key is not present, then it brings the last accessed item at
// root. This function modifies the tree and returns the new root
struct node *splay(struct node *root, int key)
{
// Base cases: root is NULL or key is present at root
if (root == NULL || root->key == key)
return root;
// Key lies in left subtree
if (root->key > key)
{
// Key is not in tree, we are done
if (root->left == NULL) return root;
// Zig-Zig (Left Left)
if (root->left->key > key)
{
// First recursively bring the key as root of left-left
root->left->left = splay(root->left->left, key);
// Do first rotation for root, second rotation is done after else
root = rightRotate(root);
}
else if (root->left->key < key) // Zig-Zag (Left Right)
{
// First recursively bring the key as root of left-right
root->left->right = splay(root->left->right, key);
// Do first rotation for root->left
if (root->left->right != NULL)
root->left = leftRotate(root->left);
}
Output:
Preorder traversal of the modified Splay tree is
20 50 30 40 100 200
Summary
1) Splay trees have excellent locality properties. Frequently accessed
items are easy to find. Infrequent items are out of way.
2) All splay tree operations take O(Logn) time on average. Splay trees
can be rigorously shown to run in O(log n) average time per operation,
over any sequence of operations (assuming we start from an empty
tree)
3) Splay trees are simpler compared to AVLand Red-Black Trees as no
extra field is required in every tree node.
4) Unlike AVL tree, a splay tree can change even with read-only
operations like search.
Applications of Splay Trees
Splay trees have become the most widely used basic data structure
invented in the last 30 years, because they're the fastest type of
balanced search tree for many applications.
Splay trees are used in Windows NT (in the virtual memory,
networking, and file system code), the gcc compiler and GNU C++
library, the sed string editor, Fore Systems network routers, the most
popular implementation of Unix malloc, Linux loadable kernel modules,
and in much other software (Source:
http://www.cs.berkeley.edu/~jrs/61b/lec/36)
We will soon be discussing insert and delete operations on splay trees.
References:
http://www.cs.berkeley.edu/~jrs/61b/lec/36
http://www.cs.cornell.edu/courses/cs3110/2009fa/recitations/recsplay.html
http://courses.cs.washington.edu/courses/cse326/01au/lectures/SplayTr
ees.ppt
Please write comments if you find anything incorrect, or you want to
share more information about the topic discussed above
Source
http://www.geeksforgeeks.org/splay-tree-set-1-insert/
Example:
100
[20]
25
/ \
\
/ \
50 200
50
20 50
/
insert(25)
/ \
insert(25)
/ \
40
======>
30 100
========>
/
1. Splay(25) \
\
2. insert 25
\ \
30
40 200
40 200
/
[20]
30 100
newnode->left = root;
newnode->right = root->right;
root->right = NULL;
}
return newnode; // newnode becomes new root
}
// A utility function to print preorder traversal of the tree.
// The function also prints height of every node
void preOrder(struct node *root)
{
if (root != NULL)
{
printf("%d ", root->key);
preOrder(root->left);
preOrder(root->right);
}
}
/* Drier program to test above function*/
int main()
{
struct node *root = newNode(100);
root->left = newNode(50);
root->right = newNode(200);
root->left->left = newNode(40);
root->left->left->left = newNode(30);
root->left->left->left->left = newNode(20);
root = insert(root, 25);
printf("Preorder traversal of the modified Splay tree is \n");
preOrder(root);
return 0;
}
Output:
Preorder traversal of the modified Splay tree is
25 20 50 30 40 100 200
Source
http://www.geeksforgeeks.org/splay-tree-set-2-insert-delete/
banana
5a
anana
Sort the Suffixes
3 ana
nana
---------------->
1 anana
ana
alphabetically
0 banana
na
4 na
a
2 nana
}
// Driver program to test above functions
int main()
{
char txt[] = "banana";
int n = strlen(txt);
int *suffixArr = buildSuffixArray(txt, n);
cout << "Following is suffix array for " << txt << endl;
printArr(suffixArr, n);
return 0;
}
Output:
Following is suffix array for banana
531042
Output:
Pattern found at index 2
Source
http://www.geeksforgeeks.org/suffix-array-set-1-introduction/
3) There are no two adjacent red nodes (A red node cannot have a red
parent or red child).
4) Every path from root to a NULL node has same number of black
nodes.
Why Red-Black Trees?
Most of the BST operations (e.g., search, max, min, insert, delete.. etc)
take O(h) time where h is the height of the BST. The cost of these
operations may become O(n) for a skewed Binary tree. If we make sure
that height of the tree remains O(Logn) after every insertion and
deletion, then we can guarantee an upper bound of O(Logn) for all
these operations. The height of a Red Black tree is always O(Logn)
where n is the number of nodes in the tree.
Comparison withAVL Tree
The AVL trees are more balanced compared to Red Black Trees, but
they may cause more rotations during insertion and deletion. So if your
application involves many frequent insertions and deletions, then Red
Black trees should be preferred. And if the insertions and deletions are
less frequent and search is more frequent operation, then AVL tree
should be preferred over Red Black Tree.
How does a Red-Black Tree ensure balance?
A simple example to understand balancing is, a chain of 3 nodes is not
possible in red black tree. We can try any combination of colors and
see all of them violate Red-Black tree property.
A chain of 3 nodes is nodes is not possible in Red-Black Trees.
Following are NOT Red-Black Trees
30
30
30
/\
/ \
/ \
20 NIL
20 NIL
20 NIL
/\
/\
/ \
10 NIL
10 NIL
10 NIL
Violates
Violates
Violates
Property 4.
Property 4
Property 3
Following are different possible Red-Black Trees with above 3 keys
20
20
/ \
/ \
10
30
10
30
/ \ / \
/ \ / \
NIL NIL NIL NIL
NIL NIL NIL NIL
From the above examples, we get some idea how Red-Black trees
ensure balance. Following is an important fact about balancing in RedBlack Trees.
Every Red Black Tree with n nodes has height <= 2Log2(n+1)
This can be proved using following facts:
1) For a general Binary Tree, let k be the minimum number of nodes
on all root to NULL paths, then n >= 2k 1 (Ex. If k is 3, then n is
atleast 7). This expression can also be written as k <= 2Log2(n+1)
2) From property 4 of Red-Black trees and above claim, we can say in a
Red-Black Tree with n nodes, there is a root to leaf path with at-most
Log2(n+1) black nodes.
3) From property 3 of Red-Black trees, we can claim that the number
black nodes in a Red-Black tree is at least n/2 where n is total
number of nodes.
From above 2 points, we can conclude the fact that Red Black Tree with
n nodes has height <= 2Log2(n+1)
In this post, we introduced Red-Black trees and discussed how balance
is ensured. The hard part is to maintain balance when keys are added
and removed. We will soon be discussing insertion and deletion
operations in coming posts on Red-Black tree.
Exercise:
1) Is it possible to have all black nodes in a Red-Black tree?
2) Draw a Red-Black Tree that is not an AVL tree structure wise?
Insertion and Deletion
Red Black Tree Insertion
Red-Black Tree Deletion
References:
Introduction to Algorithms 3rd Edition by Clifford Stein, Thomas H.
Cormen, Charles E. Leiserson, Ronald L. Rivest
http://en.wikipedia.org/wiki/Red%E2%80%93black_tree
Video Lecture on Red-Black Tree by Tim Roughgarden
MIT Video Lecture on Red-Black Tree
MIT Lecture Notes on Red Black Tree
Please write comments if you find anything incorrect, or you want to
share more information about the topic discussed above.
Source
http://www.geeksforgeeks.org/red-black-tree-set-1-introduction-2/
Examples of Insertion
Exercise:
Insert 2, 7 and 13 in below tree. Insertion of 13 is going to be really
interesting, try it to check if you have understood insertion well for
exams.
Please refer C Program for Red Black Tree Insertion for complete
implementation of above algorithm.
Please write comments if you find anything incorrect, or you want to
share more information about the topic discussed above.
Source
http://www.geeksforgeeks.org/red-black-tree-set-2-insert/
Interval Tree
Consider a situation where we have a set of intervals and we need
following operations to be implemented efficiently.
1) Add an interval
2) Remove an interval
3) Given an interval x, find if x overlaps with any of the existing
intervals.
Interval Tree: The idea is to augment a self-balancing Binary Search
Tree (BST) like Red Black Tree, AVL Tree, etc to maintain set of intervals
so that all operations can be done in O(Logn) time.
Every node of Interval Tree stores following information.
a) i: An interval which is represented as a pair [low, high]
b) max: Maximum high value in subtree rooted with this node.
The low value of an interval is used as key to maintain order in BST.
The insert and delete operations are same as insert and delete in selfbalancing BST used.
#include <iostream>
using namespace std;
// Structure to represent an interval
struct Interval
{
int low, high;
};
// Structure to represent a node in Interval Search Tree
struct ITNode
{
Interval *i; // 'i' could also be a normal variable
int max;
ITNode *left, *right;
};
// A utility function to create a new Interval Search Tree Node
ITNode * newNode(Interval i)
{
ITNode *temp = new ITNode;
temp->i = new Interval(i);
temp->max = i.high;
temp->left = temp->right = NULL;
};
// A utility function to insert a new Interval Search Tree Node
// This is similar to BST Insert. Here the low value of interval
// is used tomaintain BST property
ITNode *insert(ITNode *root, Interval i)
{
// Base case: Tree is empty, new node becomes root
if (root == NULL)
return newNode(i);
// Get low value of interval at root
int l = root->i->low;
// If root's low value is smaller, then new interval goes to
// left subtree
if (i.low < l)
root->left = insert(root->left, i);
// Else, new node goes to right subtree.
else
root->right = insert(root->right, i);
// Update the max value of this ancestor if needed
{
// Let us create interval tree shown in above figure
Interval ints[] = {{15, 20}, {10, 30}, {17, 19},
{5, 20}, {12, 15}, {30, 40}
};
int n = sizeof(ints)/sizeof(ints[0]);
ITNode *root = NULL;
for (int i = 0; i < n; i++)
root = insert(root, ints[i]);
cout << "Inorder traversal of constructed Interval Tree is\n";
inorder(root);
Interval x = {6, 7};
cout << "\nSearching for interval [" << x.low << "," << x.high << "]";
Interval *res = overlapSearch(root, x);
if (res == NULL)
cout << "\nNo Overlapping Interval";
else
cout << "\nOverlaps with [" << res->low << ", " << res->high << "]";
return 0;
}
Output:
Inorder traversal of constructed Interval Tree is
[5, 20] max = 20
[10, 30] max = 30
[12, 15] max = 15
[15, 20] max = 40
[17, 19] max = 40
[30, 40] max = 40
Searching for interval [6,7]
Overlaps with [5, 20]
Exercise:
1) Implement delete operation for interval tree.
2) Extend the intervalSearch() to print all overlapping intervals instead
of just one.
http://en.wikipedia.org/wiki/Interval_tree
http://www.cse.unr.edu/~mgunes/cs302/IntervalTrees.pptx
Introduction to Algorithms 3rd Edition by Clifford Stein, Thomas H.
Cormen, Charles E. Leiserson, Ronald L. Rivest
https://www.youtube.com/watch?v=dQF0zyaym8A
Please write comments if you find anything incorrect, or you want to
share more information about the topic discussed above
Source
http://www.geeksforgeeks.org/interval-tree/
Deletion Steps
Following are detailed steps for deletion.
1) Perform standard BST delete. When we perform standard delete
operation in BST, we always end up deleting a node which is either leaf
or has only one child (For an internal node, we copy the successor and
then recursively call delete for successor, successor is always a leaf
node or a node with one child). So we only need to handle cases where
a node is leaf or has one child. Let v be the node to be deleted and u
be the child that replaces v (Note that u is NULL when v is a leaf and
color of NULL is considered as Black).
2) Simple Case: If either u or v is red, we mark the replaced child
as black (No change in black height). Note that both u and v cannot be
red as v is parent of u and two consecutive reds are not allowed in redblack tree.
..(iv) Right Left Case (s is right child of its parent and r is left
child of s)
..(b): If sibling is black and its both children are black, perform
recoloring, and recur for the parent if parent is black.
In this case, if parent was red, then we didnt need to recur for prent,
we can simply make it black (red + double black = single black)
..(c): If sibling is red, perform a rotation to move old sibling up,
recolor the old sibling and parent. The new sibling is always black (See
the below diagram). This mainly converts the tree to black sibling case
(by rotation) and leads to case (a) or (b). This case can be divided in
two subcases.
..(i) Left Case (s is left child of its parent). This is mirror of
right right case shown in below diagram. We right rotate the parent p.
..(iii) Right Case (s is right child of its parent). We left rotate
the parent p.
Source
http://www.geeksforgeeks.org/red-black-tree-set-3-delete-2/
banana
5a
anana
Sort the Suffixes
3 ana
nana
---------------->
1 anana
ana
alphabetically
0 banana
na
4 na
a
2 nana
Suffix
banana
anana
nana
ana
Rank
1
0
13
0
4
5
na
a
13
0
For every character, we also store rank of next adjacent character, i.e.,
the rank of character at str[i + 1] (This is needed to sort the suffixes
according to first 2 characters). If a character is last character, we
store next rank as -1
Index
0
1
2
3
4
5
Suffix
banana
anana
nana
ana
na
a
Rank
1
0
13
0
13
0
Next Rank
0
13
0
13
0
-1
Suffix
a
anana
ana
banana
nana
na
Rank
0
0
0
1
13
13
Next Rank
-1
13
13
0
0
0
Suffix
a
anana
ana
banana
nana
na
Rank
0
[Assign 0 to first]
1
(0, 13) is different from previous
1
(0, 13) is same as previous
2
(1, 0) is different from previous
3
(13, 0) is different from previous
3
(13, 0) is same as previous
For every suffix str[i], also store rank of next suffix at str[i + 2]. If there
is no next suffix at i + 2, we store next rank as -1
Index
5
1
3
0
2
4
Suffix
a
anana
ana
banana
nana
na
Rank
0
1
1
2
3
3
Next Rank
-1
1
0
3
3
-1
Suffix
a
ana
anana
banana
na
nana
Rank
0
1
1
2
3
3
Next Rank
-1
0
1
3
-1
3
suffixes[ind[nextindex]].rank[0]: -1;
}
// Sort the suffixes according to first k characters
sort(suffixes, suffixes+n, cmp);
}
// Store indexes of all sorted suffixes in the suffix array
int *suffixArr = new int[n];
for (int i = 0; i < n; i++)
suffixArr[i] = suffixes[i].index;
// Return the suffix array
return suffixArr;
}
// A utility function to print an array of given size
void printArr(int arr[], int n)
{
for (int i = 0; i < n; i++)
cout << arr[i] << " ";
cout << endl;
}
// Driver program to test above functions
int main()
{
char txt[] = "banana";
int n = strlen(txt);
int *suffixArr = buildSuffixArray(txt, n);
cout << "Following is suffix array for " << txt << endl;
printArr(suffixArr, n);
return 0;
}
Output:
Following is suffix array for banana
531042
Note that the above algorithm uses standard sort function and
therefore time complexity is O(nLognLogn). We can use Radix Sort here
to reduce the time complexity to O(nLogn).
Please note that suffx arrays can be constructed in O(n) time also. We
will soon be discussing O(n) algorithms.
References:
http://www.stanford.edu/class/cs97si/suffix-array.pdf
http://www.cbcb.umd.edu/confcour/Fall2012/lec14b.pdf
Please write comments if you find anything incorrect, or you want to
share more information about the topic discussed above.
Source
http://www.geeksforgeeks.org/suffix-array-set-2-a-nlognlogn-algorithm/
Source
http://www.geeksforgeeks.org/data-structure-dictionary-spell-checker/
K Dimensional Tree
A K-D Tree(also called as K-Dimensional Tree) is a binary search tree
where data in each node is a K-Dimensional point in space. In short, it
is a space partitioning(details below) data structure for organizing
points in a K-Dimensional space.
A non-leaf node in K-D tree divides the space into two parts, called as
half-spaces.
Points to the left of this space are represented by the left subtree of
that node and points to the right of the space are represented by the
right subtree. We will soon be explaining the concept on how the space
is divided and tree is formed.
For the sake of simplicity, let us understand a 2-D Tree with an
example.
The root would have an x-aligned plane, the roots children would both
have y-aligned planes, the roots grandchildren would all have xaligned planes, and the roots great-grandchildren would all have yaligned planes and so on.
Generalization:
Let us number the planes as 0, 1, 2, (K 1). From the above
example, it is quite clear that a point (node) at depth D will have A
aligned plane where A is calculated as:
A = D mod K
How to determine if a point will lie in the left subtree or in
right subtree?
If the root node is aligned in planeA, then the left subtree will contain
all points whose coordinates in that plane are smaller than that of root
node. Similarly, the right subtree will contain all points whose
coordinates in that plane are greater-equal to that of root node.
Creation of a 2-D Tree:
Consider following points in a 2-D plane:
(3, 6), (17, 15), (13, 15), (6, 12), (9, 1), (2, 7), (10, 19)
1
2
5
6
7
Insert (3, 6): Since tree is empty, make it the root node.
Insert (17, 15): Compare it with root node point. Since root node is
X-aligned, the X-coordinate value will be compared to determine if
it lies in the rightsubtree or in the right subtree. This point will be Yaligned.
Insert (13, 15): X-value of this point is greater than X-value of point
in root node. So, this will lie in the right subtree of (3, 6). Again
Compare Y-value of this point with the Y-value of point (17, 15)
(Why?). Since, they are equal, this point will lie in the right subtree
of (17, 15). This point will be X-aligned.
Insert (6, 12): X-value of this point is greater than X-value of point
in root node. So, this will lie in the right subtree of (3, 6). Again
Compare Y-value of this point with the Y-value of point (17, 15)
(Why?). Since, 12 < 15, this point will lie in the left subtree of (17,
15). This point will be X-aligned.
Insert (9, 1):Similarly, this point will lie in the right of (6, 12).
Insert (2, 7):Similarly, this point will lie in the left of (3, 6).
Insert (10, 19): Similarly, this point will lie in the left of (13, 15).
Point (3, 6) will divide the space into two parts: Draw line X = 3.
Point (2, 7) will divide the space to the left of line X = 3 into two
parts horizontally.
Draw line Y = 7 to the left of line X = 3.
Point (17, 15) will divide the space to the right of line X = 3 into
two parts horizontally.
Draw line Y = 15 to the right of line X = 3.
Point (6, 12) will divide the space below line Y = 15 and to the right
of line X = 3 into two parts.
Draw line X = 6 to the right of line X = 3 and below line Y = 15.
Point (13, 15) will divide the space below line Y = 15 and to the
right of line X = 6 into two parts.
Draw line X = 13 to the right of line X = 6 and below line Y = 15.
Point (10, 19) will divide the space to the right of line X = 3 and
above line Y = 15 into two parts.
Draw line Y = 19 to the right of line X = 3 and above line Y = 15.
}
// Creates and returns an Input structure
struct Input* CreateInput(unsigned k, unsigned n)
{
struct Input* input = new Input;
// Memory allocation failure
assert(NULL != input);
input->n = n;
input->pointArray = new Point*[n];
// Memory allocation failure
assert(NULL != input->pointArray);
return input;
}
// A method to create a node of K D tree
struct Node* CreateNode(struct Point* point)
{
struct Node* tempNode = new Node;
// Memory allocation failure
assert(NULL != tempNode);
// Avoid shallow copy [We could have directly use
// the below assignment, But didn't, why?]
/*tempNode->point = point;*/
(tempNode->point).k = point->k;
(tempNode->point).coord = new int[point->k];
// Copy coordinate values
for (int i=0; i<(tempNode->point).k; ++i)
(tempNode->point).coord[i] = point->coord[i];
tempNode->left = tempNode->right = NULL;
return tempNode;
}
// Root is passed as pointer to pointer so that
// The parameter depth is used to decide axis of comparison
void InsertKDTreeUtil(Node * * root, Node* newNode, unsigned depth)
{
// Tree is empty?
if (!*root)
{
*root = newNode;
return;
}
// Calculate axis of comparison to determine left/right
unsigned axisOfComparison = depth % (newNode->point).k;
// Compare the new point with root and decide the left or
// right subtree
if ((newNode->point).coord[axisOfComparison] <
((*root)->point).coord[axisOfComparison])
InsertKDTreeUtil(&((*root)->left), newNode, depth + 1);
else
InsertKDTreeUtil(&((*root)->right), newNode, depth + 1);
}
// Function to insert a new point in KD Tree. It mainly uses
// above recursive function "InsertKDTreeUtil()"
void InsertKDTree(Node* *root, Point* point)
{
Node* newNode = CreateNode(point);
unsigned zeroDepth = 0;
InsertKDTreeUtil(root, newNode, zeroDepth);
}
// A utility method to determine if two Points are same
// in K Dimensional space
int ArePointsSame(Point firstPoint, Point secondPoint)
{
if (firstPoint.k != secondPoint.k)
return 0;
// Compare individual coordinate values
for (int i = 0; i < firstPoint.k; ++i)
if (firstPoint.coord[i] != secondPoint.coord[i])
return 0;
return 1;
}
// Searches a Point in the K D tree. The parameter depth is used
// to determine current axis.
int SearchKDTreeUtil(Node* root, Point point, unsigned depth)
{
if (!root)
return 0;
if (ArePointsSame(root->point, point))
return 1;
Output:
17
140
94
1818
24
55
17
Inorder traversal of K-D Tree created is:
17
140
24
17
55
94
1818
Source
http://www.geeksforgeeks.org/k-dimensional-tree/
Category: Trees Tags: Advance Data Structures, Advanced Data
Structures
Post navigation
Amazon interview Experience | Set 141 (For SDE1) Ukkonens Suffix
Tree Construction Part 4
Writing code in comment? Please use code.geeksforgeeks.org,
generate link and share the link here.
Binomial Heap
The main application of Binary Heapis as implement priority queue.
Binomial Heap is an extension of Binary Heapthat provides faster union
or merge operation together with other operations provided by Binary
Heap.
A Binomial Heap is a collection of Binomial Trees
What is a Binomial Tree?
A Binomial Tree of order 0 has 1 node. A Binomial Tree of order k can
be constructed by taking two binomial trees of order k-1, and making
one as leftmost child of other.
A Binomial Tree of order k has following properties.
a) It has exactly 2k nodes.
b) It has depth as k.
c) There are exactly kCi nodes at depth i for i = 0, 1, . . . , k.
d) The root has degree k and children of root are themselves Binomial
Trees with order k-1, k-2,.. 0 from left to right.
The following diagram is taken from 2nd Edition of CLRS book.
Binomial Heap:
A Binomial Heap is a set of Binomial Trees where each Binomial Tree
follows Min Heap property. And there can be at-most one Binomial Tree
of any degree.
Examples Binomial Heap:
12------------10--------------------20
/ \
/ |\
15 50
70 50 40
|
/| |
30
80 85 65
|
100
A Binomial Heap with 13 nodes. It is a collection of 3
Binomial Trees of orders 0, 2 and 3 from left to right.
10--------------------20
/ \
/ |\
15 50
70 50 40
|
/| |
30
80 85 65
|
100
Source
http://www.geeksforgeeks.org/binomial-heap-2/
//Driver function.
int main()
{
/* Change third ipAddress for validation */
char ipAdd[][MAX] = {"107.108.11.123", "107.109.123.255",
"74.125.200.106"};
char URL[][50] = {"www.samsung.com", "www.samsung.net",
"www.google.in"};
int n = sizeof(ipAdd)/sizeof(ipAdd[0]);
struct trieNode *root = newTrieNode();
// Inserts all the ip address and their corresponding
// domain name after ip address validation.
for (int i=0; i<n; i++)
insert(root,ipAdd[i],URL[i]);
// If reverse DNS look up succeeds print the domain
// name along with DNS resolved.
char ip[] = "107.108.11.123";
char *res_url = searchDNSCache(root, ip);
if (res_url != NULL)
printf("Reverse DNS look up resolved in cache:\n%s --> %s",
ip, res_url);
else
printf("Reverse DNS look up not resolved in cache ");
return 0;
}
Output:
Reverse DNS look up resolved in cache:
107.108.11.123 --> www.samsung.com
Note that the above implementation of Trie assumes that the given IP
address does not contain characters other than {0, 1,.. 9, .}.
What if a user gives an invalid IP address that contains some other
characters? This problem can be resolved by validating the input IP
address before inserting it into Trie. We can use the approach
discussed herefor IP address validation.
This article is contributed by Kumar Gautam. Please write comments
if you find anything incorrect, or you want to share more information
about the topic discussed above
Source
http://www.geeksforgeeks.org/implement-reverse-dns-look-cache/
Category: Trees Tags: Advance Data Structures, Advanced Data
Structures
The update process needs to make sure that all BITree nodes that have
arr[i] as part of the section they cover must be updated. We get all
such nodes of BITree by repeatedly adding the decimal number
corresponding to the last set bit.
index = index + 1;
// Traverse all ancestors and add 'val'
while (index <= n)
{
// Add 'val' to current node of BI Tree
BITree[index] += val;
// Update index to that of parent
index += index & (-index);
}
}
// Constructs and returns a Binary Indexed Tree for given
// array of size n.
int *constructBITree(int arr[], int n)
{
// Create and initialize BITree[] as 0
int *BITree = new int[n+1];
for (int i=1; i<=n; i++)
BITree[i] = 0;
// Store the actual values in BITree[] using update()
for (int i=0; i<n; i++)
updateBIT(BITree, n, i, arr[i]);
// Uncomment below lines to see contents of BITree[]
//for (int i=1; i<=n; i++)
//
cout << BITree[i] << " ";
return BITree;
}
return 0;
}
Output:
Sum of elements in arr[0..5] is 12
Sum of elements in arr[0..5] after update is 18
Can we extend the Binary Indexed Tree for range Sum in Logn
time?
This is simple to answer. The rangeSum(l, r) can be obtained as
getSum(r) getSum(l-1).
Applications:
Used to implement the arithmetic coding algorithm. Development of
operations it supports were primarily motivated by use in that case.
See thisfor more details.
References:
http://en.wikipedia.org/wiki/Fenwick_tree
http://community.topcoder.com/tc?
module=Static&d1=tutorials&d2=binaryIndexedTrees
Please write comments if you find anything incorrect, or you want to
share more information about the topic discussed above
Source
http://www.geeksforgeeks.org/binary-indexed-tree-or-fenwick-tree-2/