Sort elements by frequency using Binary Search Tree (original) (raw)

Last Updated : 23 Jul, 2025

Given an arrayof integers **arr[], sortthe array according to the **frequency of elements, i.e. elements that have higher frequency comes first. If the frequencies of two elements are the same, then the **smaller number comes first.

**Examples:

**Input: arr[] = [5, 5, 4, 6, 4]
**Output: [4, 4, 5, 5, 6]
**Explanation: The highest frequency here is 2. Both 5 and 4 have that frequency. Now since the frequencies are the same the smaller element comes first. So 4 comes first then comes 5. Finally comes 6. The output is **4 4 5 5 6.

**Input: arr[] = [9, 9, 9, 2, 5]
**Output: [9, 9, 9, 2, 5]
**Explanation: The highest frequency here is 3. Element 9 has the highest frequency So 9 comes first. Now both 2 and 5 have the same frequency. So we print smaller elements first. The output is **9 9 9 2 5.

**Note: We have discussed the multiple approaches to solve this problem in article Sort Elements by Frequency. In this article we've discussed an approach using binary search tree.

Using Binary Search Tree - O(n ^ 2) Time and O(n) Space

The idea is to use Binary Search Tree to efficiently store the elements and their frequency in the form of tree nodes. And thereafter store the value - frequency pair in a 2d array and sort it according to the frequency.

Follow the below given steps:

Below is given the **implementation:

