基本排序算法分为五类:
①交换排序(冒泡排序、快速排序)
②插入排序(直接插入排序、Shell排序)
③基数排序
④归并排序
⑤堆排序(简单选择排序、堆排序)
①交换排序(冒泡排序、快速排序)
②插入排序(直接插入排序、Shell排序)
③基数排序
④归并排序
⑤堆排序(简单选择排序、堆排序)
下面直接上代码:
#include <iostream>
#include <algorithm>
#include <iterator>
using namespace std;
/*
*********************************************** Insert Sort ************************************************
*/
/*
*********** 0(n2) *************
主要思想:
逐个将无序区的元素插入到有序区,单个元素是有序的。
*/
void DirectInsertSort(int arr[], int length)
{
int tmp;
int index;
for (int i = 1; i < length; ++i)
{
if (arr[i] < arr[i - 1])
{
tmp = arr[i];
index = i;
while (index > 0 && arr[index - 1] > tmp)
{
arr[index] = arr[index - 1];
--index;
}
arr[index] = tmp;
}
}
}
/*
******** nlog(n) < X < O(n2) ************
主要思想:
改进的直接插入排序,依据一组距离向量来确定哪两个元素比较,进而排序。如一组向量为{5,3,1};
*/
void ShellSort(int arr[], int length, int dk)
{
int tmp;
int index;
for (int i = 0; i < length - dk; ++i)
{
if (arr[i] > arr[i + dk])
{
tmp = arr[i + dk];
index = i;
while (index >= 0 && arr[index] > tmp)
{
arr[index + dk] = arr[index];
index -= dk;
}
arr[index + dk] = tmp;
}
}
}
/*
********************************************** Exchange Sort ************************************************
*/
/*
********** X <= O(n2) ***********
主要思想:
这个一个改进的冒泡排序,原始需要O(n2)时间复杂度,原因是原始的排序不是基于相邻元素的比较,所以没一趟仅知道有序区增加一个元素,其它区域的信息依然不知。
以下基于相邻元素的比较,可以确定更多有序区的范围,从而减少趟数,减少时间开销。
*/
void AdvancedBubleSort(int arr[], int length)
{
int tmp = 0;
int index = 0;
for (int i = length - 1; i > 0; --i)
{
for (int j = 0; j < i; ++j)
{
if (arr[j] > arr[j + 1])
{
index = j + 1;
tmp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmp;
}
}
i = index;
index = 0;
}
}
/*
*************O(nlogn) < X < O(n2)*****************
主要思想:
类似二分查找,每次算法都希望将无序数组均分为两个大概相等的子数组,以此递归。
但有可能不理想,会造成和冒泡一样的开销(发生在:每次取到的哨兵元素都是边缘元素)。
*/
int SubFastSort(int arr[], int low, int high)
{
int middle = arr[low];
while (low < high)
{
while (low < high && arr[high] > middle) high--;
if (low == high)
break;
arr[low++] = arr[high];
while (low < high && arr[low] < middle) low++;
if (low == high)
break;
arr[high--] = arr[low];
}
arr[low] = middle;
return low;
}
void FastSort(int arr[], int low, int high)
{
if (low >= high)
return;
int middle = SubFastSort(arr, low, high);
FastSort(arr, low, middle-1);
FastSort(arr, middle+1, high);
}
/*
********************************************** Merging Sort ***************************************************
*/
/*
**************O(nlogn)**************
主要思想:
每次将数组一分为二递归下去,知道子数组元素个数为1,则有序了。
回调过程进行合并。
*/
void MergeArray(int s[], int t[], int low, int middle, int high)
{
int t_index = low;
int s_low = low;
int s_middle = middle + 1;
for ( ; s_low <= middle && s_middle <= high ; )
{
if (s[s_low] < s[s_middle])
t[t_index++] = s[s_low++];
else t[t_index++] = s[s_middle++];
}
while (s_low <= middle) t[t_index++] = s[s_low++];
while (s_middle <= high) t[t_index++] = s[s_middle++];
}
void SubMergingSort(int s[], int t[], int i, int low, int high)
{
if (low == high)
{
if (1 == i%2) t[low] = s[low];
}
else
{
int middle = ((high - low) >> 2) + low; //(low + high)/2;
SubMergingSort(s, t, i+1, low, middle);
SubMergingSort(s, t, i+1, middle+1, high);
if (1 == i%2)
MergeArray(s, t, low, middle, high);
else
MergeArray(t, s, low, middle, high);
}
}
void MergingSort(int arr[], int length)
{
int *p = nullptr;
p = (int *)malloc(sizeof(int)*length);
if (p)
{
SubMergingSort(arr, p, 0, 0, length-1);
free(p);
}
}
/*
************************************************ Heap Sort ********************************************************
*/
/*
*************O(n2)*****************
主要思想:
找到要找的元素才进行交换,减少了交换的次数。
*/
void SimpleSelectSort(int arr[], int length)
{
int min;
for (int i = 0; i < length; ++i)
{
min = i;
for (int j = i+1; j < length; ++j)
{
if (arr[i] > arr[j])
{
min = j;
}
}
if (min != i)
{
arr[min] = arr[min] ^ arr[i];
arr[i] = arr[min] ^ arr[i];
arr[min] = arr[min] ^ arr[i];
}
}
}
/*
************O(nlogn)***************
主要思想:
第一步:
利用数组索引,构建大堆项(排序结果是升序)或者小堆项(排序结果是降序)。
第二步:
交换头尾元素,数组长度变量减1,再构建成大/小堆项,再回到第一步
*/
void ShiftDown(int arr[], int length, int pos)
{
int left, right;
while (pos <= length/2-1)
{
left = pos*2+1;
right = pos*2+2;
if (right < length)
{
if (arr[left] < arr[right])
left = right;
}
if (arr[left] > arr[pos])
{
arr[left] = arr[left] ^ arr[pos];
arr[pos] = arr[left] ^ arr[pos];
arr[left] = arr[left] ^ arr[pos];
pos = left;
}
else break;
}
}
void MakeBigHeap(int arr[], int length)
{
int left;
int right;
for (int i = length/2 - 1; i >= 0; --i)
{
ShiftDown(arr, length, i);
}
}
void HeapSort(int arr[], int length)
{
if (length <= 1)
return ;
MakeBigHeap(arr, length);
int index = length-1;
int left, right;
while (index > 0)
{
swap(arr[0], arr[index--]);
ShiftDown(arr, index+1, 0); // 保持大堆性质
}
}
int main(int argc, char *argv[])
{
int arr[] = {9,5,6,4,8,7,3,1,2,0};
DirectInsertSort(arr, 10);
int dk[] = {5,3,1};
int arr1[] = {9,5,6,4,8,7,3,1,2,0};
for (int i = 0; i < sizeof(dk)/sizeof(int); ++i)
{
ShellSort(arr1, 10, dk[i]);
}
int arr2[] = {9,5,6,4,8,7,3,1,2,0};
AdvancedBubleSort(arr2, 10);
int arr3[] = {1,2,8,3,4,5,7,6,9,0};
MergingSort(arr3, 10);
int arr4[] = {1,2,8,3,4,5,7,6,9,0};
FastSort(arr4, 0, 9);
int arr5[] = {1,2,8,3,4,5,7,6,9,0};
SimpleSelectSort(arr5, 10);
int arr6[] = {1,2,8,3,4,5,7,6,9,0};
HeapSort(arr6, 10);
ostream_iterator<int> os_iter(cout, " ");
copy(begin(arr), end(arr), os_iter);
endl(cout);
copy(begin(arr1), end(arr1), os_iter);
endl(cout);
copy(begin(arr2), end(arr2), os_iter);
endl(cout);
copy(begin(arr3), end(arr3), os_iter);
endl(cout);
copy(begin(arr4), end(arr4), os_iter);
endl(cout);
copy(begin(arr5), end(arr5), os_iter);
endl(cout);
copy(begin(arr6), end(arr6), os_iter);
endl(cout);
return 0;
}