demo.cpp:
#include <iostream>
#include "my_sort.h"
int main(void)
{
using namespace std;
const int SIZE = 30;
int arr[SIZE] = {1,1,9,9,6,6,8,8,4,4,0,0,7,7,5,5,2,2,3,3,1,9,6,8,4,0,7,5,2,3};
//InsertSort(arr, SIZE);
//BinarySort(arr, SIZE);
//BubbleSort(arr, SIZE);
//SelectSort(arr, SIZE);
//HeapSort(arr, SIZE);
//QuickSort(arr, SIZE);
//NonrecursiveQuickSort(arr, SIZE);
//MergeSort(arr, SIZE);
//NonrecursiveQuickSort(arr, SIZE);
//ShellSort(arr, SIZE);
RadixSort(arr, SIZE);
for (int i = 0; i < SIZE; ++i)
{
cout << arr[i] << endl;
}
return 0;
}
my_sort.h:
//sort integer numbers in ascending order
//for RadixSort, use LSD strategy and handle non-negative integer
#ifndef __MY_SORT
#define __MY_SORT
#include <cmath>
void InsertSort(int *arr, const int size);
void BinarySort(int *arr, const int size);
void BubbleSort(int *arr, const int size);
void SelectSort(int *arr, const int size);
void HeapSort(int *arr, const int size);
void QuickSort(int *arr, const int size);
void NonrecursiveQuickSort(int *arr, const int size);
void MergeSort(int *arr, const int size);
void NonrecursiveMergeSort(int *arr, const int size);
void ShellSort(int *arr, const int size);
void RadixSort(int *arr, const int size);
#endif
my_sort.cpp:
#include "my_sort.h"
void InsertSort(int *arr, const int size)
{
for (int i = 1; i < size; ++i)
{
int temp = arr[i];
int j;
for (j = i-1; j >= 0 ; --j)
{
if (temp < arr[j])
{
arr[j+1] = arr[j];
}
else
{
break;
}
}
arr[j+1] = temp;
}
return;
}
int BinarySearch(int *arr, int target, int size)
{
int left = 0;
int right = size - 1;
int middle;
while (left <= right)
{
middle = (left + right)/2;
if (target < arr[middle])
{
right = middle - 1;
}
else
{
left = middle + 1;
}
}
return left;
}
void BinarySort(int *arr, const int size)
{
for (int temp, idx, i = 1; i < size; ++i)
{
temp = arr[i];
idx = BinarySearch(arr, temp, i);
for (int j = i-1; j >= idx; --j)
{
arr[j+1] = arr[j];
}
arr[idx] = temp;
}
return;
}
void BubbleSort(int *arr, const int size)
{
bool isChanged = true;
for (int i = size - 1; isChanged && i > 0; --i)
{
isChanged = false;
for (int j = 1; j <= i; ++j)
{
if (arr[j] < arr[j-1])
{
isChanged = true;
arr[j] ^= arr[j-1];
arr[j-1] ^= arr[j];
arr[j] ^= arr[j-1];
}
}
}
return;
}
void SelectSort(int *arr, const int size)
{
for (int i = 0; i < size; ++i)
{
int k = i;
for (int j = i + 1; j < size; ++j)
{
if (arr[j] < arr[k])
{
k = j;
}
}
if (k != i)
{
arr[i] ^= arr[k];
arr[k] ^= arr[i];
arr[i] ^= arr[k];
}
}
return;
}
void CreateBigRootHeap(int *arr, int rt_idx, int size)
{//create big-root heap
int temp;
while (2*rt_idx + 1 < size)
{
temp = 2*rt_idx + 1;
if (temp + 1 < size)
{
if (arr[temp] < arr[temp + 1])
{
++temp;
}
}
if (arr[rt_idx] < arr[temp])
{//the heap may be disturbed and need reordering
arr[rt_idx] ^= arr[temp];
arr[temp] ^= arr[rt_idx];
arr[rt_idx] ^= arr[temp];
rt_idx = temp;
}
else
{
break;
}
}
return;
}
void HeapSort(int *arr, const int size)
{
//Firtly, ceate big-root heap first
for (int i = size/2 - 1; i >= 0; --i)
{
CreateBigRootHeap(arr, i, size);
}
for (int i = size - 1; i > 0; --i)
{
//make an element be in the right order
arr[0] ^= arr[i];
arr[i] ^= arr[0];
arr[0] ^= arr[i];
//reorder to make the rest be big-root heap
CreateBigRootHeap(arr, 0, i);
}
return;
}
int Partition(int *arr, int left, int right)
{
int temp = arr[left];
while (left < right)
{
while (left < right)
{
if(temp <= arr[right])
{
--right;
}
else
{
arr[left++] = arr[right];
break;
}
}
while (left < right)
{
if (arr[left] <= temp)
{
++left;
}
else
{
arr[right--] = arr[left];
break;
}
}
}
arr[left] = temp;
return left;
}
void MyQuickSort(int *arr, int beg, int end)
{
if (beg < end)
{
int p_idx = Partition(arr, beg, end);
MyQuickSort(arr, beg, p_idx - 1);
MyQuickSort(arr, p_idx + 1, end);
}
return;
}
void QuickSort(int *arr, const int size)
{
MyQuickSort(arr, 0, size - 1);
return;
}
void NonrecursiveQuickSort(int *arr, const int size)
{
int beg = 0, end = size - 1;
if (beg < end)
{
const int SIZE = 30;//change along with the size of the sequence.
struct
{
int beg;
int end;
}st[SIZE];
int ptr = 0, idx;
st[ptr].beg = beg;st[ptr].end = end;++ptr;
while (ptr)
{
--ptr;beg = st[ptr].beg;end = st[ptr].end;
idx = Partition(arr, beg, end);
if (beg < idx - 1)
{
st[ptr].beg = beg;st[ptr].end = idx - 1;++ptr;
}
if (idx + 1 < end)
{
st[ptr].beg = idx + 1;st[ptr].end = end;++ptr;
}
}
}
return;
}
void MergeArray(int *arr, int beg1, int end1, int beg2, int end2, int *temp)
{//in fact, (end1 + 1) must be equal to beg2 in this implementation.
int m1 = beg1, n1 = end1, m2 = beg2, n2 = end2;
int idx = 0;
while (m1 <= n1 && m2 <= n2)
{
temp[idx++] = (arr[m2] < arr[m1])?arr[m2++]:arr[m1++];
}
while (m1 <= n1)
{
arr[--m2] = arr[n1--]; //this trick can reduce the unnecessary element move
}
while (idx > 0)
{
arr[--m2] = temp[--idx];
}
}
void MyMergeSort(int *arr, int beg, int end, int *temp)
{
if (beg < end)
{
int mid = (beg + end)/2;
MyMergeSort(arr, beg, mid, temp);
MyMergeSort(arr, mid + 1, end, temp);
MergeArray(arr, beg, mid, mid + 1, end, temp);
}
return;
}
void MergeSort(int *arr, const int size)
{
if(0 < size)
{
int *temp = new int[size];
MyMergeSort(arr, 0, size - 1, temp);
delete[] temp;
}
}
void NonrecursiveMergeSort(int *arr, const int size)
{
if (0 < size)
{
int *temp = new int[size];
int m1, n1, m2, n2;
for (int step = 1; step < size; step *=2)
{
for(m1 = 0; m1 < size - step; m1 = n2)
{
n1 = m2 = m1 + step;
n2 = m2 + step;
if (n2 > size)
{
n2 = size;
}
MergeArray(arr, m1, n1 - 1, m2, n2 - 1, temp);
}
}
delete[] temp;
}
return;
}
void ShellSort(int *arr, const int size)
{
for (int i, j, temp, step = size/2; step > 0; step /= 2)
{
for (i = step; i < size; ++i)
{
temp = arr[i];
j = i - step;
while (j >= 0 && temp < arr[j])
{
arr[j+step] = arr[j];
j -= step;
}
arr[j+step] = temp;
}
}
return;
}
int GetMaxElement(int *arr, const int size)
{
int temp = 0;
if (0 < size)
{
temp = arr[0];
for (int i = 1; i < size; ++i)
{
if (temp < arr[i])
{
temp = arr[i];
}
}
}
return temp;
}
int GetLoopTimes(int elem)
{
const int radix = 10;
int num = 0;
do{
++num;
}while(elem /= 10);
return num;
}
void OnePassRadixSort(int *arr, const int size, int digit_pos)
{
const int radix = 10;
int *temp = new int[size*radix];
int *counts = new int[radix];
int t = 1;
while (--digit_pos)
{
t *= radix;
}
for (int i = 0; i < radix; ++i)
{
*(counts + i) = 0;
}
for (int i = 0; i < size; ++i)
{
int d = arr[i]/t%radix;
temp[d*size+(*(counts+d))++] = arr[i];
}
int i = 0;
for (int d = 0; d < radix; ++d)
{
for (int k = 0; k < *(counts+d); ++k)
{
arr[i++] = temp[d*size+k];
}
}
return;
}
void RadixSort(int *arr, const int size)
{
if (0 < size)
{
int max_elem = GetMaxElement(arr, size);
int loop_times = GetLoopTimes(max_elem);
for (int i = 1; i <= loop_times; ++i)
{
OnePassRadixSort(arr, size, i);
}
}
return;
}
Java Implementation:
package com.huawei.test;
import java.util.Arrays;
import java.util.Stack;
public class SortTools {
public static void main(String[] args) {
System.out.println("mySortTool");
int[] arr = new int[] { 4, 2, 3, 1, 5, -1, 2, 3, -1, -2, 0 };
int[] arr1 = new int[] { 4, 2, 3, 1, 5, 11, 2, 3, 12, 10, 0 };
// bubbleSort(arr);
// insertSort(arr);
// binaryInsertSort(arr);
// selectSort(arr);
// heapSort(arr);
// quickSort(arr);
// nonRecursiveQuickSort(arr);
// mergeSort(arr);
// nonRecursiceMergeSort(arr);
// shellSort(arr);
radixSortLSD(arr1);
System.out.print(Arrays.toString(arr1));
}
private static void swap(int[] arr, int a, int b) {
arr[a] ^= arr[b];
arr[b] ^= arr[a];
arr[a] ^= arr[b];
}
/**
* bubble sort time Complexity: O(n^2) space Complexity: O(1) stability: stable
*
* @param arr data need to be sorted
*/
public static void bubbleSort(int[] arr) {
if ((arr == null) || (arr.length < 2)) {
return;
}
boolean isNeedTry = true;
for (int j, i = 0; (i < (arr.length - 1) && isNeedTry); i++) { // each traversal settle an element
isNeedTry = false;
for (j = i + 1; j < arr.length; j++) { // find the final element for position (arr.length - 1 - i)
if (arr[j - 1] > arr[j]) {
// swap
swap(arr, j - 1, j);
isNeedTry = true;
}
}
}
}
/**
* insert sort. time Complexity: O(n^2), space Complexity: O(1), stability:
* stable
*
* @param arr data need to be sorted
*/
public static void insertSort(int[] arr) {
if ((arr == null) || (arr.length < 2)) {
return;
}
for (int temp, j, i = 1; i < arr.length; i++) { // each traversal settle an element
temp = arr[i];
for (j = i - 1; j != 0; j--) { // find the final position for element i
if (temp < arr[j]) {
arr[j + 1] = arr[j];
} else {
break;
}
}
arr[j + 1] = temp;
}
}
/**
* find the right position for target to put when inserted into an increasing
* sequence
*
* @param arr increasing sequence
* @param begin start position of the increasing sequence
* @param end end position of the increasing sequence
* @param target element need to be inserted
* @return
*/
private static int binarySearch(int[] arr, int begin, int end, int target) {
int left = begin;
int right = end;
int mid;
while (left <= right) {
mid = (begin + end) / 2;
if (target >= arr[mid]) {
left = mid + 1;
} else {
right = mid - 1;
}
}
return left;
}
/**
* binary search insert sort. time Complexity: O(n^2), space Complexity: O(1),
* stability: stable
*
* @param arr data need to be sorted
*/
public static void binaryInsertSort(int[] arr) {
if ((arr == null) || (arr.length < 2)) {
return;
}
for (int temp, idx, j, i = 1; i < arr.length; i++) { // each traversal settle an element
temp = arr[i];
idx = binarySearch(arr, 0, i - 1, arr[i]); // find the final position for element i, decrease compare
// operation
for (j = i; j > idx; j--) {
arr[j] = arr[j - 1];
}
arr[idx] = temp;
}
}
/**
* select sort. time Complexity: O(n^2), space Complexity: O(1), stability:
* unstable
*
* @param arr data need to be sorted
*/
public static void selectSort(int[] arr) {
if ((arr == null) || (arr.length < 2)) {
return;
}
for (int k, j, i = 0; i < (arr.length - 1); i++) { // each traversal settle an element
k = i;
for (j = (i + 1); j < arr.length; j++) { // find the final position for element i
if (arr[k] > arr[j]) {
k = j;
}
}
if (k != i) { // swap
swap(arr, k, i);
}
}
}
/**
* make a binary tree be big-root heap on condition that the child binary trees
* are all big-root heap
*
* @param arr the whole sequence need to be handled
* @param parent the root of the sub binary tree
* @param size the size of the whole binary tree
*/
private static void adjustToBigRootHeap(int[] arr, int parentIdx, int size) {
int bigIdx;
while ((bigIdx = (parentIdx * 2) + 1) < size) {
if (((bigIdx + 1) < size) && (arr[bigIdx] < arr[bigIdx + 1])) {
bigIdx = bigIdx + 1;
}
if (arr[parentIdx] < arr[bigIdx]) {
swap(arr, parentIdx, bigIdx);
parentIdx = bigIdx;
} else {
break;
}
}
}
/**
* make the sequence be big-root heap
*
* @param arr sequence need to be handled
*/
private static void createBigRootHeap(int[] arr) {
for (int i = ((arr.length / 2) - 1); i >= 0; i--) {
adjustToBigRootHeap(arr, i, arr.length);
}
}
/**
* heap sort. time Complexity: O(n*log(n)), space Complexity: O(1), stability:
* unstable
*
* @param arr data need to be sorted
*/
public static void heapSort(int[] arr) {
if ((arr == null) || (arr.length < 2)) {
return;
}
// firstly, make the array be a big-root heap
createBigRootHeap(arr);
// secondly, make the array be increasing order
for (int i = (arr.length - 1); i > 0; i--) {
swap(arr, 0, i); // set the biggest element to the final position
adjustToBigRootHeap(arr, 0, i); // make the rest element keep being big-root heap
}
}
/**
* split the sequence into two part based on element begin, elements in the left
* part are all smaller than element begin, elements in the right part are all
* bigger than element begin.
*
* @param arr sequence need to be handled
* @param begin the beginning position of the sequence
* @param end the ending position of the sequence
* @return the partition position
*/
private static int partition(int[] arr, int begin, int end) {
int temp = arr[begin];
while (begin < end) {
while (begin < end) {
if (temp <= arr[end]) {
end--;
} else {
arr[begin++] = arr[end];
break;
}
}
while (begin < end) {
if (arr[begin] <= temp) {
begin++;
} else {
arr[end--] = arr[begin];
break;
}
}
}
arr[begin] = temp;
return begin;
}
/**
* sort the sequence in a recursive way
*
* @param arr sequence need to be handled
* @param begin the beginning position of the sequence
* @param end the ending position of the sequence
*/
private static void myQuickSort(int[] arr, int begin, int end) {
if (begin >= end) {
return;
}
int partitionIdx = partition(arr, begin, end);
myQuickSort(arr, begin, partitionIdx - 1);
myQuickSort(arr, partitionIdx + 1, end);
}
/**
* quick sort. time Complexity: O(n*log(n)), space Complexity: O(log(n)),
* stability: unstable. (at the worst situation, time Complexity: O(n^2),
* Complexity: O(n))
*
* @param arr data need to be sorted
*/
public static void quickSort(int[] arr) {
if ((arr == null) || (arr.length < 2)) {
return;
}
myQuickSort(arr, 0, arr.length - 1);
}
/**
* non recursive quick sort. time Complexity: O(n*log(n)), space Complexity:
* O(log(n)), stability: unstable. (at the worst situation, time Complexity:
* O(n^2), Complexity: O(n))
*
* @param arr data need to be sorted
*/
public static void nonRecursiveQuickSort(int[] arr) {
if ((arr == null) || (arr.length < 2)) {
return;
}
class Pair<A, B> {
A first;
B second;
Pair(A a, B b) {
first = a;
second = b;
}
}
Stack<Pair<Integer, Integer>> sortStates = new Stack<Pair<Integer, Integer>>();
sortStates.push(new Pair<Integer, Integer>(0, arr.length - 1));
while (!sortStates.isEmpty()) {
Pair<Integer, Integer> sortPair = sortStates.pop();
if (sortPair.first < sortPair.second) {
int pivotalIdx = partition(arr, sortPair.first, sortPair.second);
sortStates.push(new Pair<Integer, Integer>(sortPair.first, pivotalIdx - 1));
sortStates.push(new Pair<Integer, Integer>(pivotalIdx + 1, sortPair.second));
}
}
}
/**
* merge two sequence in increasing order into one sequence with increasing
* order
*
* @param assist the temporary space to perform the merge action
* @param arr sequence need to be handled
* @param beg1 the beginning position of the first sequence
* @param end1 the ending position of the first sequence
* @param beg2 the beginning position of the second sequence
* @param end2 the ending position of the second sequence
*/
private static void merge(int[] assist, int[] arr, int beg1, int end1, int beg2, int end2) {
// in fact, (end1 + 1) must be equal to beg2 in this implementation.
int i = 0;
while ((beg1 <= end1) && (beg2 <= end2)) {
assist[i++] = (arr[beg1] < arr[beg2]) ? arr[beg1++] : arr[beg2++];
}
while (beg1 <= end1) {
// this trick can reduce the unnecessary element move
arr[--beg2] = arr[end1--];
}
while (i > 0) {
arr[--beg2] = assist[--i];
}
}
/**
* sort the sequence in a recursive way
*
* @param assist the temporary space to perform the merge action
* @param arr sequence need to be handled
* @param beg the beginning position of the sequence
* @param end the ending position of the sequence
*/
private static void myMergeSort(int[] assist, int[] arr, int beg, int end) {
if (beg < end) {
int mid = ((beg + end) / 2);
myMergeSort(assist, arr, beg, mid);
myMergeSort(assist, arr, (mid + 1), end);
merge(assist, arr, beg, mid, (mid + 1), end);
}
}
/**
* recursive merge sort. time Complexity: O(n*log(n)), space Complexity: O(n),
* stability: stable.
*
* @param arr data need to be sorted
*/
public static void mergeSort(int[] arr) {
if ((arr == null) || (arr.length < 2)) {
return;
}
int[] assist = new int[arr.length];
myMergeSort(assist, arr, 0, arr.length - 1);
}
/**
* non recursive merge sort. time Complexity: O(n*log(n)), space Complexity:
* O(n), stability: stable.
*
* @param arr data need to be sorted
*/
public static void nonRecursiceMergeSort(int[] arr) {
if ((arr == null) || (arr.length < 2)) {
return;
}
int[] assist = new int[arr.length];
for (int beg, mid, end, step = 1; step < arr.length; step *= 2) {
for (beg = 0; (mid = (beg + step)) < arr.length; beg += 2 * step) {
end = ((mid + step) < arr.length) ? (mid + step - 1) : (arr.length - 1);
merge(assist, arr, beg, mid - 1, mid, end);
}
}
}
/**
* shell sort(diminishing increment sort). time Complexity: O(n*log(2n)), space
* Complexity: O(1), stability: unstable. Shell Increment: N/(2^1), N/(2^2),
* ..., 1}, time Complexity O(n^2), O(n*log(2n)). Hibbard Increment: time
* Complexity O(n^1.5)
*
* @param arr data need to be sorted
*/
public static void shellSort(int[] arr) {
if ((arr == null) || (arr.length < 2)) {
return;
}
for (int i, j, temp, delta = (arr.length / 2); delta > 0; delta /= 2) {
for (i = delta; (j = i) < arr.length; i++) {
temp = arr[i];
while (((j -= delta) >= 0) && arr[j] > temp) {
arr[j + delta] = arr[j];
}
arr[j + delta] = temp;
}
}
}
/**
* radix sort(least significant digit). time Complexity: O(d*n), space
* Complexity: O(n), stability: stable.
*/
public static void radixSortLSD(int[] arr) {
if ((arr == null) || (arr.length < 2)) {
return;
}
// find max value
int max = arr[0];
for (int i = 1; i < arr.length; i++) {
if (max < arr[i]) {
max = arr[i];
}
}
final int RADIX = 10;
int[] assist = new int[arr.length];
for (int exp = 1; (max / exp) > 0; exp *= RADIX) {// n times of dispatch and collect
int[] bucket = new int[RADIX];
for (int i = 0; i < arr.length; i++) {// count for each radix
bucket[((arr[i] / exp) % RADIX)]++;
}
for (int i = 1; i < RADIX; i++) {// calculate increment number
bucket[i] += bucket[i - 1];
}
for (int i = arr.length - 1; i >= 0; i--) {// dispatch and collect on the temporary space
assist[--bucket[((arr[i] / exp) % RADIX)]] = arr[i];
}
for (int i = 0; i < arr.length; i++) {// store into the final space
arr[i] = assist[i];
}
}
}
}