C++ `

#include <bits/stdc++.h> using namespace std;

// BST Node Structure class Node { public:

int data;
int freq;
Node *left;
Node *right;

Node(int data) {
    this->data = data;
    this->freq = 1;
    this->left = nullptr;
    this->right = nullptr;
}

};

// to store the element in BST Node* insert(Node* root, int data) {

// base case: if the data
// is not present in the BST
if (root == nullptr)
    return new Node(data);

// if the data is already present
// in the BST, increment the frequency
if (data == root->data)
    root->freq += 1;

// if the data is less than the root
// data, recur for the left subtree
else if (data < root->data)
    root->left = insert(root->left, data);

// if the data is more than the root
// data, recur for the right subtree
else
    root->right = insert(root->right, data);

return root;

}

// Function to store the frequency of each element void store(Node *root, vector<vector> &freq) {

// Base Case
if (root == nullptr) return;

// Recur for left subtree
store(root->left, freq);

// Store item from root in freq
freq.push_back({root->freq, root->data});

// Recur for right subtree
store(root->right, freq);

}

// Function to sort the array // according to frequency of elements vector sortByFreq(vector &arr) { int n = arr.size();

// create bst and insert all elements
Node *root = nullptr;
for(int i = 0; i < n; i++) {
    root = insert(root, arr[i]);
}

// create a 2d vector to store 
// the frequency of each element
vector<vector<int>> freq;

// to sort the frequency in descending order
auto comp = [&](vector<int> &a, vector<int> &b)
{
    if (a[0] == b[0])
        return a[1] < b[1];
    return a[0] > b[0];
};

// store the frequency and the element
store(root, freq);

// sort the frequency array
sort(freq.begin(), freq.end(), comp);

// to store the answer
vector<int> ans;

// push the elements in the answer array
for(int i = 0; i < freq.size(); i++) {
    for(int j = 0; j < freq[i][0]; j++) {
        ans.push_back(freq[i][1]);
    }
}

return ans;

}

int main() { vector arr = {5, 5, 4, 6, 4}; vector ans = sortByFreq(arr); for(int i = 0; i < ans.size(); i++) { cout << ans[i] << " "; } return 0; }

Java

import java.util.*;

// Node structure class Node { int data; int freq; Node left; Node right;

Node(int data) {
    this.data = data;
    this.freq = 1;
    this.left = null;
    this.right = null;
}

}

// Function to store the element in BST class GfG {

static Node insert(Node root, int data) {
    // base case: if the data
    // is not present in the BST
    if (root == null)
        return new Node(data);
    
    // if the data is already present
    // in the BST, increment the frequency
    if (data == root.data)
        root.freq += 1;
    
    // if the data is less than the root
    // data, recur for the left subtree
    else if (data < root.data)
        root.left = insert(root.left, data);
    
    // if the data is more than the root
    // data, recur for the right subtree
    else
        root.right = insert(root.right, data);
    return root;
}

// Function to store the frequency of each element
static void store(Node root, ArrayList<ArrayList<Integer>> freq) {
    // Base Case
    if (root == null)
        return;
    
    // Recur for left subtree
    store(root.left, freq);
    
    // Store item from root in freq
    ArrayList<Integer> temp = new ArrayList<>();
    temp.add(root.freq);
    temp.add(root.data);
    freq.add(temp);
    
    // Recur for right subtree
    store(root.right, freq);
}

// Function to sort the array 
// according to frequency of elements
static ArrayList<Integer> sortByFreq(int[] arr) {
    int n = arr.length;
    
    // create bst and insert all elements
    Node root = null;
    for (int i = 0; i < n; i++) {
        root = insert(root, arr[i]);
    }
    
    // create a 2d vector to store 
    // the frequency of each element
    ArrayList<ArrayList<Integer>> freq = new ArrayList<>();
    
    // store the frequency and the element
    store(root, freq);
    
    // to sort the frequency in descending order
    Comparator<ArrayList<Integer>> comp = 
            new Comparator<ArrayList<Integer>>() {
        public int compare(ArrayList<Integer> a, ArrayList<Integer> b) {
            if (a.get(0).equals(b.get(0)))
                return a.get(1) - b.get(1);
            return b.get(0) - a.get(0);
        }
    };
    Collections.sort(freq, comp);
    
    // to store the answer
    ArrayList<Integer> ans = new ArrayList<>();
    
    // push the elements in the answer array
    for (int i = 0; i < freq.size(); i++) {
        for (int j = 0; j < freq.get(i).get(0); j++) {
            ans.add(freq.get(i).get(1));
        }
    }
    return ans;
}

public static void main(String[] args) {
    int[] arr = {5, 5, 4, 6, 4};
    ArrayList<Integer> ans = sortByFreq(arr);
    for (int i = 0; i < ans.size(); i++) {
        System.out.print(ans.get(i) + " ");
    }
}

}

Python

Node structure

class Node: def init(self, data): self.data = data self.freq = 1 self.left = None self.right = None

to store the element in BST

def insert(root, data): # base case: if the data # is not present in the BST if root is None: return Node(data)

# if the data is already present
# in the BST, increment the frequency
if data == root.data:
    root.freq += 1
# if the data is less than the root
# data, recur for the left subtree
elif data < root.data:
    root.left = insert(root.left, data)
# if the data is more than the root
# data, recur for the right subtree
else:
    root.right = insert(root.right, data)
return root

Function to store the frequency of each element

def store(root, freq): # Base Case if root is None: return # Recur for left subtree store(root.left, freq) # Store item from root in freq freq.append([root.freq, root.data]) # Recur for right subtree store(root.right, freq)

Function to sort the array

according to frequency of elements

def sortByFreq(arr): n = len(arr)

# create bst and insert all elements
root = None
for i in range(n):
    root = insert(root, arr[i])

# create a 2d vector to store 
# the frequency of each element
freq = []

# store the frequency and the element
store(root, freq)

# to sort the frequency in descending order
freq.sort(key=lambda a: (-a[0], a[1]))

# to store the answer
ans = []

# push the elements in the answer array
for i in range(len(freq)):
    for j in range(freq[i][0]):
        ans.append(freq[i][1])
return ans

if name == "main": arr = [5, 5, 4, 6, 4] ans = sortByFreq(arr) for i in range(len(ans)): print(ans[i], end=" ")

C#

// Node structure using System; using System.Collections.Generic;

class Node { public int data; public int freq; public Node left; public Node right;

public Node(int data) {
    this.data = data;
    this.freq = 1;
    this.left = null;
    this.right = null;
}

}

class GfG {

// to store the element in BST
static Node insert(Node root, int data) {
    // base case: if the data
    // is not present in the BST
    if (root == null)
        return new Node(data);
    
    // if the data is already present
    // in the BST, increment the frequency
    if (data == root.data)
        root.freq += 1;
    // if the data is less than the root
    // data, recur for the left subtree
    else if (data < root.data)
        root.left = insert(root.left, data);
    // if the data is more than the root
    // data, recur for the right subtree
    else
        root.right = insert(root.right, data);
    return root;
}

// Function to store the frequency of each element
static void store(Node root, List<List<int>> freq) {
    // Base Case
    if (root == null)
        return;
    
    // Recur for left subtree
    store(root.left, freq);
    
    // Store item from root in freq
    List<int> temp = new List<int>();
    temp.Add(root.freq);
    temp.Add(root.data);
    freq.Add(temp);
    
    // Recur for right subtree
    store(root.right, freq);
}

// Function to sort the array 
// according to frequency of elements
static List<int> sortByFreq(int[] arr) {
    int n = arr.Length;
    
    // create bst and insert all elements
    Node root = null;
    for (int i = 0; i < n; i++) {
        root = insert(root, arr[i]);
    }
    
    // create a 2d vector to store 
    // the frequency of each element
    List<List<int>> freq = new List<List<int>>();
    
    // store the frequency and the element
    store(root, freq);
    
    // to sort the frequency in descending order
    freq.Sort((a, b) => {
        if (a[0] == b[0])
            return a[1].CompareTo(b[1]);
        return b[0].CompareTo(a[0]);
    });
    
    // to store the answer
    List<int> ans = new List<int>();
    
    // push the elements in the answer array
    for (int i = 0; i < freq.Count; i++) {
        for (int j = 0; j < freq[i][0]; j++) {
            ans.Add(freq[i][1]);
        }
    }
    return ans;
}

static void Main() {
    int[] arr = {5, 5, 4, 6, 4};
    List<int> ans = sortByFreq(arr);
    foreach (int i in ans) {
        Console.Write(i + " ");
    }
}

}

JavaScript

// Node structure class Node { constructor(data) { this.data = data; this.freq = 1; this.left = null; this.right = null; } }

// to store the element in BST function insert(root, data) { // base case: if the data // is not present in the BST if (root === null) return new Node(data);

// if the data is already present
// in the BST, increment the frequency
if (data === root.data)
    root.freq += 1;
// if the data is less than the root
// data, recur for the left subtree
else if (data < root.data)
    root.left = insert(root.left, data);
// if the data is more than the root
// data, recur for the right subtree
else
    root.right = insert(root.right, data);
return root;

}

// Function to store the frequency of each element function store(root, freq) { // Base Case if (root === null) return;

// Recur for left subtree
store(root.left, freq);

// Store item from root in freq
freq.push([root.freq, root.data]);

// Recur for right subtree
store(root.right, freq);

}

// Function to sort the array // according to frequency of elements function sortByFreq(arr) { let n = arr.length;

// create bst and insert all elements
let root = null;
for (let i = 0; i < n; i++) {
    root = insert(root, arr[i]);
}

// create a 2d vector to store 
// the frequency of each element
let freq = [];

// store the frequency and the element
store(root, freq);

// to sort the frequency in descending order
freq.sort((a, b) => {
    if (a[0] === b[0])
        return a[1] - b[1];
    return b[0] - a[0];
});

// to store the answer
let ans = [];

// push the elements in the answer array
for (let i = 0; i < freq.length; i++) {
    for (let j = 0; j < freq[i][0]; j++) {
        ans.push(freq[i][1]);
    }
}
return ans;

}

let arr = [5, 5, 4, 6, 4]; let ans = sortByFreq(arr); console.log(ans.join(" "));

`

