0
0
DSA Javascriptprogramming

Sorting Stability and When to Use Which Sort in DSA Javascript

Choose your learning style9 modes available
Mental Model
Stable sorting keeps equal items in the same order they started. Different sorts work best for different situations.
Analogy: Imagine sorting playing cards by number but keeping the order of cards with the same number as they were originally placed in your hand.
Unsorted list:
5a -> 3 -> 5b -> 2 -> 3 -> null

'a' and 'b' show two different 5s to track order.
Dry Run Walkthrough
Input: list: 5a -> 3 -> 5b -> 2 -> 3, sort ascending stable
Goal: Sort the list so numbers are in order, but keep 5a before 5b and first 3 before second 3
Step 1: Compare 5a and 3, swap because 3 < 5a
3 -> 5a -> 5b -> 2 -> 3 -> null
Why: We want smaller numbers first, so 3 moves before 5a
Step 2: Compare 5a and 5b, no swap because equal and stable keeps order
3 -> 5a -> 5b -> 2 -> 3 -> null
Why: Stable sort keeps 5a before 5b since they are equal
Step 3: Compare 5b and 2, swap because 2 < 5b
3 -> 5a -> 2 -> 5b -> 3 -> null
Why: Smaller number 2 moves forward
Step 4: Compare 5b and 3, swap because 3 < 5b
3 -> 5a -> 2 -> 3 -> 5b -> null
Why: Smaller number 3 moves forward
Step 5: Compare 5a and 2, swap because 2 < 5a; then compare 5a and 3, no swap because 3 > 5a
3 -> 2 -> 3 -> 5a -> 5b -> null
Why: Smaller number 2 moves forward; 3 is not less than 5a so no swap
Step 6: Compare 3 and 2, swap because 2 < 3
2 -> 3 -> 3 -> 5a -> 5b -> null
Why: 2 moves to front as smallest
Result:
2 -> 3 -> 3 -> 5a -> 5b -> null
Order of equal numbers (3s and 5s) is kept the same as original
Annotated Code
DSA Javascript
class Node {
  constructor(value, label) {
    this.value = value;
    this.label = label; // to track original order
    this.next = null;
  }
}

class LinkedList {
  constructor() {
    this.head = null;
  }

  append(value, label) {
    const newNode = new Node(value, label);
    if (!this.head) {
      this.head = newNode;
      return;
    }
    let curr = this.head;
    while (curr.next) {
      curr = curr.next;
    }
    curr.next = newNode;
  }

  print() {
    let curr = this.head;
    let result = '';
    while (curr) {
      result += curr.value + curr.label + ' -> ';
      curr = curr.next;
    }
    result += 'null';
    console.log(result);
  }
}

function stableSortLinkedList(list) {
  if (!list.head || !list.head.next) return;

  let changed;
  do {
    changed = false;
    let curr = list.head;
    while (curr.next) {
      // Compare values
      if (curr.value > curr.next.value) {
        // Swap values and labels to keep nodes stable
        [curr.value, curr.next.value] = [curr.next.value, curr.value];
        [curr.label, curr.next.label] = [curr.next.label, curr.label];
        changed = true;
      }
      curr = curr.next;
    }
  } while (changed);
}

// Driver code
const list = new LinkedList();
list.append(5, 'a');
list.append(3, '');
list.append(5, 'b');
list.append(2, '');
list.append(3, '');

console.log('Before sorting:');
list.print();
stableSortLinkedList(list);
console.log('After stable sorting:');
list.print();
if (!list.head || !list.head.next) return;
handle empty or single node list - no sorting needed
do { changed = false; let curr = list.head; while (curr.next) { ... } } while (changed);
repeat passes until no swaps - bubble sort approach
if (curr.value > curr.next.value) { swap values and labels; changed = true; }
swap only if current value is greater to keep ascending order and maintain stability by swapping labels with values
curr = curr.next;
advance to next node to compare pairs
OutputSuccess
Before sorting: 5a -> 3 -> 5b -> 2 -> 3 -> null After stable sorting: 2 -> 3 -> 3 -> 5a -> 5b -> null
Complexity Analysis
Time: O(n²) because bubble sort compares pairs repeatedly until sorted
Space: O(1) because sorting happens in place without extra storage
vs Alternative: More efficient sorts like merge sort are O(n log n) and stable, better for large data; bubble sort is simple but slow
Edge Cases
empty list
function returns immediately, no error
DSA Javascript
if (!list.head || !list.head.next) return;
single element list
function returns immediately, no sorting needed
DSA Javascript
if (!list.head || !list.head.next) return;
all elements equal
no swaps happen, original order preserved
DSA Javascript
if (curr.value > curr.next.value) { ... }
When to Use This Pattern
When you need to keep the original order of equal items after sorting, look for a stable sort pattern because it preserves order while sorting.
Common Mistakes
Mistake: Swapping nodes instead of just values can break stability or complicate code.
Fix: Swap only the values and labels inside nodes to keep the node order stable.
Mistake: Using unstable sorts when order of equal elements matters.
Fix: Choose stable sorting algorithms like merge sort or bubble sort for stable results.
Summary
Stable sorting keeps equal items in their original order after sorting.
Use stable sorts when the order of equal elements matters, like sorting cards or records with ties.
The key is to swap values carefully without changing the relative order of equal elements.