-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathQuickSort.ts
More file actions
152 lines (134 loc) · 4.4 KB
/
Copy pathQuickSort.ts
File metadata and controls
152 lines (134 loc) · 4.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
import {
IAlgorithm,
changeStatusOfElement,
swapElements,
Bar,
BarStatus,
Steps
} from '@/utils'
const { ACTIVE, SORTED, UNSORTED, PIVOT } = BarStatus
export default class QuickSort implements IAlgorithm {
private steps!: Steps
private colorMode: boolean
constructor(colorMode: boolean) {
this.colorMode = colorMode
}
public sort(arr: Bar[]): Bar[][] {
this.steps = new Steps(arr)
this.quickSort(this.steps.getLastStep(), 0, arr.length - 1)
return [
...this.steps.getSteps(),
this.steps.getLastStep().map(i => {
i.status = BarStatus.SORTED
return i
})
]
}
private quickSort(items: Bar[], left: number, right: number) {
let index
if (left < right) {
index = this.partition(this.steps.getLastStep(), left, right)
this.quickSort(this.steps.getLastStep(), left, index - 1)
this.quickSort(this.steps.getLastStep(), index, right)
}
return items
}
private partition(items: Bar[], left: number, right: number): number {
const initialLeft = left
const initialRight = right
const pivot = items[Math.floor((right + left) / 2)]
if (this.colorMode) {
changeStatusOfElement(this.steps.getSteps(), pivot, PIVOT)
}
while (left <= right) {
if (this.colorMode) {
changeStatusOfElement(this.steps.getSteps(), items[left], ACTIVE)
changeStatusOfElement(this.steps.getSteps(), items[right], ACTIVE)
}
while (items[left].value < pivot.value) {
if (this.colorMode) {
this.makePreviousEleUnsorted(items[left - 1], initialLeft, left)
changeStatusOfElement(this.steps.getSteps(), items[left], ACTIVE)
this.steps.addStep()
}
left++
}
while (items[right].value > pivot.value) {
if (this.colorMode) {
this.makePreviousEleUnsorted(items[right + 1], initialRight, right)
changeStatusOfElement(this.steps.getSteps(), items[right], ACTIVE)
this.steps.addStep()
}
right--
}
if (left <= right) {
if (this.colorMode) {
this.makePreviousEleUnsorted(items[left - 1], initialLeft, left)
this.makePreviousEleUnsorted(items[right + 1], initialRight, right)
changeStatusOfElement(this.steps.getSteps(), items[left], ACTIVE)
changeStatusOfElement(this.steps.getSteps(), items[right], ACTIVE)
}
items = this.steps.getLastStep()
items = swapElements(
[...this.steps.getLastStep()],
this.steps.getLastStep()[left],
this.steps.getLastStep()[right]
)
this.steps.addStep(items)
this.steps.addStep()
left++
right--
}
/**
* Make element status 'SORTED'
* @conditions
* - If the sub array under partition has length 2 or less
* - And the left and right pointer is not out of array index bound
* - And left pointer is greater than right pointer then the element is SORTED
*
*/
if (
initialRight - initialLeft <= 2 &&
this.ifIndicesAreOutOfBound(left, right) &&
left > right
) {
changeStatusOfElement(this.steps.getSteps(), items[left], SORTED)
changeStatusOfElement(this.steps.getSteps(), items[right], SORTED)
} else {
this.makePreviousEleUnsorted(items[left - 1], initialLeft, left)
this.makePreviousEleUnsorted(items[right + 1], initialRight, right)
}
}
/**
* Make pivot status SORTED
* @condition
* - If the sub array under partition has length 2 or less then the pivot after the loop will be sorted
*/
this.steps.addStep()
if (initialRight - initialLeft <= 3) {
changeStatusOfElement(this.steps.getSteps(), pivot, SORTED)
} else {
changeStatusOfElement(this.steps.getSteps(), pivot, UNSORTED)
}
// return left
return Math.max(left, right)
}
private makePreviousEleUnsorted(
ele: Bar,
initialIndex: number,
currentIndex: number
): void {
// if the element is the first element there is no previous element
if (initialIndex !== currentIndex) {
changeStatusOfElement(this.steps.getSteps(), ele, UNSORTED)
}
}
private ifIndicesAreOutOfBound(left: number, right: number): boolean {
return (
left >= 0 &&
left < this.steps.getLastStep().length &&
right >= 0 &&
right < this.steps.getLastStep().length
)
}
}