Strand Sort
Strand Sort is a recursive sorting algorithm that repeatedly extracts sorted sublists (strands) from the unsorted list and merges them to create a sorted list.
Steps:
-
Extract a strand: Start from the first element of the list. Extract elements in order as long as they are larger than the last extracted one.
-
Remove extracted elements: Once a strand is extracted, remove those elements from the original list.
-
Merge the strand: Merge the extracted strand into the previously sorted list.
-
Repeat: Repeat the process with the remaining unsorted elements until all elements are sorted.
Example
Let’s take an unsorted list:
[4, 3, 9, 1, 7, 2, 6, 5, 8]
Step-by-Step Execution:
-
Initial list:
Unsorted list = [4, 3, 9, 1, 7, 2, 6, 5, 8] -
Extract the first strand:
- Start with the first element
4. - Next,
9is larger than4, so we add it to the strand. - The extracted strand is
[4, 9].
Now, the unsorted list becomes:
Unsorted list = [3, 1, 7, 2, 6, 5, 8] - Start with the first element
-
Merge the strand with the sorted list:
- The sorted list is initially empty.
- Merging the first strand
[4, 9]results in:
Sorted list = [4, 9].
-
Extract the second strand:
- Start with the first element
3. - Next,
7is larger than3, so we add it to the strand. - The extracted strand is
[3, 7].
Now, the unsorted list becomes:
Unsorted list = [1, 2, 6, 5, 8] - Start with the first element
-
Merge the second strand:
- Merge the second strand
[3, 7]with the sorted list[4, 9]. - The result after merging:
Sorted list = [3, 4, 7, 9].
- Merge the second strand
-
Extract the third strand:
- Start with the first element
1. 2is larger than1, so we add it.6is larger than2, so we add it as well.- The extracted strand is
[1, 2, 6].
Now, the unsorted list becomes:
Unsorted list = [5, 8] - Start with the first element
-
Merge the third strand:
- Merge the third strand
[1, 2, 6]with the sorted list[3, 4, 7, 9]. - The result after merging:
Sorted list = [1, 2, 3, 4, 6, 7, 9].
- Merge the third strand
-
Extract the fourth strand:
- Start with the first element
5. - Next,
8is larger than5, so we add it. - The extracted strand is
[5, 8].
Now, the unsorted list is empty:
Unsorted list = [] - Start with the first element
-
Merge the fourth strand:
- Merge the final strand
[5, 8]with the sorted list[1, 2, 3, 4, 6, 7, 9]. - The result after merging:
Sorted list = [1, 2, 3, 4, 5, 6, 7, 8, 9].
- Merge the final strand
Final Sorted List:
The sorted list is:
[1, 2, 3, 4, 5, 6, 7, 8, 9]
Time Complexity
- Best Case: O(n) (When the array is already sorted, only one strand is extracted and no merging is needed)
- Average Case: O(n^2)
- Worst Case: O(n^2) (When the array is sorted in reverse order, extracting
nstrands of length 1)
Space Complexity
- O(n)
where
nis the number of elements. Space is required for the strands and the resulting sorted list (or the recursive call stack if implemented recursively).
Explanation
Strand sort extracts ascending sublists ("strands") and merges them into a sorted list. If the list is already sorted, it extracts one strand in O(n) time and completes. In the worst case (reverse sorted), it has to extract n strands of length 1, and the merging process takes quadratic time overall. Because it creates sublists to hold the strands and the merged result, it inherently requires O(n) auxiliary space.
Advantages:
- Simple to understand: The process of extracting sorted strands and merging is conceptually easy.
- Works well with linked lists: As strand sort can efficiently handle linked lists, it avoids the overhead of frequent element shifting like in arrays.
- Stable sort: Strand sort maintains the relative order of equal elements.
Disadvantages:
- Not efficient for large datasets: The worst-case time complexity is O(n²), which makes it inefficient for large lists.
- Recursive nature: Its recursive design can lead to high memory usage and potential stack overflow issues for deep recursion.
- Limited use cases: Due to its inefficiency with arrays and larger datasets, it's not commonly used in practice.
Implementations
1. C Implementation
#include <stdio.h>
#include <stdlib.h>
typedef struct Node {
int data;
struct Node* next;
} Node;
Node* newNode(int data) {
Node* node = (Node*)malloc(sizeof(Node));
node->data = data;
node->next = NULL;
return node;
}
void append(Node** head, int data) {
Node* temp = *head;
Node* new_node = newNode(data);
if (!*head) {
*head = new_node;
return;
}
while (temp->next)
temp = temp->next;
temp->next = new_node;
}
Node* merge(Node* a, Node* b) {
if (!a) return b;
if (!b) return a;
if (a->data < b->data) {
a->next = merge(a->next, b);
return a;
} else {
b->next = merge(a, b->next);
return b;
}
}
Node* extractStrand(Node** head) {
Node* curr = *head, *prev = NULL, *strand = NULL, *tail = NULL;
while (curr) {
if (!prev || curr->data >= prev->data) {
if (!strand) strand = tail = curr;
else {
tail->next = curr;
tail = curr;
}
if (prev) prev->next = curr->next;
else *head = curr->next;
curr = curr->next;
tail->next = NULL;
} else {
prev = curr;
curr = curr->next;
}
}
return strand;
}
void strandSort(Node** head) {
Node* sorted = NULL;
while (*head) {
Node* strand = extractStrand(head);
sorted = merge(sorted, strand);
}
*head = sorted;
}
void printList(Node* head) {
while (head) {
printf("%d ", head->data);
head = head->next;
}
printf("\n");
}
int main() {
Node* head = NULL;
int arr[] = {4, 3, 9, 1, 7, 2, 6, 5, 8};
int n = sizeof(arr) / sizeof(arr[0]);
for (int i = 0; i < n; i++) append(&head, arr[i]);
strandSort(&head);
printf("Sorted list: ");
printList(head);
return 0;
}
2) Python Implementation
def merge(a, b):
if not a:
return b
if not b:
return a
if a[0] < b[0]:
return [a[0]] + merge(a[1:], b)
else:
return [b[0]] + merge(a, b[1:])
def extract_strand(lst):
strand = [lst[0]]
i = 1
while i < len(lst):
if lst[i] >= strand[-1]:
strand.append(lst.pop(i))
else:
i += 1
return strand
def strand_sort(lst):
sorted_lst = []
while lst:
strand = extract_strand(lst)
sorted_lst = merge(sorted_lst, strand)
return sorted_lst
# Example usage
lst = [4, 3, 9, 1, 7, 2, 6, 5, 8]
sorted_lst = strand_sort(lst)
print("Sorted list:", sorted_lst)
3) Java Implementation
import java.util.LinkedList;
public class StrandSort {
public static LinkedList<Integer> merge(LinkedList<Integer> a, LinkedList<Integer> b) {
LinkedList<Integer> result = new LinkedList<>();
while (!a.isEmpty() && !b.isEmpty()) {
if (a.peek() <= b.peek()) {
result.add(a.poll());
} else {
result.add(b.poll());
}
}
result.addAll(a);
result.addAll(b);
return result;
}
public static LinkedList<Integer> extractStrand(LinkedList<Integer> list) {
LinkedList<Integer> strand = new LinkedList<>();
strand.add(list.poll());
for (int i = 0; i < list.size(); ) {
if (list.get(i) >= strand.getLast()) {
strand.add(list.remove(i));
} else {
i++;
}
}
return strand;
}
public static LinkedList<Integer> strandSort(LinkedList<Integer> list) {
LinkedList<Integer> sorted = new LinkedList<>();
while (!list.isEmpty()) {
LinkedList<Integer> strand = extractStrand(list);
sorted = merge(sorted, strand);
}
return sorted;
}
public static void main(String[] args) {
LinkedList<Integer> list = new LinkedList<>();
int[] arr = {4, 3, 9, 1, 7, 2, 6, 5, 8};
for (int j : arr) {
list.add(j);
}
LinkedList<Integer> sortedList = strandSort(list);
System.out.println("Sorted list: " + sortedList);
}
}