Tree Sort is a unique and interesting sorting algorithm that uses a Binary Search Tree (BST) to sort data. Instead of repeatedly comparing numbers like in Bubble Sort or Insertion Sort, Tree Sort inserts elements into a BST, which automatically arranges them in order. Then, by performing an in-order traversal of the tree, you can retrieve the sorted array. This approach combines data structures and algorithms, making it a great exercise for beginners who want to learn both at the same time.
with hands-on learning.
get the skills and confidence to land your next move.
Tree Sort is important because it demonstrates the practical use of binary trees in sorting and searching. It can handle dynamic datasets efficiently, and it is especially useful when the data is being updated frequently because you can insert new elements into the tree without needing to re-sort the entire array. In TypeScript, implementing Tree Sort gives beginners an opportunity to work with classes, recursion, and traversal methods while understanding how structure can simplify sorting.
Program 1: Basic Tree Sort Using a Binary Search Tree
This program demonstrates the classic implementation of Tree Sort using a BST. It inserts elements into the tree and retrieves them in sorted order using in-order traversal.
class TreeNode {
value: number;
left: TreeNode | null = null;
right: TreeNode | null = null;
constructor(value: number) {
this.value = value;
}
}
function insert(root: TreeNode | null, value: number): TreeNode {
if (!root) return new TreeNode(value);
if (value < root.value) {
root.left = insert(root.left, value);
} else {
root.right = insert(root.right, value);
}
return root;
}
function inOrderTraversal(root: TreeNode | null, result: number[] = []): number[] {
if (root) {
inOrderTraversal(root.left, result);
result.push(root.value);
inOrderTraversal(root.right, result);
}
return result;
}
function treeSort(arr: number[]): number[] {
let root: TreeNode | null = null;
arr.forEach(num => {
root = insert(root, num);
});
return inOrderTraversal(root);
}
let data: number[] = [5, 2, 8, 1, 3, 7];
console.log("Sorted array:", treeSort(data));In this program, each element is inserted into the BST according to its value. The in-order traversal then visits the nodes in ascending order. Beginners can understand this as building a “sorting tree” that naturally organizes data for retrieval.
Program 2: Tree Sort Using Recursion for Insertion
This version highlights recursion for inserting elements, emphasizing the power of recursive thinking in algorithms.
class TreeNode {
value: number;
left: TreeNode | null = null;
right: TreeNode | null = null;
constructor(value: number) {
this.value = value;
}
}
function inOrderTraversal(root: TreeNode | null, result: number[] = []): number[] {
if (root) {
inOrderTraversal(root.left, result);
result.push(root.value);
inOrderTraversal(root.right, result);
}
return result;
}
function insertRecursive(root: TreeNode | null, value: number): TreeNode {
if (!root) return new TreeNode(value);
if (value < root.value) {
root.left = insertRecursive(root.left, value);
} else {
root.right = insertRecursive(root.right, value);
}
return root;
}
function treeSortRecursive(arr: number[]): number[] {
let root: TreeNode | null = null;
arr.forEach(num => root = insertRecursive(root, num));
return inOrderTraversal(root);
}
let values: number[] = [9, 4, 6, 2, 8, 1];
console.log("Sorted array:", treeSortRecursive(values));This program shows that recursive insertion is concise and readable. Beginners can see that recursion can replace loops for inserting elements while keeping the logic simple.
Program 3: Tree Sort with Duplicate Values
This example demonstrates that Tree Sort naturally handles duplicate values by placing them in the right subtree.
class TreeNode {
value: number;
left: TreeNode | null = null;
right: TreeNode | null = null;
constructor(value: number) {
this.value = value;
}
}
function insert(root: TreeNode | null, value: number): TreeNode {
if (!root) return new TreeNode(value);
if (value < root.value) {
root.left = insert(root.left, value);
} else {
root.right = insert(root.right, value);
}
return root;
}
function inOrderTraversal(root: TreeNode | null, result: number[] = []): number[] {
if (root) {
inOrderTraversal(root.left, result);
result.push(root.value);
inOrderTraversal(root.right, result);
}
return result;
}
function treeSort(arr: number[]): number[] {
let root: TreeNode | null = null;
arr.forEach(num => {
root = insert(root, num);
});
return inOrderTraversal(root);
}
let duplicates: number[] = [5, 2, 3, 5, 2, 7, 3];
console.log("Sorted array:", treeSort(duplicates));Handling duplicates is automatic in Tree Sort. Beginners learn that the structure of a BST can manage repeated elements without extra logic, which is a useful property in many applications.
Program 4: Tree Sort for Already Sorted Data
Tree Sort performs efficiently even on arrays that are already sorted, though the tree may become unbalanced.
class TreeNode {
value: number;
left: TreeNode | null = null;
right: TreeNode | null = null;
constructor(value: number) {
this.value = value;
}
}
function insert(root: TreeNode | null, value: number): TreeNode {
if (!root) return new TreeNode(value);
if (value < root.value) {
root.left = insert(root.left, value);
} else {
root.right = insert(root.right, value);
}
return root;
}
function inOrderTraversal(root: TreeNode | null, result: number[] = []): number[] {
if (root) {
inOrderTraversal(root.left, result);
result.push(root.value);
inOrderTraversal(root.right, result);
}
return result;
}
function treeSort(arr: number[]): number[] {
let root: TreeNode | null = null;
arr.forEach(num => {
root = insert(root, num);
});
return inOrderTraversal(root);
}
let sortedData: number[] = [1, 2, 3, 4, 5, 6];
console.log("Sorted array:", treeSort(sortedData));This example reassures beginners that Tree Sort produces correct results regardless of input order. However, it also introduces the idea that BST balance affects efficiency.
Program 5: Tree Sort Using Iterative In-Order Traversal
Instead of recursion, we can retrieve the sorted array using an iterative in-order traversal with a stack.
class TreeNode {
value: number;
left: TreeNode | null = null;
right: TreeNode | null = null;
constructor(value: number) {
this.value = value;
}
}
function insert(root: TreeNode | null, value: number): TreeNode {
if (!root) return new TreeNode(value);
if (value < root.value) {
root.left = insert(root.left, value);
} else {
root.right = insert(root.right, value);
}
return root;
}
function inOrderIterative(root: TreeNode | null): number[] {
let stack: TreeNode[] = [];
let result: number[] = [];
let current = root;
while (current || stack.length > 0) {
while (current) {
stack.push(current);
current = current.left;
}
current = stack.pop()!;
result.push(current.value);
current = current.right;
}
return result;
}
function treeSortIterative(arr: number[]): number[] {
let root: TreeNode | null = null;
arr.forEach(num => root = insert(root, num));
return inOrderIterative(root);
}
let numbers: number[] = [7, 3, 9, 1, 5];
console.log("Sorted array:", treeSortIterative(numbers));This version shows beginners that recursion is not the only way to traverse a tree. Iterative traversal using a stack is efficient and avoids potential stack overflow for large datasets.
Program 6: Tree Sort with Negative Numbers
Tree Sort works naturally with negative numbers, as they can be inserted into the BST like any other number.
class TreeNode {
value: number;
left: TreeNode | null = null;
right: TreeNode | null = null;
constructor(value: number) {
this.value = value;
}
}
function insert(root: TreeNode | null, value: number): TreeNode {
if (!root) return new TreeNode(value);
if (value < root.value) {
root.left = insert(root.left, value);
} else {
root.right = insert(root.right, value);
}
return root;
}
function inOrderTraversal(root: TreeNode | null, result: number[] = []): number[] {
if (root) {
inOrderTraversal(root.left, result);
result.push(root.value);
inOrderTraversal(root.right, result);
}
return result;
}
function treeSort(arr: number[]): number[] {
let root: TreeNode | null = null;
arr.forEach(num => {
root = insert(root, num);
});
return inOrderTraversal(root);
}
let mixedNumbers: number[] = [-5, 3, -2, 7, 0, -1];
console.log("Sorted array:", treeSort(mixedNumbers));Beginners can see that no special adjustments are needed for negative values. The tree structure handles them just like positive integers.
Program 7: Tree Sort with Floating Point Numbers
Tree Sort can also handle decimal numbers without modification.
class TreeNode {
value: number;
left: TreeNode | null = null;
right: TreeNode | null = null;
constructor(value: number) {
this.value = value;
}
}
function insert(root: TreeNode | null, value: number): TreeNode {
if (!root) return new TreeNode(value);
if (value < root.value) {
root.left = insert(root.left, value);
} else {
root.right = insert(root.right, value);
}
return root;
}
function inOrderTraversal(root: TreeNode | null, result: number[] = []): number[] {
if (root) {
inOrderTraversal(root.left, result);
result.push(root.value);
inOrderTraversal(root.right, result);
}
return result;
}
function treeSort(arr: number[]): number[] {
let root: TreeNode | null = null;
arr.forEach(num => {
root = insert(root, num);
});
return inOrderTraversal(root);
}
let decimals: number[] = [3.5, 1.2, 4.8, 0.9, 2.3];
console.log("Sorted array:", treeSort(decimals));This example highlights that the comparison-based nature of BSTs makes Tree Sort versatile for integers, decimals, and negatives.
Program 8: Tree Sort with Random Data
Tree Sort can efficiently organize random datasets of any size.
class TreeNode {
value: number;
left: TreeNode | null = null;
right: TreeNode | null = null;
constructor(value: number) {
this.value = value;
}
}
function insert(root: TreeNode | null, value: number): TreeNode {
if (!root) return new TreeNode(value);
if (value < root.value) {
root.left = insert(root.left, value);
} else {
root.right = insert(root.right, value);
}
return root;
}
function inOrderTraversal(root: TreeNode | null, result: number[] = []): number[] {
if (root) {
inOrderTraversal(root.left, result);
result.push(root.value);
inOrderTraversal(root.right, result);
}
return result;
}
function treeSort(arr: number[]): number[] {
let root: TreeNode | null = null;
arr.forEach(num => {
root = insert(root, num);
});
return inOrderTraversal(root);
}
let randomData: number[] = [12, 5, 18, 7, 2, 15, 10];
console.log("Sorted array:", treeSort(randomData));This program demonstrates that Tree Sort works reliably for different datasets. Beginners can use it to practice building trees from scratch and retrieving sorted data.
Frequently Asked Questions (FAQ)
This section answers common beginner questions about Tree Sort in TypeScript.
Q1. Is Tree Sort faster than Quick Sort?
It depends on the tree balance. A balanced BST makes it efficient, but an unbalanced tree can slow it down.
Q2. Can Tree Sort handle negative numbers?
Yes, negative numbers can be inserted into the BST like any other number.
Q3. Is Tree Sort stable?
Tree Sort is generally not stable because duplicate elements may not maintain their original order.
Q4. Does Tree Sort work with decimals?
Yes, any number that can be compared can be sorted using Tree Sort.
Q5. Why is Tree Sort useful for beginners?
It combines data structures and algorithms, helping beginners understand recursion, traversal, and sorting in one exercise.
Conclusion
Tree Sort is an elegant algorithm that uses the structure of a Binary Search Tree to sort data efficiently. In this article, we explored several TypeScript programs implementing Tree Sort in different ways, including recursive and iterative traversal, handling duplicates, negatives, and decimals.
By practicing these examples, beginners can improve their understanding of BSTs, recursion, and sorting logic. Experimenting with different datasets and traversal methods will help solidify your understanding of how Tree Sort works and prepare you to tackle more advanced algorithms confidently.




