Skip to content

Commit

Permalink
fm_sort optimized if the array is sorted. refer 13 Feb to 15 Feb Prog…
Browse files Browse the repository at this point in the history
…ressReport_sorting.md for detailed changes
  • Loading branch information
fenilgmehta committed Feb 21, 2019
1 parent 359167c commit 4acd2a5
Show file tree
Hide file tree
Showing 10 changed files with 126 additions and 892 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
cmake-build-debug/*
CMakeList.txt

ProgressReport.md
ProgressReport_sorting.md
references/*
test/*.out

Expand Down
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
cmake_minimum_required(VERSION 3.8)
project(project_Sorting C CXX)

set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_VERBOSE_MAKEFILE on)

add_subdirectory(src)
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,15 +60,15 @@ The graphs above shows how ir_sort::integer_sort starts performing better with h
Usage
----------------------------------
For projects:
```
```c++
// copy the following four files to the project folder: "basic_sorts.hpp", "ir_commons.hpp", "integer_sort.cpp" and "integer_sort_objects_small.cpp"

// paste the following lines in the file start
include "integer_sort.cpp"
```

For competitions:
```
```c++
// copy the namespace "ir_sort" from "ir_sort_competitions.cpp" to the main ".cpp" program file

// to call the function, from the namespace "ir_sort"
Expand Down
158 changes: 4 additions & 154 deletions src/basic_sorts.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -155,84 +155,10 @@ namespace ir_sort {
merge_basic_asc<RandomAccessIterator, ArrayValueType>(arr, low, mid, high);
}

//=================================================
// INSERTION SORT
template<typename RandomAccessIterator, typename ArrayValueType>
inline void insertion_sort_basic_desc(RandomAccessIterator arr, const int_fast64_t low, const int_fast64_t high) {
ArrayValueType key;

for (int_fast64_t i = low + 1, j; i <= high; ++i) {
key = arr[i];
j = i - 1;

// Move elements of arr[low...i-1], that are greater than key, to one position ahead of their current position
while (j >= low && arr[j] < key) {
arr[j + 1] = arr[j];
--j;
}
arr[j + 1] = key;
}
}

// MERGE sort
template<typename RandomAccessIterator, typename ArrayValueType>
inline void merge_basic_desc(RandomAccessIterator arr, const int_fast64_t low, const int_fast64_t mid, const int_fast64_t high) {
// "mid" points to the END of FIRST sub-array
// arr[mid] is the last element of the first sub-array

int_fast64_t i, j, k;
int_fast64_t leftArray_length = mid - low + 1, rightArray_length = high - mid;
ArrayValueType L[leftArray_length]; // this will work here because we use merge_sort only for array size < approx 500
RandomAccessIterator R = std::next(arr, mid+1);

for (i = low, j = 0; j < leftArray_length; ++i, ++j) {
L[j] = arr[i];
}

for (i = 0, j = 0, k = low; k <= high; ++k) {
if (i < leftArray_length && j < rightArray_length) {
if (L[i] >= R[j]) {
arr[k] = L[i++];
// arr[k] = L[i];
// ++i;
} else {
arr[k] = R[j++];
// arr[k] = R[j];
// ++j;
}
} else if (i == leftArray_length) {
return;
} else if (j == rightArray_length) {
while (k <= high) arr[k++] = L[i++];
return;
}
}
}

template<typename RandomAccessIterator, typename ArrayValueType>
inline void merge_sort_basic_desc(RandomAccessIterator arr, const int_fast64_t low, const int_fast64_t high) {
if (low >= high) return;

if ((high - low) < INSERTION_SORT_THRESHOLD) {
insertion_sort_basic_desc<RandomAccessIterator, ArrayValueType>(arr, low, high);
return;
}

int_fast64_t mid = (low + high) >> 1; // int64_t mid = (low + high) / 2;

if ((mid - low) < INSERTION_SORT_THRESHOLD) insertion_sort_basic_desc<RandomAccessIterator, ArrayValueType>(arr, low, mid);
else merge_sort_basic_desc<RandomAccessIterator, ArrayValueType>(arr, low, mid);

if ((high - mid - 1) < INSERTION_SORT_THRESHOLD) insertion_sort_basic_desc<RandomAccessIterator, ArrayValueType>(arr, mid + 1, high);
else merge_sort_basic_desc<RandomAccessIterator, ArrayValueType>(arr, mid + 1, high);

merge_basic_desc<RandomAccessIterator, ArrayValueType>(arr, low, mid, high);
}

//=================================================
// MERGE SORT and INSERTION SORT hybrid
template<typename RandomAccessIterator>
inline void merge_sort(RandomAccessIterator start, RandomAccessIterator end, bool ascendingOrder) {
inline void merge_sort(RandomAccessIterator start, RandomAccessIterator end) {
// return if RandomAccessIterator is not a random_access_iterator
if (typeid(typename std::iterator_traits<RandomAccessIterator>::iterator_category) != typeid(std::random_access_iterator_tag))
return;
Expand All @@ -247,8 +173,7 @@ namespace ir_sort {
// NOTE: determine the type of elements stored in the array to be sorted, and it pointer type
using ArrayValueType = typename std::iterator_traits<RandomAccessIterator>::value_type;

if (ascendingOrder) merge_sort_basic_asc<RandomAccessIterator, ArrayValueType>(start, low, high);
else merge_sort_basic_desc<RandomAccessIterator, ArrayValueType>(start, low, high);
merge_sort_basic_asc<RandomAccessIterator, ArrayValueType>(start, low, high);
}

//############################################################################
Expand Down Expand Up @@ -330,84 +255,10 @@ namespace ir_sort {
merge_asc<RandomAccessIterator, ArrayValueType, myGetIndex>(arr, low, mid, high, getIndex);
}

//=================================================
// INSERTION SORT
template<typename RandomAccessIterator, typename ArrayValueType, typename myGetIndex>
inline void insertion_sort_desc(RandomAccessIterator arr, const int_fast64_t low, const int_fast64_t high, myGetIndex getIndex) {
ArrayValueType key;

for (int_fast64_t i = low + 1, j; i <= high; ++i) {
key = arr[i];
j = i - 1;

// Move elements of arr[low...i-1], that are greater than key, to one position ahead of their current position
while (j >= low && getIndex(arr[j]) < getIndex(key)) {
arr[j + 1] = arr[j];
--j;
}
arr[j + 1] = key;
}
}

// MERGE SORT
template<typename RandomAccessIterator, typename ArrayValueType, typename myGetIndex>
inline void merge_desc(RandomAccessIterator arr, const int_fast64_t low, const int_fast64_t mid, const int_fast64_t high, myGetIndex getIndex) {
// "mid" points to the END of FIRST sub-array
// arr[mid] is the last element of the first sub-array

int_fast64_t i, j, k;
int_fast64_t leftArray_length = mid - low + 1, rightArray_length = high - mid;
ArrayValueType L[leftArray_length]; // CHECK: not sure if this would suffice for large object arrays
RandomAccessIterator R = std::next(arr, mid+1);

for (i = low, j = 0; j < leftArray_length; ++i, ++j) {
L[j] = arr[i];
}

for (i = 0, j = 0, k = low; k <= high; ++k) {
if (i < leftArray_length && j < rightArray_length) {
if (getIndex(L[i]) >= getIndex(R[j])) {
arr[k] = L[i++];
// arr[k] = L[i];
// ++i;
} else {
arr[k] = R[j++];
// arr[k] = R[j];
// ++j;
}
} else if (i == leftArray_length) {
return;
} else if (j == rightArray_length) {
while (k <= high) arr[k++] = L[i++];
return;
}
}
}

template<typename RandomAccessIterator, typename ArrayValueType, typename myGetIndex>
inline void merge_sort_desc(RandomAccessIterator arr, const int_fast64_t low, const int_fast64_t high, myGetIndex getIndex) {
if (low >= high) return;

if ((high - low) < INSERTION_SORT_THRESHOLD) {
insertion_sort_desc<RandomAccessIterator, ArrayValueType, myGetIndex>(arr, low, high, getIndex);
return;
}

int_fast64_t mid = (low + high) >> 1; // int64_t mid = (low + high) / 2;

if ((mid - low) < INSERTION_SORT_THRESHOLD) insertion_sort_desc<RandomAccessIterator, ArrayValueType, myGetIndex>(arr, low, mid, getIndex);
else merge_sort_desc<RandomAccessIterator, ArrayValueType, myGetIndex>(arr, low, mid, getIndex);

if ((high - mid - 1) < INSERTION_SORT_THRESHOLD) insertion_sort_desc<RandomAccessIterator, ArrayValueType, myGetIndex>(arr, mid + 1, high, getIndex);
else merge_sort_desc<RandomAccessIterator, ArrayValueType, myGetIndex>(arr, mid + 1, high, getIndex);

merge_desc<RandomAccessIterator, ArrayValueType, myGetIndex>(arr, low, mid, high, getIndex);
}

//=================================================
// MERGE SORT
template<typename RandomAccessIterator, typename myGetIndex>
inline void merge_sort(RandomAccessIterator first, RandomAccessIterator last, bool ascendingOrder, myGetIndex getIndex) {
inline void merge_sort(RandomAccessIterator first, RandomAccessIterator last, myGetIndex getIndex) {
// return if RandomAccessIterator is not a random_access_iterator
if (typeid(typename std::iterator_traits<RandomAccessIterator>::iterator_category) != typeid(std::random_access_iterator_tag))
return;
Expand All @@ -422,8 +273,7 @@ namespace ir_sort {
// NOTE: determine the type of elements stored in the array to be sorted, and it pointer type
using ArrayValueType = typename std::iterator_traits<RandomAccessIterator>::value_type;

if (ascendingOrder) merge_sort_asc<RandomAccessIterator, ArrayValueType, myGetIndex>(first, low, high, getIndex);
else merge_sort_desc<RandomAccessIterator, ArrayValueType, myGetIndex>(first, low, high, getIndex);
merge_sort_asc<RandomAccessIterator, ArrayValueType, myGetIndex>(first, low, high, getIndex);
}

} // namespace basic_sorts
Expand Down
Loading

0 comments on commit 4acd2a5

Please sign in to comment.