Data Structure and Algorithm
Data Structure and Algorithm
What is an Algorithm?
Step 1: Start
Step 4: Add num1 and num2 and assign the result to sum.
sum←num1+num2
Step 6: Stop
Step 1: Start
Step 4: If a > b
If a > c
Else
Else
If b > c
Else
Display c is the greatest number.
Step 5: Stop
D ← b2-4ac
Step 4: If D ≥ 0
r1 ← (-b+√D)/2a
r2 ← (-b-√D)/2a
Else
rp ← -b/2a
ip ← √(-D)/2a
Step 5: Stop
Array
data Structure Representation
Note: Data structure and data types are slightly different. Data structure is
the collection of data types arranged in a specific order.
In linear data structures, the elements are arranged in sequence one after
the other. Since elements are arranged in particular order, they are easy to
implement.
However, when the complexity of the program increases, the linear data
structures might not be the best choice because of operational
complexities.
In stack data structure, elements are stored in the LIFO principle. That is,
the last element stored in a stack will be removed first.
It works just like a pile of plates where the last plate kept on the pile will be
removed first. To learn more, visit Stack Data Structure.
In a stack, operations can be perform only from one end (top
here).
Unlike stack, the queue data structure works in the FIFO principle where
first element stored in the queue will be removed first.
It works just like a queue of people in the ticket counter where first person
on the queue will get the ticket first. To learn more, visit Queue Data
Structure.
In linked list data structure, data elements are connected through a series
of nodes. And, each node contains the data items and address to the next
node.
Non linear data structures
Unlike linear data structures, elements in non-linear data structures are not
in any sequence. Instead they are arranged in a hierarchical manner where
one element will be connected to one or more elements.
Non-linear data structures are further divided into graph and tree based
data structures.
In graph data structure, each node is called vertex and each vertex is
connected to other vertices through edges.
Binary Tree
Binary Search Tree
AVL Tree
B-Tree
B+ Tree
Red-Black Tree
Now that we know about linear and non-linear data structures, let's see the
major differences between them.
The data items are arranged in sequential order, The data items are arranged in non-sequential
one after the other. order (hierarchical manner).
All the items are present on the single layer. The data items are present at different layers.
It can be traversed on a single run. That is, if we It requires multiple runs. That is, if we start from
start from the first element, we can traverse all the first element it might not be possible to
the elements sequentially in a single pass. traverse all the elements in a single pass.
The time complexity increase with the data size. Time complexity remains the same.
This article is for those who have just started learning algorithms and
wondered how impactful it will be to boost their career/programming skills.
It is also for those who wonder why big companies like Google, Facebook,
and Amazon hire programmers who are exceptionally good at optimizing
Algorithms.
Initialize fact = 1
int factorial(int n) {
int fact = 1;
for (int v = 1; v <= n; v++) {
fact = fact * v;
}
return fact;
}
Time is precious.
Suppose, Alice and Bob are trying to solve a simple problem of finding the
sum of the first 1011 natural numbers. While Bob was writing the algorithm,
Alice implemented it proving that it is as simple as criticizing Donald Trump.
Algorithm (by Bob)
Initialize sum = 0
int findSum() {
int sum = 0;
for (int v = 1; v <= 100000000000; v++) {
sum += v;
}
return sum;
}
Alice and Bob are feeling euphoric of themselves that they could build
something of their own in almost no time. Let's sneak into their workspace
and listen to their conversation.
Alice: Let's run this code and find out the sum.
Bob: I ran this code a few minutes back but it's still not showing the
output. What's wrong with it?
The number of instructions depends on the code you used, and the time
taken to execute each code depends on your machine and compiler.
In this case, the total number of instructions executed (let's say x) are x = 1
Hence,
Is it possible to optimize the algorithm so that Alice and Bob do not have to
wait for 33 minutes every time they run this code?
I am sure that you already guessed the right method. The sum of
first N natural numbers is given by the formula:
Sum = N * (N + 1) / 2
int sum(int N) {
return N * (N + 1) / 2;
}
This code executes in just one instruction and gets the task done no matter
what the value is. Let it be greater than the total number of atoms in the
universe. It will find the result in no time.
The time taken to solve the problem, in this case, is 1/y (which is 10
nanoseconds). By the way, the fusion reaction of a hydrogen bomb takes
40-50 ns, which means your program will complete successfully even if
someone throws a hydrogen bomb on your computer at the same time you
ran your code. :)
More on Scalability
But what if the size of the problem increases? What if the number of
students increased to 200?
The solution still holds but it needs more resources. In this case, you will
probably need a much larger room (probably a theater), a projector screen
and a digital pen.
What if the number of students increased to 1000?
The solution fails or uses a lot of resources when the size of the problem
increases. This means, your solution wasn't scalable.
Memory is expensive
Here are some examples of what learning algorithms and data structures
enable you to do:
Problems like finding the people of a certain age group can easily be
solved with a little modified version of the binary search
algorithm (assuming that the data is sorted).
The naive algorithm which goes through all the persons one by one, and
checks if it falls in the given age group is linearly scalable. Whereas, binary
search claims itself to be a logarithmically scalable algorithm. This means
that if the size of the problem is squared, the time taken to solve it is only
doubled.
Suppose, it takes 1 second to find all the people at a certain age for a
group of 1000. Then for a group of 1 million people,
the binary search algorithm will take only 2 seconds to solve the
problem
The same binary search algorithm is used to find the square root of a
number.
Imagine you are writing a program to find the solution of a Rubik's cube.
This cute looking puzzle has annoyingly 43,252,003,274,489,856,000
positions, and these are just positions! Imagine the number of paths one
can take to reach the wrong positions.
Fortunately, the way to solve this problem can be represented by the graph
data structure. There is a graph algorithm known as Dijkstra's
algorithm which allows you to solve this problem in linear time. Yes, you
heard it right. It means that it allows you to reach the solved position in a
minimum number of states.
A typical DNA strand has millions of such units. Eh! worry not. KMP
algorithm can get this done in time which is proportional to
Final Words
If you don't know algorithms well, you won't be able to identify if you can
optimize the code you are writing right now. You are expected to know
them in advance and apply them wherever possible and critical.
However, it's important to note that this is not the only way to make a
system scalable. For example, a technique known as distributed
computing allows independent parts of a program to run to multiple
machines together making it even more scalable.
Asymptotic Analysis: Big-O
Notation and More
In this tutorial, you will learn what asymptotic notations are. Also, you will
learn about Big-O notation, Theta notation and Omega notation.
An algorithm may not have the same performance for different types of
inputs. With the increase in the input size, the performance will change.
The study of change in performance of the algorithm with the change in the
order of the input size is defined as asymptotic analysis.
Asymptotic Notations
For example: In bubble sort, when the input array is already sorted, the
time taken by the algorithm is linear i.e. the best case.
But, when the input array is in reverse condition, the algorithm takes the
maximum time (quadratic) to sort the elements i.e. the worst case.
When the input array is neither sorted nor in reverse order, then it takes
average time. These durations are denoted using asymptotic notations.
Big-O notation
Omega notation
Theta notation
Big-O gives
the upper bound of a function
O(g(n)) = { f(n): there exist positive constants c and n0
such that 0 ≤ f(n) ≤ cg(n) for all n ≥ n0 }
Theta notation encloses the function from above and below. Since it
represents the upper and the lower bound of the running time of an
algorithm, it is used for analyzing the average-case complexity of an
algorithm.
Theta bounds
the function within constants factors
Master Theorem
In this tutorial, you will learn what master theorem is and how it is used for
solving recurrence relations.
The master method is a formula for solving recurrence relations of the form:
n = size of input
Master Theorem
ϵ > 0 is a constant.
T(n) = 3T(n/2) + n2
Here,
a = 3
n/b = n/2
f(n) = n2
a < 1
In this tutorial, you will learn how the divide and conquer algorithm works.
We will also compare the divide and conquer approach versus other
approaches to solve a recursive problem.
To use the divide and conquer algorithm, recursion is used. Learn about
recursion in different programming languages:
Recursion in Java
Recursion in Python
Recursion in C++
Here, we will sort an array using the divide and conquer approach
(ie. merge sort).
Com
bine the subparts
Time Complexity
n = size of input
n/b = size of each subproblem. All subproblems are assumed to have the
same size.
f(n) = cost of the work done outside the recursive call, which includes
the cost of dividing the problem and cost of merging the solutions
= 2T(n/2) + O(n)
Where,
f(n) = time taken to divide the problem and merging the subproblems
T(n/2) = O(n log n) (To understand this, please refer to the master
theorem.)
≈ O(n log n)
Use the divide and conquer approach when the same subproblem is not
solved multiple times. Use the dynamic approach when the result of a
subproblem is to be used multiple times in the future.
Let us understand this with an example. Suppose we are trying to find the
Fibonacci series. Then,
fib(n)
If n < 2, return 1
Dynamic approach:
mem = []
fib(n)
else,
If n < 2, f = 1
mem[n] = f
return f
The complexity for the multiplication of two matrices using the naive
method is O(n3) , whereas using the divide and conquer approach (i.e.
Strassen's matrix multiplication) is O(n2.8074) . This approach also
simplifies other problems, such as the Tower of Hanoi.
This approach is suitable for multiprocessing systems.
Binary Search
Merge Sort
Quick Sort
Strassen's Matrix multiplication
Karatsuba Algorithm
In this tutorial, you will learn about the stack data structure and its
implementation in Python, Java and C/C++.
A stack is a linear data structure that follows the principle of Last In First
Out (LIFO). This means the last element inserted inside the stack is
removed first.
You can think of the stack data structure as the pile of plates on top of
another.
Stack representation similar to a pile of plate
And, if you want the plate at the bottom, you must first remove all the plates
on top. This is exactly how the stack data structure works.
In the above image, although item 3 was kept last, it was removed first.
This is exactly how the LIFO (Last In First Out) Principle works.
We can implement a stack in any programming language like C, C++, Java,
Python or C#, but the specification is pretty much the same.
Basic Operations of Stack
There are some basic operations that allow us to perform different actions
on a stack.
1. A pointer called TOP is used to keep track of the top element in the
stack.
2. When initializing the stack, we set its value to -1 so that we can
check if the stack is empty by comparing TOP == -1 .
To reverse a word - Put all the letters in a stack and pop them out.
Because of the LIFO order of stack, you will get the letters in reverse
order.
In compilers - Compilers use the stack to calculate the value of
expressions like 2 + 4 / 5 * (7 - 9) by converting the expression to
prefix or postfix form.
In browsers - The back button in a browser saves all the URLs you
have visited previously in a stack. Each time you visit a new page, it
is added on top of the stack. When you press the back button, the
current URL is removed from the stack, and the previous URL is
accessed.
Queue Data Structure
In this tutorial, you will learn what a queue is. Also, you will find
implementation of queue in C, C++, Java and Python.
Queue follows the First In First Out (FIFO) rule - the item that goes in first
is the item that comes out first.
In the above image, since 1 was kept in the queue before 2, it is the first to
be removed from the queue as well. It follows the FIFO rule.
In programming terms, putting items in the queue is called enqueue, and
removing items from the queue is called dequeue.
We can implement the queue in any programming language like C, C++,
Java, Python or C#, but the specification is pretty much the same.
A queue is an object (an abstract data structure - ADT) that allows the
following operations:
Working of Queue
Dequeue Operation
As you can see in the image below, after a bit of enqueuing and dequeuing,
the size of the queue has been reduced.
Limitation of a queue
And we can only add indexes 0 and 1 only when the queue is reset (when
all the elements have been dequeued).
After REAR reaches the last index, if we can store extra elements in the
empty spaces (0 and 1), we can make use of the empty spaces. This is
implemented by a modified queue called the circular queue.
Complexity Analysis
Applications of Queue
Types of Queues
In this tutorial, you will learn different types of queues with along with
illustration.
Simple Queue
Circular Queue
Priority Queue
Simple Queue
In a simple queue, insertion takes place at the rear and removal occurs at
the front. It strictly follows the FIFO (First in First out) rule.
Circular Queue
In a circular queue, the last element points to the first element making a
circular link.
Priority Queue
Insertion occurs based on the arrival of the values and removal occurs
based on priority.
Deque Representation
In this tutorial, you will learn what a circular queue is. Also, you will find
implementation of circular queue in C, C++, Java and Python.
A circular queue is the extended version of a regular queue where the last
element is connected to the first element. Thus forming a circle-like
structure.
Circular queue representation
The circular queue solves the major limitation of the normal queue. In a
normal queue, after a bit of insertion and deletion, there will be non-usable
empty space.
Here, indexes 0 and 1 can only be used after resetting the queue (deletion
of all elements). This reduces the actual size of the queue.
Circular Queue works by the process of circular increment i.e. when we try
to increment the pointer and we reach the end of the queue, we start from
the beginning of the queue.
Here, the circular increment is performed by modulo division with the queue
size. That is,
if REAR + 1 == 5 (overflow!), REAR = (REAR + 1)%5 = 0 (start of queue)
2. Dequeue Operation
CPU scheduling
Memory management
Traffic Management
Priority Queue
In this tutorial, you will learn what priority queue is. Also, you will learn
about it's implementations in Python, Java, C, and C++.
The element with the highest value is considered the highest priority
element. However, in other cases, we can assume the element with the
lowest value as the highest priority element.
We can also set priorities according to our needs.
Removing Highest
Priority Element
Priority queue can be implemented using an array, a linked list, a heap data
structure, or a binary search tree. Among these data structures, heap data
structure provides an efficient implementation of priority queues.
Hence, we will be using the heap data structure to implement the priority
queue in this tutorial. A max-heap is implemented in the following
operations. If you want to learn more about it, please visit max-heap and
min-heap.
A comparative analysis of different implementations of priority queue is
given below.
Before studying the priority queue, please refer to the heap data
structure for a better understanding of binary heap as it is used to
implement the priority queue in this article.
If there is no node,
create a newNode.
insert the newNode at the end (last node from left to right.)
For Min Heap, the above algorithm is modified so that parentNode is always
smaller than newNode .
remove noteToBeDeleted
Peek operation returns the maximum element from Max Heap or minimum
element from Min Heap without deleting the node.
Extract-Max returns the node with maximum value after removing it from a
Max Heap whereas Extract-Min returns the node with minimum value after
removing it from Min Heap.
Dijkstra's algorithm
In this tutorial, you will learn what a double ended queue (deque) is. Also,
you will find working examples of different operations on a deque in C, C+
+, Java and Python.
Representation of Deque
Types of Deque
Operations on a Deque
Check if deque is
empty
1 and rear = -1 .
Check if deque is
empty
Time Complexity
The time complexity of all the above operations is constant i.e. O(1) .
In this tutorial, you will learn about linked list data structure and it's
You have to start somewhere, so we give the address of the first node a
special name called HEAD . Also, the last node in the linked list can be
identified because its next portion points to NULL .
Linked lists can be of multiple types: singly, doubly, and circular linked
list. In this article, we will focus on the singly linked list. To learn about
other types, visit Types of Linked List.
Note: You might have played the game Treasure Hunt, where each clue
includes the information about the next clue. That is how the linked list
operates.
Let's see how each node of the linked list is represented. Each node
consists:
A data item
We wrap both the data item and the next node reference in a struct as:
struct node
{
int data;
struct node *next;
};
Each struct node has a data item and a pointer to another struct node. Let
us create a simple Linked List with three items to understand how this
works.
/* Initialize nodes */
struct node *head;
struct node *one = NULL;
struct node *two = NULL;
struct node *three = NULL;
/* Allocate memory */
one = malloc(sizeof(struct node));
two = malloc(sizeof(struct node));
three = malloc(sizeof(struct node));
/* Connect nodes */
one->next = two;
two->next = three;
three->next = NULL;
If you didn't understand any of the lines above, all you need is a refresher
on pointers and structs.
In just a few steps, we have created a simple linked list with three nodes.
Linked list Representation
The power of a linked list comes from the ability to break the chain and
rejoin it. E.g. if you wanted to put an element 4 between 1 and 2, the steps
would be:
Point its next pointer to the struct node containing 2 as the data value
Time Complexity
In this tutorial, you will learn different operations on a linked list. Also, you
will find implementation of linked list operations in C/C++, Python and Java.
There are various linked list operations that allow us to perform different
actions on linked lists. For example, the insertion operation adds a new
element to the linked list.
Here's a list of basic linked list operations that we will cover in this article.
struct node {
int data;
struct node *next;
};
Traverse a Linked List
Displaying the contents of a linked list is very simple. We keep moving the
temp node to the next one and display its contents.
When temp is NULL , we know that we have reached the end of the linked list
so we get out of the while loop.
You can add elements to either the beginning, middle or end of the linked
list.
Store data
Store data
temp->next = newNode;
You can delete either from the beginning, end or from a particular position.
head = head->next;
temp->next = temp->next->next;
You can search an element on a linked list using a loop using the following
steps. We are finding item on a linked list.
Make head as the current node.
Run a loop until the current node is NULL because the last element
points to NULL .
In each iteration, check if the key of the node is equal to item . If it the
key matches the item, return true otherwise return false .
// Search a node
bool searchNode(struct Node** head_ref, int key) {
struct Node* current = *head_ref;
We will use a simple sorting algorithm, Bubble Sort, to sort the elements of
a linked list in ascending order below.
1. Make the head as the current node and create another
node index for later use.
2. If head is null, return.
3. Else, run a loop till the last node (i.e. NULL ).
6. Check if the data of the current node is greater than the next node. If
it is greater, swap current and index .
circular
In this tutorial, you will learn different types of linked list. Also, you will find
implementation of linked list in C.
Before you learn about the type of the linked list, make sure you know
about the LinkedList Data Structure.
There are three common types of Linked List.
It is the most common. Each node has data and a pointer to the next node.
struct node {
int data;
struct node *next;
}
/* Initialize nodes */
struct node *head;
struct node *one = NULL;
struct node *two = NULL;
struct node *three = NULL;
/* Allocate memory */
one = malloc(sizeof(struct node));
two = malloc(sizeof(struct node));
three = malloc(sizeof(struct node));
/* Connect nodes */
one->next = two;
two->next = three;
three->next = NULL;
A node is represented as
struct node {
int data;
struct node *next;
struct node *prev;
}
/* Initialize nodes */
struct node *head;
struct node *one = NULL;
struct node *two = NULL;
struct node *three = NULL;
/* Allocate memory */
one = malloc(sizeof(struct node));
two = malloc(sizeof(struct node));
three = malloc(sizeof(struct node));
/* Connect nodes */
one->next = two;
one->prev = NULL;
two->next = three;
two->prev = one;
three->next = NULL;
three->prev = two;
If you want to learn more about it, please visit doubly linked list and
operations on it.
A circular linked list is a variation of a linked list in which the last element is
linked to the first element. This forms a circular loop.
Circ
ular linked list
for singly linked list, next pointer of last item points to the first item
In the doubly linked list, prev pointer of the first item points to the last
item as well.
A three-member circular singly linked list can be created as:
/* Initialize nodes */
struct node *head;
struct node *one = NULL;
struct node *two = NULL;
struct node *three = NULL;
/* Allocate memory */
one = malloc(sizeof(struct node));
two = malloc(sizeof(struct node));
three = malloc(sizeof(struct node));
/* Connect nodes */
one->next = two;
two->next = three;
three->next = one;
Hash Table
In this tutorial, you will learn what hash table is. Also, you will find working
examples of hash table operations in C, C++, Java and Python.
The Hash table data structure stores elements in key-value pairs where
In a hash table, a new index is processed using the keys. And, the element
corresponding to that key is stored in the index. This process is
called hashing.
Let k be a key and h(x) be a hash function.
Here, h(k) will give us a new index to store the element linked with k
Hash Collision
When the hash function generates the same index for multiple keys, there
will be a conflict (what value to be stored in that index). This is called
a hash collision.
We can resolve the hash collision using one of the following techniques.
If j is the slot for multiple elements, it contains a pointer to the head of the
list of elements. If no element is present, j contains NIL .
chainedHashSearch(T, k)
return T[h(k)]
chainedHashInsert(T, x)
T[h(x.key)] = x //insert at the head
chainedHashDelete(T, x)
T[h(x.key)] = NIL
2. Open Addressing
Unlike chaining, open addressing doesn't store multiple elements into the
same slot. Here, each slot is either filled with a single key or left NIL .
i. Linear Probing
where
i = {0, 1, ….}
It works similar to linear probing but the spacing between the slots is
increased (greater than one) by using the following relation.
where,
If a collision occurs after applying a hash function h(k) , then another hash
function is calculated for finding the next slot.
h(k, i) = (h1(k) + ih2(k)) mod m
Good Hash Functions
A good hash function may not prevent the collisions completely however it
can reduce the number of collisions.
Here, we will look into different methods to find a good hash function
1. Division Method
If k is a key and m is the size of the hash table, the hash function h() is
calculated as:
h(k) = k mod m
For example, If the size of a hash table is 10 and k = 112 then h(k) =
2. Multiplication Method
where,
cryptographic applications
Heap data structure is a complete binary tree that satisfies the heap
property, where any given node is
always greater than its child node/s and the key of the root node is
the largest among all other nodes. This property is also called max
heap property.
always smaller than the child node/s and the key of the root node is
the smallest among all other nodes. This property is also called min
heap property.
MAX HEAP
Min-heap
Heapify
Heapify is the process of creating a heap data structure from a binary tree.
It is used to create a Min-Heap or a Max-Heap.
Initial Array
3. Start from the first index of non-leaf node whose index is given
by n/2- 1 .
Start from the first on leaf node
4. Set current element i as largest .
5. The index of left child is given by 2i + 1 and the right child is given
by 2i + 2 .
Swap if necessary
7. Repeat steps 3-7 until the subtrees are also heapified.
Algorithm
Heapify(array, size, i)
set i as largest
leftChild = 2i + 1
rightChild = 2i + 2
To create a Max-Heap:
MaxHeap(array, size)
loop from the first index of non-leaf node down to zero
call heapify
For Min-Heap, both leftChild and rightChild must be larger than the
parent for all nodes.
If there is no node,
create a newNode.
else (a node is already present)
insert the newNode at the end (last node from left to right.)
e
H Heapify the array
For Min Heap, the above algorithm is modified so that parentNode is always
smaller than newNode .
Peek operation returns the maximum element from Max Heap or minimum
element from Min Heap without deleting the node.
return rootNode
Extract-Max/Min
Extract-Max returns the node with maximum value after removing it from a
Max Heap whereas Extract-Min returns the node with minimum after
removing it from Min Heap.
Heap Data Structure Applications
Dijkstra's Algorithm
Heap Sort
Fibonacci Heap
In this tutorial, you will learn what a Fibonacci Heap is. Also, you will find
working examples of different operations on a fibonacci heap in C, C++,
Java and Python.
A fibonacci heap is a data structure that consists of a collection of trees
which follow min heap or max heap property. We have already
discussed min heap and max heap property in the Heap Data
Structure article. These two properties are the characteristics of the trees
present on a fibonacci heap.
In a fibonacci heap, a node can have more than two children or no children
at all. Also, it has more efficient heap operations than that supported by the
binomial and binary heaps.
The fibonacci heap is called a fibonacci heap because the trees are
constructed in a way such that a tree of order n has at least Fn+2 nodes in it,
where Fn+2 is the (n + 2)th Fibonacci number.
Fibonacci Heap
The roots of all the trees are linked together for faster access. The child
nodes of a parent node are connected to each other through a circular
doubly linked list as shown below.
There are two main advantages of using a circular doubly linked list.
Insertion
Algorithm
insert(H, x)
degree[x] = 0
p[x] = NIL
child[x] = NIL
left[x] = x
right[x] = x
mark[x] = FALSE
then min[H] = x
n[H] = n[H] + 1
Inserting a node into an already existing heap follows the steps below.
3. If the heap is empty, set the new node as a root node and mark
it min .
4. Else, insert the node into the root list and update min .
I
nsertion Example
Find Min
2. Update min by selecting a minimum key from the new root lists.
Extract Min
4. Do the following (steps 5-7) until there are no multiple roots with the
same degree.
Fibonacci Heap
2. Delete the min node, add all its child nodes to the root list and set the
min-pointer to the next root in the root list.
Uni
te those having the same degrees
Uni
te those having the same degrees
6. Again 7 and 24 have the same degree, so unite them.
Un
ite those having the same degrees
These are the most important operations which are discussed in Decrease
Key and Delete Node Operations.
Complexities
Insertion O(1)
Union O(1)
Fibonacci Heap
In this tutorial, you will learn how decrease key and delete node operations
work. Also, you will find working examples of these operations on a
fibonacci heap in C, C++, Java and Python.
A fibonacci heap is a tree based data structure which consists of a
collection of trees with min heap or max heap property. Its operations are
more efficient in terms of time complexity than those of its similar data
structures like binomial heap and binary heap.
Now, we will discuss two of its important operations.
1. Decrease a key: decreases the value of a the key to any lower value
2. Delete a node: deletes the given node
Decreasing a Key
Decrease-Key
1. Select the node to be decreased, x , and change its value to the new
value k .
2. If the parent of x , y , is not null and the key of parent is greater than
that of the k then call Cut(x) and Cascading-Cut(y) subsequently.
3. If the key of x is smaller than the key of min, then mark x as min.
Cut
1. Remove x from the current position and add it to the root list.
2. If x is marked, then mark it as false.
Cascading-Cut
Decrease 46 to 15
2. Cut part: Since 24 ≠ nill and 15 < its parent , cut it and add it to
the root list. Cascading-Cut part: mark 24.
Decrease 35 to 5
2. Cut part: Since 26 ≠ nill and 5<its parent , cut it and add it to the
root list.
Cut 5 and add it to root list
3. Cascading-Cut part: Since 26 is marked, the flow goes
to Cut and Cascading-Cut .
Cut(26): Cut 26 and add it to the root list and mark it as false.
C
u Cut 26 and add it to root list
Cascading-Cut(24):
Since the 24 is also marked, again call Cut(24) and Cascading-
Mark 5 as min
Deleting a Node
In this tutorial, you will learn about tree data structure. Also, you will learn
about different types of trees and the terminologies used in tree.
A Tree
Other data structures such as arrays, linked list, stack, and queue are
linear data structures that store data sequentially. In order to perform any
operation in a linear data structure, the time complexity increases with the
increase in the data size. But, it is not acceptable in today's computational
world.
Different tree data structures allow quicker and easier access to the data as
it is a non-linear data structure.
Tree Terminologies
Node
A node is an entity that contains a key or value and pointers to its child
nodes.
The last nodes of each path are called leaf nodes or external nodes that
do not contain a link/pointer to child nodes.
The node having at least a child node is called an internal node.
Edge
Root
Height of a Node
The height of a node is the number of edges from the node to the deepest
leaf (ie. the longest path from the node to a leaf node).
Depth of a Node
The depth of a node is the number of edges from the root to the node.
Height of a Tree
The height of a Tree is the height of the root node or the depth of the
deepest node.
Height and depth of each node in a tree
Degree of a Node
Forest
Types of Tree
1. Binary Tree
2. Binary Search Tree
3. AVL Tree
4. B-Tree
Tree Traversal
Tree Applications
Most popular databases use B-Trees and T-Trees, which are variants
of the tree structure we learned above to store their data