Skip to content

Commit 796582a

Browse files
authored
Add IntroSort Algorithm in R (#239)
1 parent 4ec0df4 commit 796582a

File tree

1 file changed

+121
-0
lines changed

1 file changed

+121
-0
lines changed

sorting_algorithms/intro_sort.r

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
# Intro sort in R:
2+
3+
# IntroSort is a hybrid sorting algorithm that starts with Quick Sort,
4+
# switches to Heap Sort when recursion depth grows too large, and uses
5+
# Insertion Sort for small partitions. This provides robust O(n log n)
6+
# worst-case performance with excellent average-case behavior.
7+
8+
intro.sort <- function(elements.vec) {
9+
n <- length(elements.vec)
10+
if (n <= 1) return(elements.vec)
11+
12+
SIZE_THRESHOLD <- 16
13+
# Depth limit: 2 * floor(log2(n)) similar to the canonical definition
14+
max.depth <- floor(2 * log(n, base = 2))
15+
16+
insertion.sort.range <- function(arr, low, high) {
17+
if (low >= high) return(arr)
18+
if ((low + 1) <= high) {
19+
for (i in (low + 1):high) {
20+
key <- arr[i]
21+
j <- i - 1
22+
while (j >= low && arr[j] > key) {
23+
arr[j + 1] <- arr[j]
24+
j <- j - 1
25+
}
26+
arr[j + 1] <- key
27+
}
28+
}
29+
return(arr)
30+
}
31+
32+
heap.sort.range <- function(arr, low, high) {
33+
n <- high - low + 1
34+
if (n <= 1) return(arr)
35+
36+
heapify <- function(a, heap.size, i, offset) {
37+
# 0-based heap indices mapped into 'a' via 'offset'
38+
repeat {
39+
largest <- i
40+
left <- 2 * i + 1
41+
right <- 2 * i + 2
42+
43+
if (left < heap.size && a[offset + left] > a[offset + largest]) {
44+
largest <- left
45+
}
46+
if (right < heap.size && a[offset + right] > a[offset + largest]) {
47+
largest <- right
48+
}
49+
50+
if (largest != i) {
51+
tmp <- a[offset + i]
52+
a[offset + i] <- a[offset + largest]
53+
a[offset + largest] <- tmp
54+
i <- largest
55+
} else {
56+
break
57+
}
58+
}
59+
return(a)
60+
}
61+
62+
# Build max heap
63+
if ((floor(n / 2) - 1) >= 0) {
64+
for (i in seq(floor(n / 2) - 1, 0, by = -1)) {
65+
arr <- heapify(arr, n, i, low)
66+
}
67+
}
68+
69+
# Extract elements from heap
70+
for (i in seq(n - 1, 1, by = -1)) {
71+
tmp <- arr[low]
72+
arr[low] <- arr[low + i]
73+
arr[low + i] <- tmp
74+
arr <- heapify(arr, i, 0, low)
75+
}
76+
return(arr)
77+
}
78+
79+
partition.range <- function(arr, low, high) {
80+
pivot <- arr[high]
81+
i <- low - 1
82+
if (low <= (high - 1)) {
83+
for (j in low:(high - 1)) {
84+
if (arr[j] <= pivot) {
85+
i <- i + 1
86+
tmp <- arr[i]
87+
arr[i] <- arr[j]
88+
arr[j] <- tmp
89+
}
90+
}
91+
}
92+
tmp <- arr[i + 1]
93+
arr[i + 1] <- arr[high]
94+
arr[high] <- tmp
95+
return(list(arr = arr, p = i + 1))
96+
}
97+
98+
util <- function(arr, low, high, depth.limit) {
99+
if (low >= high) return(arr)
100+
size <- high - low + 1
101+
if (size <= SIZE_THRESHOLD) {
102+
return(insertion.sort.range(arr, low, high))
103+
}
104+
if (depth.limit == 0) {
105+
return(heap.sort.range(arr, low, high))
106+
}
107+
pr <- partition.range(arr, low, high)
108+
arr <- pr$arr
109+
p <- pr$p
110+
arr <- util(arr, low, p - 1, depth.limit - 1)
111+
arr <- util(arr, p + 1, high, depth.limit - 1)
112+
return(arr)
113+
}
114+
115+
elements.vec <- util(elements.vec, 1, n, max.depth)
116+
return(elements.vec)
117+
}
118+
119+
# Example:
120+
# intro.sort(c(10, 7, 8, 9, 1, 5, 3, 12))
121+
# [1] 1 3 5 7 8 9 10 12

0 commit comments

Comments
 (0)