**Time Complexity: O(n ^ 2), in the worst case when given array is sorted, the skewed tree will be formed that takes O(n) time to store the elements, and we are storing n elements, thus the overall time complexity will be O(n ^ 2).
**Auxiliary Space: O(n), to store the elements in BST and freq[] array.

Using Self Balancing Binary Search Tree - O(n * log n) Time and O(n) Space

The idea is to use self balancing binary search tree (AVL Tree or Red Black Tree), that offers O(log n) insertion time complexity even in the worst case.

C++, Java and C# seem to have built-in implementations of a self balancing in BST. We have implemented our own AVL tree in Python and JavaScript.

C++ `

#include <bits/stdc++.h> using namespace std;

// Function to sort the array // according to frequency of elements vector sortByFreq(vector &arr) { int n = arr.size();

// hash map to store the 
// frequency of each element
map<int, int> mp;

// store the frequency of each element
for(int i = 0; i < n; i++) {
    mp[arr[i]]++;
}

// create a 2d vector to store 
// the frequency of each element
vector<vector<int>> freq;

// to sort the frequency in descending order
auto comp = [&](vector<int> &a, vector<int> &b)
{
    if (a[0] == b[0])
        return a[1] < b[1];
    return a[0] > b[0];
};

// store the frequency and the element
for(auto i : mp) {
    freq.push_back({i.second, i.first});
}

// sort the frequency array
sort(freq.begin(), freq.end(), comp);

// to store the answer
vector<int> ans;

// push the elements in the answer array
for(int i = 0; i < freq.size(); i++) {
    for(int j = 0; j < freq[i][0]; j++) {
        ans.push_back(freq[i][1]);
    }
}
return ans;

}

int main() { vector arr = {5, 5, 4, 6, 4}; vector ans = sortByFreq(arr); for(int i = 0; i < ans.size(); i++) { cout << ans[i] << " "; } return 0; }

Java

// Function to sort the array // according to frequency of elements import java.util.*;

class GfG {

// Function to sort the array 
// according to frequency of elements
static ArrayList<Integer> sortByFreq(int[] arr) {
    int n = arr.length;
    
    // hash map to store the 
    // frequency of each element
    TreeMap<Integer, Integer> mp = new TreeMap<>();
    for (int i = 0; i < n; i++) {
        mp.put(arr[i], mp.getOrDefault(arr[i], 0) + 1);
    }
    
    // create a 2d vector to store 
    // the frequency of each element
    ArrayList<ArrayList<Integer>> freq = new ArrayList<>();
    for (Map.Entry<Integer, Integer> entry : mp.entrySet()) {
        ArrayList<Integer> pair = new ArrayList<>();
        pair.add(entry.getValue());
        pair.add(entry.getKey());
        freq.add(pair);
    }
    
    // to sort the frequency in descending order
    Collections.sort(freq, new Comparator<ArrayList<Integer>>() {
        public int compare(ArrayList<Integer> a, ArrayList<Integer> b) {
            if(a.get(0).equals(b.get(0)))
                return a.get(1) - b.get(1);
            return b.get(0) - a.get(0);
        }
    });
    
    // to store the answer
    ArrayList<Integer> ans = new ArrayList<>();
    
    // push the elements in the answer array
    for (int i = 0; i < freq.size(); i++) {
        for (int j = 0; j < freq.get(i).get(0); j++) {
            ans.add(freq.get(i).get(1));
        }
    }
    return ans;
}

public static void main(String[] args) {
    int[] arr = {5, 5, 4, 6, 4};
    ArrayList<Integer> ans = sortByFreq(arr);
    for (int i = 0; i < ans.size(); i++) {
        System.out.print(ans.get(i) + " ");
    }
}

}

Python

class Node: def init(self, key): self.key = key self.freq = 1 self.left = None self.right = None self.height = 1

A utility function to get the

height of the tree

def height(node): if not node: return 0 return node.height

A utility function to right rotate

subtree rooted with y

def right_rotate(y): x = y.left T2 = x.right

# Perform rotation
x.right = y
y.left = T2

# Update heights
y.height = 1 + max(height(y.left), height(y.right))
x.height = 1 + max(height(x.left), height(x.right))

# Return new root
return x

A utility function to left rotate

subtree rooted with x

def left_rotate(x): y = x.right T2 = y.left

# Perform rotation
y.left = x
x.right = T2

# Update heights
x.height = 1 + max(height(x.left), height(x.right))
y.height = 1 + max(height(y.left), height(y.right))

# Return new root
return y

Get balance factor of node N

def get_balance(node): if not node: return 0 return height(node.left) - height(node.right)

Recursive function to insert a key in

the subtree rooted with node

def insert(node, key):

# Perform the normal BST insertion
if not node:
    return Node(key)

if key < node.key:
    node.left = insert(node.left, key)
elif key > node.key:
    node.right = insert(node.right, key)
else:
    node.freq += 1
    return node

# Update height of this ancestor node
node.height = 1 + max(height(node.left), height(node.right))

# Get the balance factor of this ancestor node
balance = get_balance(node)

# If this node becomes unbalanced, 
# then there are 4 cases

# Left Left Case
if balance > 1 and key < node.left.key:
    return right_rotate(node)

# Right Right Case
if balance < -1 and key > node.right.key:
    return left_rotate(node)

# Left Right Case
if balance > 1 and key > node.left.key:
    node.left = left_rotate(node.left)
    return right_rotate(node)

# Right Left Case
if balance < -1 and key < node.right.key:
    node.right = right_rotate(node.right)
    return left_rotate(node)

# Return the (unchanged) node pointer
return node

Function to store the frequency of each element

def store(root, freq):

# Base Case
if root is None:
    return

# Recur for left subtree
store(root.left, freq)

# Store item from root in freq
freq.append([root.freq, root.key])

# Recur for right subtree
store(root.right, freq)

Function to sort the array

according to frequency of elements

def sortByFreq(arr): n = len(arr)

# create bst and insert all elements
root = None
for i in range(n):
    root = insert(root, arr[i])

# create a 2d vector to store 
# the frequency of each element
freq = []

# store the frequency and the element
store(root, freq)

# to sort the frequency in descending order
freq.sort(key=lambda a: (-a[0], a[1]))

# to store the answer
ans = []

# push the elements in the answer array
for i in range(len(freq)):
    for j in range(freq[i][0]):
        ans.append(freq[i][1])
return ans

if name == "main": arr = [5, 5, 4, 6, 4] ans = sortByFreq(arr) for i in range(len(ans)): print(ans[i], end=" ")

C#

// Function to sort the array // according to frequency of elements using System; using System.Collections.Generic;

class GfG {

// Function to sort the array 
// according to frequency of elements
static List<int> sortByFreq(int[] arr) {
    int n = arr.Length;
    
    // hash map to store the 
    // frequency of each element
    SortedDictionary<int, int> mp = 
        new SortedDictionary<int, int>();
    for (int i = 0; i < n; i++) {
        if (mp.ContainsKey(arr[i]))
            mp[arr[i]]++;
        else
            mp[arr[i]] = 1;
    }
    
    // create a 2d vector to store 
    // the frequency of each element
    List<List<int>> freq = new List<List<int>>();
    foreach (KeyValuePair<int, int> kvp in mp) {
        List<int> pair = new List<int>();
        pair.Add(kvp.Value);
        pair.Add(kvp.Key);
        freq.Add(pair);
    }
    
    // to sort the frequency in descending order
    freq.Sort((a, b) => {
        if(a[0] == b[0])
            return a[1].CompareTo(b[1]);
        return b[0].CompareTo(a[0]);
    });
    
    // to store the answer
    List<int> ans = new List<int>();
    
    // push the elements in the answer array
    for (int i = 0; i < freq.Count; i++) {
        for (int j = 0; j < freq[i][0]; j++) {
            ans.Add(freq[i][1]);
        }
    }
    return ans;
}

static void Main() {
    int[] arr = {5, 5, 4, 6, 4};
    List<int> ans = sortByFreq(arr);
    foreach (int i in ans) {
        Console.Write(i + " ");
    }
}

}

JavaScript

// Node Structure class Node { constructor(key) { this.key = key; this.freq = 1; this.left = null; this.right = null; this.height = 1; } }

// A utility function to get // the height of the tree function height(node) { if (node === null) { return 0; } return node.height; }

// A utility function to right rotate // subtree rooted with y function rightRotate(y) { const x = y.left; const T2 = x.right;

// Perform rotation
x.right = y;
y.left = T2;

// Update heights
y.height = 1 + Math.max(height(y.left), height(y.right));
x.height = 1 + Math.max(height(x.left), height(x.right));

// Return new root
return x;

}

// A utility function to left rotate subtree rooted with x function leftRotate(x) { const y = x.right; const T2 = y.left;

// Perform rotation
y.left = x;
x.right = T2;

// Update heights
x.height = 1 + Math.max(height(x.left), height(x.right));
y.height = 1 + Math.max(height(y.left), height(y.right));

// Return new root
return y;

}

// Get balance factor of node function getBalance(node) { if (node === null) { return 0; } return height(node.left) - height(node.right); }

// Recursive function to insert a key in // the subtree rooted with node function insert(node, key) {

// Perform the normal BST insertion
if (node === null) {
    return new Node(key);
}

if (key < node.key) {
    node.left = insert(node.left, key);
} else if (key > node.key) {
    node.right = insert(node.right, key);
} else {
    node.freq++;
    return node;
}

// Update height of this ancestor node
node.height = 1 + Math.max(height(node.left), height(node.right));

// Get the balance factor of this ancestor node
const balance = getBalance(node);

// If this node becomes unbalanced, then there are 4 cases

// Left Left Case
if (balance > 1 && key < node.left.key) {
    return rightRotate(node);
}

// Right Right Case
if (balance < -1 && key > node.right.key) {
    return leftRotate(node);
}

// Left Right Case
if (balance > 1 && key > node.left.key) {
    node.left = leftRotate(node.left);
    return rightRotate(node);
}

// Right Left Case
if (balance < -1 && key < node.right.key) {
    node.right = rightRotate(node.right);
    return leftRotate(node);
}

// Return the (unchanged) node pointer
return node;

}

// Function to store the frequency of each element function store(root, freq) {

// Base Case
if (root === null)
    return;

// Recur for left subtree
store(root.left, freq);

// Store item from root in freq
freq.push([root.freq, root.key]);

// Recur for right subtree
store(root.right, freq);

}

// Function to sort the array // according to frequency of elements function sortByFreq(arr) { let n = arr.length;

// create bst and insert all elements
let root = null;
for (let i = 0; i < n; i++) {
    root = insert(root, arr[i]);
}

// create a 2d vector to store 
// the frequency of each element
let freq = [];

// store the frequency and the element
store(root, freq);

// to sort the frequency in descending order
freq.sort((a, b) => {
    if (a[0] === b[0])
        return a[1] - b[1];
    return b[0] - a[0];
});

// to store the answer
let ans = [];

// push the elements in the answer array
for (let i = 0; i < freq.length; i++) {
    for (let j = 0; j < freq[i][0]; j++) {
        ans.push(freq[i][1]);
    }
}
return ans;

}

let arr = [5, 5, 4, 6, 4]; let ans = sortByFreq(arr); console.log(ans.join(" "));

`

**Time Complexity: O(n * log n), storing an element in self balancing BST takes O(log n) Time and we are storing n elements, thus the total time required will be O(n * log n). Also, we are sorting the array freq[], which also takes O(n * log n). Thus the overall time complexity will be O(n * log n).
**Auxiliary Space: O(n), to store the elements in BST and freq[] array.