Cartesian Sort is an Adaptive Sorting as it sorts the data faster if data is partially sorted. In fact, there are very few sorting algorithms that make use of this fact. For example consider the array {5, 10, 40, 30, 28}. The input data is partially sorted too as only one swap between “40” and “28” results in a completely sorted order.
See how Cartesian Tree Sort will take advantage of this fact below. Below are steps used for sorting.
Step 1 : Build a (min-heap) Cartesian Tree from the given input sequence.
Applications for Cartesian Tree Sorting:
- It is possible to quantify how much faster algorithm will run than O(nlogn) using a measurement called oscillation. Practically, the complexity is close to O(nlog(Osc)) (where Osc is oscillation).
- Oscillation is small if the sequence is partially sorted, hence the algorithm performs faster with partially sorted sequences.
Step 2 : Starting from the root of the built Cartesian Tree, we push the nodes in a priority queue. Then we pop the node at the top of the priority queue and push the children of the popped node in the priority queue in a pre-order manner.
- Pop the node at the top of the priority queue and add it to a list.
- Push left child of the popped node first (if present).
- Push right child of the popped node next (if present).

How to build (min-heap) Cartesian Tree?
Building min-heap is similar to building a (max-heap) Cartesian Tree (discussed in previous post), except the fact that now we scan upward from the node's parent up to the root of the tree until a node is found whose value is smaller (and not larger as in the case of a max-heap Cartesian Tree) than the current one and then accordingly reconfigure links to build the min-heap Cartesian tree.
Why not to use only priority queue?
One might wonder that using priority queue would anyway result in a sorted data if we simply insert the numbers of the input array one by one in the priority queue (i.e- without constructing the Cartesian tree). But the time taken differs a lot. Suppose we take the input array – {5, 10, 40, 30, 28} If we simply insert the input array numbers one by one (without using a Cartesian tree), then we may have to waste a lot of operations in adjusting the queue order everytime we insert the numbers (just like a typical heap performs those operations when a new number is inserted, as priority queue is nothing but a heap). Whereas, here we can see that using a Cartesian tree took only 5 operations (see the above two figures in which we are continuously pushing and popping the nodes of Cartesian tree), which is linear as there are 5 numbers in the input array also. So we see that the best case of Cartesian Tree sort is O(n), a thing where heap-sort will take much more number of operations, because it doesn’t make advantage of the fact that the input data is partially sorted.
Why pre-order traversal?
The answer to this is that since Cartesian Tree is basically a heap- data structure and hence follows all the properties of a heap. Thus the root node is always smaller than both of its children. Hence, we use a pre-order fashion popping-and-pushing as in this, the root node is always pushed earlier than its children inside the priority queue and since the root node is always less than both its child, so we don’t have to do extra operations inside the priority queue. Refer to the below figure for better understanding- 
Approach:
- Construct a Cartesian tree for given sequence.
- Create a priority queue, at first having only the root of Cartesian tree.
- Pop the minimum value x from the priority queue
- Add x to the output sequence
- Push the left child of x from Cartesian tree into priority queue.
- Push the right child of x from Cartesian tree into priority queue.
- If priority queue is not empty, again goto step 3.
Below is the implementation for the above approach:
CPP
// A C++ program to implement Cartesian Tree sort
// Note that in this program we will build a min-heap
// Cartesian Tree and not max-heap.
#include<bits/stdc++.h>
using namespace std;
/* A binary tree node has data, pointer to left child
and a pointer to right child */
struct Node
{
int data;
Node *left, *right;
};
// Creating a shortcut for int, Node* pair type
typedef pair<int, Node*> iNPair;
// This function sorts by pushing and popping the
// Cartesian Tree nodes in a pre-order like fashion
void pQBasedTraversal(Node* root)
{
// We will use a priority queue to sort the
// partially-sorted data efficiently.
// Unlike Heap, Cartesian tree makes use of
// the fact that the data is partially sorted
priority_queue <iNPair, vector<iNPair>, greater<iNPair>> pQueue;
pQueue.push (make_pair (root->data, root));
// Resembles a pre-order traverse as first data
// is printed then the left and then right child.
while (! pQueue.empty())
{
iNPair popped_pair = pQueue.top();
printf("%d ", popped_pair.first);
pQueue.pop();
if (popped_pair.second->left != NULL)
pQueue.push (make_pair(popped_pair.second->left->data,
popped_pair.second->left));
if (popped_pair.second->right != NULL)
pQueue.push (make_pair(popped_pair.second->right->data,
popped_pair.second->right));
}
return;
}
Node *buildCartesianTreeUtil(int root, int arr[],
int parent[], int leftchild[], int rightchild[])
{
if (root == -1)
return NULL;
Node *temp = new Node;
temp->data = arr[root];
temp->left = buildCartesianTreeUtil(leftchild[root],
arr, parent, leftchild, rightchild);
temp->right = buildCartesianTreeUtil(rightchild[root],
arr, parent, leftchild, rightchild);
return temp ;
}
// A function to create the Cartesian Tree in O(N) time
Node *buildCartesianTree(int arr[], int n)
{
// Arrays to hold the index of parent, left-child,
// right-child of each number in the input array
int parent[n], leftchild[n], rightchild[n];
// Initialize all array values as -1
memset(parent, -1, sizeof(parent));
memset(leftchild, -1, sizeof(leftchild));
memset(rightchild, -1, sizeof(rightchild));
// 'root' and 'last' stores the index of the root and the
// last processed of the Cartesian Tree.
// Initially we take root of the Cartesian Tree as the
// first element of the input array. This can change
// according to the algorithm
int root = 0, last;
// Starting from the second element of the input array
// to the last on scan across the elements, adding them
// one at a time.
for (int i = 1; i <= n - 1; i++)
{
last = i-1;
rightchild[i] = -1;
// Scan upward from the node's parent up to
// the root of the tree until a node is found
// whose value is smaller than the current one
// This is the same as Step 2 mentioned in the
// algorithm
while (arr[last] >= arr[i] && last != root)
last = parent[last];
// arr[i] is the smallest element yet; make it
// new root
if (arr[last] >= arr[i])
{
parent[root] = i;
leftchild[i] = root;
root = i;
}
// Just insert it
else if (rightchild[last] == -1)
{
rightchild[last] = i;
parent[i] = last;
leftchild[i] = -1;
}
// Reconfigure links
else
{
parent[rightchild[last]] = i;
leftchild[i] = rightchild[last];
rightchild[last]= i;
parent[i] = last;
}
}
// Since the root of the Cartesian Tree has no
// parent, so we assign it -1
parent[root] = -1;
return (buildCartesianTreeUtil (root, arr, parent,
leftchild, rightchild));
}
// Sorts an input array
int printSortedArr(int arr[], int n)
{
// Build a cartesian tree
Node *root = buildCartesianTree(arr, n);
printf("The sorted array is-\n");
// Do pr-order traversal and insert
// in priority queue
pQBasedTraversal(root);
}
/* Driver program to test above functions */
int main()
{
/* Given input array- {5,10,40,30,28},
it's corresponding unique Cartesian Tree
is-
5
\
10
\
28
/
30
/
40
*/
int arr[] = {5, 10, 40, 30, 28};
int n = sizeof(arr)/sizeof(arr[0]);
printSortedArr(arr, n);
return(0);
}
Java
// A Java program to implement Cartesian Tree sort
// Note that in this program we will build a min-heap
// Cartesian Tree and not max-heap.
import java.util.*;
public class Main {
/* A binary tree node has data, pointer to left child
and a pointer to right child */
static class Node {
int data;
Node left, right;
Node(int d)
{
data = d;
left = null;
right = null;
}
}
static class iNPair implements Comparable<iNPair> {
int first;
Node second;
iNPair(int f, Node s)
{
first = f;
second = s;
}
@Override public int compareTo(iNPair other)
{
return Integer.compare(first, other.first);
}
}
// This function sorts by pushing and popping the
// Cartesian Tree nodes in a pre-order like fashion
static void pQBasedTraversal(Node root)
{
// We will use a priority queue to sort the
// partially-sorted data efficiently.
// Unlike Heap, Cartesian tree makes use of
// the fact that the data is partially sorted
PriorityQueue<iNPair> pQueue
= new PriorityQueue<>();
pQueue.add(new iNPair(root.data, root));
// Resembles a pre-order traverse as first data
// is printed then the left and then right child.
while (!pQueue.isEmpty()) {
iNPair popped_pair = pQueue.poll();
System.out.print(popped_pair.first + " ");
if (popped_pair.second.left != null)
pQueue.add(
new iNPair(popped_pair.second.left.data,
popped_pair.second.left));
if (popped_pair.second.right != null)
pQueue.add(new iNPair(
popped_pair.second.right.data,
popped_pair.second.right));
}
}
static Node buildCartesianTreeUtil(int root, int arr[],
int parent[],
int leftchild[],
int rightchild[])
{
if (root == -1)
return null;
Node temp = new Node(arr[root]);
temp.left = buildCartesianTreeUtil(
leftchild[root], arr, parent, leftchild,
rightchild);
temp.right = buildCartesianTreeUtil(
rightchild[root], arr, parent, leftchild,
rightchild);
return temp;
}
// A function to create the Cartesian Tree in O(N) time
static Node buildCartesianTree(int arr[], int n)
{
// Arrays to hold the index of parent, left-child,
// right-child of each number in the input array
int parent[] = new int[n];
int leftchild[] = new int[n];
int rightchild[] = new int[n];
// Initialize all array values as -1
Arrays.fill(parent, -1);
Arrays.fill(leftchild, -1);
Arrays.fill(rightchild, -1);
// 'root' and 'last' stores the index of the root
// and the last processed of the Cartesian Tree.
// Initially we take root of the Cartesian Tree as
// the first element of the input array. This can
// change according to the algorithm
int root = 0, last;
// Starting from the second element of the input
// array to the last on scan across the elements,
// adding them one at a time.
for (int i = 1; i <= n - 1; i++) {
last = i - 1;
rightchild[i] = -1;
// Scan upward from the node's parent up to
// the root of the tree until a node is found
// whose value is smaller than the current one
// This is the same as Step 2 mentioned in the
// algorithm
while (arr[last] >= arr[i] && last != root)
last = parent[last];
// arr[i] is the smallest element yet; make it
// new root
if (arr[last] >= arr[i]) {
parent[root] = i;
leftchild[i] = root;
root = i;
}
else if (rightchild[last] == -1) {
rightchild[last] = i;
parent[i] = last;
leftchild[i] = -1;
}
else {
parent[rightchild[last]] = i;
leftchild[i] = rightchild[last];
rightchild[last] = i;
parent[i] = last;
}
}
// Since the root of the Cartesian Tree has no
// parent, so we assign it -1
parent[root] = -1;
return (buildCartesianTreeUtil(
root, arr, parent, leftchild, rightchild));
}
static void printSortedArr(int arr[], int n)
{
Node root = buildCartesianTree(arr, n);
System.out.println("The sorted array is-");
pQBasedTraversal(root);
}
public static void main(String[] args)
{
/* Given input array- {5,10,40,30,28},
it's corresponding unique Cartesian Tree
is-
5
\
10
\
28
/
30
/
40
*/
int[] arr = { 5, 10, 40, 30, 28 };
int n = arr.length;
printSortedArr(arr, n);
}
}
Python3
# A C++ program to implement Cartesian Tree sort
# Note that in this program we will build a min-heap
# Cartesian Tree and not max-heap.
import queue
''' A binary tree node has data, pointer to left child
and a pointer to right child '''
class Node:
def __init__(self, data):
self.data = data
self.left = None
self.right = None
# This function sorts by pushing and popping the
# Cartesian Tree nodes in a pre-order like fashion
def pQBasedTraversal(root):
# We will use a priority queue to sort the
# partially-sorted data efficiently.
# Unlike Heap, Cartesian tree makes use of
# the fact that the data is partially sorted
pQueue = queue.PriorityQueue()
pQueue.put((root.data, root))
# Resembles a pre-order traverse as first data
# is printed then the left and then right child.
while not pQueue.empty():
popped_pair = pQueue.get()
print(popped_pair[0], end=' ')
if popped_pair[1].left is not None:
pQueue.put((popped_pair[1].left.data, popped_pair[1].left))
if popped_pair[1].right is not None:
pQueue.put((popped_pair[1].right.data, popped_pair[1].right))
def buildCartesianTreeUtil(root, arr, parent, leftchild, rightchild):
if root == -1:
return None
temp = Node(arr[root])
temp.left = buildCartesianTreeUtil(leftchild[root], arr, parent, leftchild, rightchild)
temp.right = buildCartesianTreeUtil(rightchild[root], arr, parent, leftchild, rightchild)
return temp
# A function to create the Cartesian Tree in O(N) time
def buildCartesianTree(arr, n):
# Arrays to hold the index of parent, left-child,
# right-child of each number in the input array
# Initialize all array values as -1
parent = [-1] * n
leftchild = [-1] * n
rightchild = [-1] * n
''' 'root' and 'last' stores the index of the root and the
last processed of the Cartesian Tree.
Initially we take root of the Cartesian Tree as the
first element of the input array. This can change
according to the algorithm '''
root, last = 0, 0
# Starting from the second element of the input array
# to the last on scan across the elements, adding them
# one at a time.
for i in range(1, n):
last = i-1
rightchild[i] = -1
# Scan upward from the node's parent up to
# the root of the tree until a node is found
# whose value is smaller than the current one
# This is the same as Step 2 mentioned in the
# algorithm
while arr[last] >= arr[i] and last != root:
last = parent[last]
# arr[i] is the smallest element yet; make it
# new root
if arr[last] >= arr[i]:
parent[root] = i
leftchild[i] = root
root = i
# Just insert it
elif rightchild[last] == -1:
rightchild[last] = i
parent[i] = last
leftchild[i] = -1
# Reconfigure links
else:
parent[rightchild[last]] = i
leftchild[i] = rightchild[last]
rightchild[last] = i
parent[i] = last
# Since the root of the Cartesian Tree has no
# parent, so we assign it -1
parent[root] = -1
return buildCartesianTreeUtil(root, arr, parent, leftchild, rightchild)
# Sorts an input array
def printSortedArr(arr, n):
# Build a cartesian tree
root = buildCartesianTree(arr, n)
print("The sorted array is-")
# Do pr-order traversal and insert
# in priority queue
pQBasedTraversal(root)
# Driver code
''' Given input array- {5,10,40,30,28},
it's corresponding unique Cartesian Tree
is-
5
\
10
\
28
/
30
/
40
'''
arr = [5, 10, 40, 30, 28]
n = len(arr)
printSortedArr(arr, n)
# This code is contributed by Prince Kumar
C#
using System;
using System.Collections.Generic;
/* A binary tree node has data, pointer to left child
and a pointer to right child */
public class Node
{
public int data;
public Node left, right;
}
// Creating a shortcut for int, Node* pair type
public class iNPair : IComparable<iNPair>
{
public int first;
public Node second;
public iNPair(int f, Node s)
{
first = f;
second = s;
}
public int CompareTo(iNPair other)
{
return first.CompareTo(other.first);
}
}
class CartesianTreeSort
{
// This function sorts by pushing and popping the
// Cartesian Tree nodes in a pre-order like fashion
static void pQBasedTraversal(Node root)
{
// We will use a priority queue to sort the
// partially-sorted data efficiently.
// Unlike Heap, Cartesian tree makes use of
// the fact that the data is partially sorted
PriorityQueue<iNPair> pQueue = new PriorityQueue<iNPair>();
pQueue.Enqueue(new iNPair(root.data, root));
// Resembles a pre-order traverse as first data
// is printed then the left and then right child.
while (!pQueue.IsEmpty())
{
iNPair poppedPair = pQueue.Dequeue();
Console.Write(poppedPair.first + " ");
if (poppedPair.second.left != null)
pQueue.Enqueue(new iNPair(poppedPair.second.left.data, poppedPair.second.left));
if (poppedPair.second.right != null)
pQueue.Enqueue(new iNPair(poppedPair.second.right.data, poppedPair.second.right));
}
Console.WriteLine();
}
static Node buildCartesianTreeUtil(int root, int[] arr,
int[] parent, int[] leftChild, int[] rightChild)
{
if (root == -1)
return null;
Node temp = new Node();
temp.data = arr[root];
temp.left = buildCartesianTreeUtil(leftChild[root], arr, parent, leftChild, rightChild);
temp.right = buildCartesianTreeUtil(rightChild[root], arr, parent, leftChild, rightChild);
return temp;
}
// A function to create the Cartesian Tree in O(N) time
static Node buildCartesianTree(int[] arr, int n)
{
// Arrays to hold the index of parent, left-child,
// right-child of each number in the input array
int[] parent = new int[n];
int[] leftChild = new int[n];
int[] rightChild = new int[n];
// Initialize all array values as -1
Array.Fill(parent, -1);
Array.Fill(leftChild, -1);
Array.Fill(rightChild, -1);
// 'root' and 'last' stores the index of the root and the
// last processed of the Cartesian Tree.
// Initially, we take the root of the Cartesian Tree as the
// first element of the input array. This can change
// according to the algorithm
int root = 0, last;
// Starting from the second element of the input array
// to the last on scan across the elements, adding them
// one at a time.
for (int i = 1; i <= n - 1; i++)
{
last = i - 1;
rightChild[i] = -1;
// Scan upward from the node's parent up to
// the root of the tree until a node is found
// whose value is smaller than the current one
// This is the same as Step 2 mentioned in the
// algorithm
while (arr[last] >= arr[i] && last != root)
last = parent[last];
// arr[i] is the smallest element yet; make it
// the new root
if (arr[last] >= arr[i])
{
parent[root] = i;
leftChild[i] = root;
root = i;
}
else if (rightChild[last] == -1)
{
rightChild[last] = i;
parent[i] = last;
leftChild[i] = -1;
}
else
{
parent[rightChild[last]] = i;
leftChild[i] = rightChild[last];
rightChild[last] = i;
parent[i] = last;
}
}
// Since the root of the Cartesian Tree has no
// parent, so we assign it -1
parent[root] = -1;
return buildCartesianTreeUtil(root, arr, parent, leftChild, rightChild);
}
// Sorts an input array
static void printSortedArr(int[] arr, int n)
{
// Build a Cartesian tree
Node root = buildCartesianTree(arr, n);
Console.WriteLine("The sorted array is-");
// Do pre-order traversal and insert
// in priority queue
pQBasedTraversal(root);
}
/* Driver program to test above functions */
static void Main()
{
/* Given input array- {5,10,40,30,28},
its corresponding unique Cartesian Tree
is-
5
\
10
\
28
/
30
/
40
*/
int[] arr = { 5, 10, 40, 30, 28 };
int n = arr.Length;
printSortedArr(arr, n);
}
}
// Priority Queue implementation for C#
public class PriorityQueue<T> where T : IComparable<T>
{
private List<T> data;
public PriorityQueue()
{
this.data = new List<T>();
}
public bool IsEmpty()
{
return this.data.Count == 0;
}
public void Enqueue(T item)
{
this.data.Add(item);
int ci = this.data.Count - 1; // child index; start at end
while (ci > 0)
{
int pi = (ci - 1) / 2; // parent index
if (this.data[ci].CompareTo(this.data[pi]) >= 0)
break; // child item is larger than (or equal) parent so we're done
T tmp = this.data[ci];
this.data[ci] = this.data[pi];
this.data[pi] = tmp;
ci = pi;
}
}
public T Dequeue()
{
// assumes pq is not empty; up to calling code
int li = this.data.Count - 1; // last index (before removal)
T frontItem = this.data[0]; // fetch the front
this.data[0] = this.data[li];
this.data.RemoveAt(li);
--li; // last index (after removal)
int pi = 0; // parent index. start at front of pq
while (true)
{
int ci = pi * 2 + 1; // left child index of parent
if (ci > li)
break; // no children so done
int rc = ci + 1; // right child
if (rc <= li && this.data[rc].CompareTo(this.data[ci]) < 0)
ci = rc; // if there is a rc (ci + 1), and it is smaller than left child,
// use the rc instead
if (this.data[pi].CompareTo(this.data[ci]) <= 0)
break; // parent is smaller than (or equal to) smallest child so done
T tmp = this.data[pi];
this.data[pi] = this.data[ci];
this.data[ci] = tmp; // swap parent and child
pi = ci;
}
return frontItem;
}
}
JavaScript
// A Javascript program to implement Cartesian Tree sort
// Note that in this program we will build a min-heap
// Cartesian Tree and not max-heap.
// Define the Node class
/* A binary tree node has data, pointer to left child
and a pointer to right child */
class Node {
constructor(d) {
this.data = d;
this.left = null;
this.right = null;
}
}
// Define the iNPair class
class iNPair {
constructor(f, s) {
this.first = f;
this.second = s;
}
// Implement the compareTo method to allow the iNPair objects to be sorted in a priority queue
compareTo(other) {
return this.first - other.first;
}
}
// Define the pQBasedTraversal function
// This function sorts by pushing and popping the
// Cartesian Tree nodes in a pre-order like fashion
function pQBasedTraversal(root) {
// We will use a priority queue to sort the
// partially-sorted data efficiently.
// Unlike Heap, Cartesian tree makes use of
// the fact that the data is partially sorted
let pQueue = [];
pQueue.push(new iNPair(root.data, root));
// Resembles a pre-order traverse as first data
// is printed then the left and then right child.
while (pQueue.length > 0) {
let poppedPair = pQueue.shift();
console.log(poppedPair.first + " ");
if (poppedPair.second.left !== null) {
pQueue.push(
new iNPair(poppedPair.second.left.data, poppedPair.second.left)
);
}
if (poppedPair.second.right !== null) {
pQueue.push(
new iNPair(poppedPair.second.right.data, poppedPair.second.right)
);
}
}
}
// Define the buildCartesianTreeUtil function
function buildCartesianTreeUtil(root, arr, parent, leftchild, rightchild) {
if (root == -1) {
return null;
}
let temp = new Node(arr[root]);
temp.left = buildCartesianTreeUtil(
leftchild[root],
arr,
parent,
leftchild,
rightchild
);
temp.right = buildCartesianTreeUtil(
rightchild[root],
arr,
parent,
leftchild,
rightchild
);
return temp;
}
// Define the buildCartesianTree function
// A function to create the Cartesian Tree in O(N) time
function buildCartesianTree(arr, n) {
// Arrays to hold the index of parent, left-child,
// right-child of each number in the input array
// Initialize all array values as -1
let parent = new Array(n).fill(-1);
let leftchild = new Array(n).fill(-1);
let rightchild = new Array(n).fill(-1);
// 'root' and 'last' stores the index of the root
// and the last processed of the Cartesian Tree.
// Initially we take root of the Cartesian Tree as
// the first element of the input array. This can
// change according to the algorithm
let root = 0,
last;
// Starting from the second element of the input
// array to the last on scan across the elements,
// adding them one at a time.
for (let i = 1; i <= n - 1; i++) {
last = i - 1;
rightchild[i] = -1;
// Scan upward from the node's parent up to
// the root of the tree until a node is found
// whose value is smaller than the current one
// This is the same as Step 2 mentioned in the
// algorithm
while (arr[last] >= arr[i] && last != root) last = parent[last];
// arr[i] is the smallest element yet; make it
// new root
if (arr[last] >= arr[i]) {
parent[root] = i;
leftchild[i] = root;
root = i;
} else if (rightchild[last] == -1) {
rightchild[last] = i;
parent[i] = last;
leftchild[i] = -1;
} else {
parent[rightchild[last]] = i;
leftchild[i] = rightchild[last];
rightchild[last] = i;
parent[i] = last;
}
}
// Since the root of the Cartesian Tree has no
// parent, so we assign it -1
parent[root] = -1;
return buildCartesianTreeUtil(root, arr, parent, leftchild, rightchild);
}
// Define the printSortedArr function
function printSortedArr(arr, n) {
let root = buildCartesianTree(arr, n);
console.log("The sorted array is-");
pQBasedTraversal(root);
}
// Main function
function main() {
/* Given input array- {5,10,40,30,28},
it's corresponding unique Cartesian Tree
is-
5
\
10
\
28
/
30
/
40
*/
let arr = [5, 10, 40, 30, 28];
let n = arr.length;
printSortedArr(arr, n);
}
// Call the main function
main();
//This code is contributed by shivhack999
OutputThe sorted array is-
5 10 28 30 40
Time Complexity:
- O(n) best-case behaviour (when the input data is partially sorted),
- O(n log n) worst-case behavior (when the input data is not partially sorted)
Auxiliary Space: We use a priority queue and a Cartesian tree data structure. Now, at any moment of time the size of the priority queue doesn’t exceeds the size of the input array, as we are constantly pushing and popping the nodes.
Hence we are using O(n) auxiliary space.
If you like GeeksforGeeks and would like to contribute, you can also write an article and mail your article to [email protected]. See your article appearing on the GeeksforGeeks main page and help other Geeks. Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above
Similar Reads
Basics & Prerequisites
Data Structures
Array Data StructureIn this article, we introduce array, implementation in different popular languages, its basic operations and commonly seen problems / interview questions. An array stores items (in case of C/C++ and Java Primitive Arrays) or their references (in case of Python, JS, Java Non-Primitive) at contiguous
3 min read
String in Data StructureA string is a sequence of characters. The following facts make string an interesting data structure.Small set of elements. Unlike normal array, strings typically have smaller set of items. For example, lowercase English alphabet has only 26 characters. ASCII has only 256 characters.Strings are immut
2 min read
Hashing in Data StructureHashing is a technique used in data structures that efficiently stores and retrieves data in a way that allows for quick access. Hashing involves mapping data to a specific index in a hash table (an array of items) using a hash function. It enables fast retrieval of information based on its key. The
2 min read
Linked List Data StructureA linked list is a fundamental data structure in computer science. It mainly allows efficient insertion and deletion operations compared to arrays. Like arrays, it is also used to implement other data structures like stack, queue and deque. Hereâs the comparison of Linked List vs Arrays Linked List:
2 min read
Stack Data StructureA Stack is a linear data structure that follows a particular order in which the operations are performed. The order may be LIFO(Last In First Out) or FILO(First In Last Out). LIFO implies that the element that is inserted last, comes out first and FILO implies that the element that is inserted first
2 min read
Queue Data StructureA Queue Data Structure is a fundamental concept in computer science used for storing and managing data in a specific order. It follows the principle of "First in, First out" (FIFO), where the first element added to the queue is the first one to be removed. It is used as a buffer in computer systems
2 min read
Tree Data StructureTree Data Structure is a non-linear data structure in which a collection of elements known as nodes are connected to each other via edges such that there exists exactly one path between any two nodes. Types of TreeBinary Tree : Every node has at most two childrenTernary Tree : Every node has at most
4 min read
Graph Data StructureGraph Data Structure is a collection of nodes connected by edges. It's used to represent relationships between different entities. If you are looking for topic-wise list of problems on different topics like DFS, BFS, Topological Sort, Shortest Path, etc., please refer to Graph Algorithms. Basics of
3 min read
Trie Data StructureThe Trie data structure is a tree-like structure used for storing a dynamic set of strings. It allows for efficient retrieval and storage of keys, making it highly effective in handling large datasets. Trie supports operations such as insertion, search, deletion of keys, and prefix searches. In this
15+ min read
Algorithms
Searching AlgorithmsSearching algorithms are essential tools in computer science used to locate specific items within a collection of data. In this tutorial, we are mainly going to focus upon searching in an array. When we search an item in an array, there are two most common algorithms used based on the type of input
2 min read
Sorting AlgorithmsA Sorting Algorithm is used to rearrange a given array or list of elements in an order. For example, a given array [10, 20, 5, 2] becomes [2, 5, 10, 20] after sorting in increasing order and becomes [20, 10, 5, 2] after sorting in decreasing order. There exist different sorting algorithms for differ
3 min read
Introduction to RecursionThe process in which a function calls itself directly or indirectly is called recursion and the corresponding function is called a recursive function. A recursive algorithm takes one step toward solution and then recursively call itself to further move. The algorithm stops once we reach the solution
14 min read
Greedy AlgorithmsGreedy algorithms are a class of algorithms that make locally optimal choices at each step with the hope of finding a global optimum solution. At every step of the algorithm, we make a choice that looks the best at the moment. To make the choice, we sometimes sort the array so that we can always get
3 min read
Graph AlgorithmsGraph is a non-linear data structure like tree data structure. The limitation of tree is, it can only represent hierarchical data. For situations where nodes or vertices are randomly connected with each other other, we use Graph. Example situations where we use graph data structure are, a social net
3 min read
Dynamic Programming or DPDynamic Programming is an algorithmic technique with the following properties.It is mainly an optimization over plain recursion. Wherever we see a recursive solution that has repeated calls for the same inputs, we can optimize it using Dynamic Programming. The idea is to simply store the results of
3 min read
Bitwise AlgorithmsBitwise algorithms in Data Structures and Algorithms (DSA) involve manipulating individual bits of binary representations of numbers to perform operations efficiently. These algorithms utilize bitwise operators like AND, OR, XOR, NOT, Left Shift, and Right Shift.BasicsIntroduction to Bitwise Algorit
4 min read
Advanced
Segment TreeSegment Tree is a data structure that allows efficient querying and updating of intervals or segments of an array. It is particularly useful for problems involving range queries, such as finding the sum, minimum, maximum, or any other operation over a specific range of elements in an array. The tree
3 min read
Pattern SearchingPattern searching algorithms are essential tools in computer science and data processing. These algorithms are designed to efficiently find a particular pattern within a larger set of data. Patten SearchingImportant Pattern Searching Algorithms:Naive String Matching : A Simple Algorithm that works i
2 min read
GeometryGeometry is a branch of mathematics that studies the properties, measurements, and relationships of points, lines, angles, surfaces, and solids. From basic lines and angles to complex structures, it helps us understand the world around us.Geometry for Students and BeginnersThis section covers key br
2 min read
Interview Preparation
Practice Problem