-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmergesortengine.ts
124 lines (107 loc) · 3.11 KB
/
mergesortengine.ts
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
import ISortEngine from "./isortengine";
import appsettings from "../../appsettings";
import SortingHelper from "./sortinghelper";
import ItemElementMap from "./typings/itemelementmap";
import SortOptions from "../../components/stage/typings/sortoptions";
class MergeSortEngine implements ISortEngine {
// array to sort
private array: ItemElementMap[];
// sort options
private options: SortOptions;
/**
* constructor of merge sort engine
*/
constructor(array: ItemElementMap[], options: SortOptions) {
this.array = array;
this.options = options;
}
/**
* sort and visualize the array sorting
*/
public sort = async () => {
let low = 0;
let high = this.array.length - 1;
await this.mergeSort(this.array, low, high);
};
/**
* merge sort items
*/
private mergeSort = async (
array: ItemElementMap[],
low: number,
high: number
) => {
if (low < high) {
// find mid of array and divide the array to two.
let mid = Math.floor((low + high) / 2);
// call merge sort recursively for lot to mid and mid + 1 to high
await this.mergeSort(array, low, mid);
await this.mergeSort(array, mid + 1, high);
// merge the two arrays back to main array
await this.merge(array, low, mid, high);
}
};
/**
* merge items
*/
private merge = async (
array: ItemElementMap[],
low: number,
mid: number,
high: number
) => {
let i = low;
let j = mid + 1;
let k = low;
let newArray: ItemElementMap[] = [];
/**
* compare two arrays. first array from low to mid point and second array
* from mid + 1 to high. if element from first array id smaller add it to
* new array. otherwise add element from second array.
*/
while (i <= mid && j <= high) {
if (array[i].value <= array[j].value) {
newArray[k] = array[i];
i++;
} else {
newArray[k] = array[j];
j++;
}
k++;
}
/**
* When either of the above condition is failed, one of the array item will
* be added to new array. we need to find the other array and add all remaining
* items to the new array.
*/
if (i > mid) {
while (j <= high) {
newArray[k] = array[j];
j++;
k++;
}
} else {
while (i <= mid) {
newArray[k] = array[i];
i++;
k++;
}
}
let filteredArray = newArray.filter((i) => i !== null);
let isLastMerge = array.length === filteredArray.length;
let color = appsettings.itemColor;
// merge new array created in the above step to original array
for (k = low; k <= high; k++) {
array[k] = newArray[k];
let previousIndex = array[k].previousIndex;
let totalMovement = (k - previousIndex) * (this.options.itemWidth + 1);
// animate element movement and wait for UI change
await SortingHelper.animate(array[k].element, totalMovement);
await SortingHelper.sleep(this.options.getSortingSpeed());
if (isLastMerge) {
array[k].element.style.backgroundColor = color.sorted;
}
}
};
}
export default MergeSortEngine;