大家熟知的排序方式有冒泡排序、选择排序,这两种排序方式在处理少量数据的排序时比较方便,但当数据量变大时效率明显变低。在此我们引入了新的排序方式比如:插入排序、归并排序、希尔排序、堆排序、快排。
1. 插入排序
直接插入排序:适用于数据量少且非常接近有序。(稳定)
(1)时间复杂度:最优—–已序—-O(N) / 最差—-逆序—-O(N^2)
(2)空间复杂度:O(1)
2.归并排序
归并排序:稳定(没有最好最坏的情况)
(1)时间复杂度:O(NlgN)
(2)空间复杂度:O(N+lgN)=O(N)
3.希尔排序
缩小增量排序
时间复杂度:O(N^1.25) ~ O(1.6N^1.25)
空间复杂度:O(1)
不稳定
4.堆排序
使用堆结构排序
(1)升序排序:使用最大堆
(2)降序排序:使用最小堆
时间复杂度:O(NlgN)
空间复杂度:O(1)
不稳定
5.快排
快排对大量数据的排序效率很高
快排的代码实现有三种方式:
(1)从两边向中间推进法
(2)挖坑法
(3)追赶法
【Sort.h】
#include<iostream>
using namespace std;
//插入排序
void InsertSort(int *arr,int size)
{
for (int i = 1; i < size; i++)
{
int key = arr[i];
int end = i - 1;
int j = 0;
for (j = end; j >= 0; j--)
{
if (arr[j]>key)
arr[j + 1] = arr[j];
else
{
arr[j + 1] = key;
break;
}
}
arr[j + 1] = key;
}
}
//折半插入排序
void BinaryInsert(int *arr,int size)
{
for (int i = 1; i < size; i++)
{
int key = arr[i];
int end = i - 1;
int left = 0;
int right = i;
while (left < right)
{
int mid = left + (right - left) / 2;
if (key<arr[mid])
right=mid-1; //right有可能越界,所以交换元素时用left
else
left=mid+1;
}
for (int j = i; j>right; j--)
{
arr[j] = arr[j-1];
}
arr[left] = key;
}
}
////////////////////////////////////////////////////////////////////
//希尔排序
void ShellSort(int* arr,int size)
{
int gap = size;
while (gap)
{
gap = gap / 3 + 1;
for (int i = 0; i < gap; i++)
{
for (int j = i+gap; j < size; j += gap)
{
if (arr[j] < arr[j - gap])
{
int ret = arr[j];
int k = j - gap;
while (k>=0 && arr[k]>ret)
{
arr[k + gap] = arr[k];
k = k - gap;
}
arr[k + gap] = ret;
}
}
}
if (gap == 1)
break;
}
}
/////////////////////////////////////////////////////////////////////
//选择排序1
void SelectSort1(int *arr, int size)
{
int i, j;
int k = 0;
for (i = 0; i < size - 1; i++)
{
k = i;
for (j = i; j < size;j++)
{
if (arr[k]>arr[j])
k = j;
}
swap(arr[k], arr[i]);
}
}
void SelectSort(int* arr,int size) //选择排序2
{
int begin = 0;
int end = size - 1;
while (begin < end)
{
int minset = begin;
int maxset = begin;
for (int i = begin; i <= end; i++)
{
if (arr[maxset] < arr[i])
maxset = i;
if (arr[minset]>arr[i])
minset = i;
}
if (arr[maxset]>arr[end])
swap(arr[maxset],arr[end]);
if (minset == end)
minset = maxset;
if (arr[minset]<arr[begin])
swap(arr[minset], arr[begin]);
begin++;
end--;
}
}
//////////////////////////////////////////////////////////////////////////////
int GetMidNumber(int *arr,int left,int right)
{
if (left > right)
return right;
int mid = left + (right - left) / 2;
if (arr[left] < arr[right])
{
if (arr[mid] < arr[left])
return left;
else if (arr[right] < arr[mid])
return right;
else
return mid;
}
else
{
if (arr[mid]>arr[left])
return left;
else if (arr[mid < arr[right]])
return right;
else
return mid;
}
}
//////////////
//快排
int position1(int*arr,int left,int right) //左右向中推进法
{
int begin = left;
int end = right;
int key = arr[end];
while (begin<end)
{
while (arr[begin] <=key)
{
begin++;
}
if (begin == right)
return right;
while (begin!=end&&arr[end]>=key)
{
end--;
}
if (begin == end)
{
swap(arr[begin], arr[right]);
return begin;
}
else
swap(arr[begin], arr[end]);
}
return begin;
}
int position2(int *arr,int left,int right) //追赶法
{
int temp = GetMidNumber(arr, left, right);
if (temp != right)
swap(arr[temp], arr[right]);
int key = arr[right];
int cur = left;
int pur = left - 1;
while (cur!=right+1)
{
if (arr[cur] <key)
{
pur++;
if (arr[cur] == arr[pur])
cur++;
else
{
swap(arr[cur], arr[pur]);
}
}
else
{
cur++;
}
}
if (left<right)
swap(arr[pur + 1], arr[right]);
pur++;
return pur;
}
int position3(int *arr, int left, int right) //挖坑法
{
int key = arr[right]; //基准值
/*int ret = GetMidNumber(arr, left, right);
int key = arr[ret];*/
int begin = left;
int end = right;
while (begin<end)
{
while (arr[begin] <= key)
{
if (end == begin)
break;
begin++;
}
if (begin == right)
break;
if (begin!=end)
arr[end] = arr[begin];
while (arr[end] > key)
{
if (end == begin)
break;
end--;
}
if (begin != end)
arr[begin] = arr[end];
}
if (begin==end)
arr[begin] = key;
return begin;
}
void _QuickSort(int *arr, int left, int right)
{
//int div = position1(arr,left,right);
int div = position2(arr, left,right);
//int div = position3(arr, left, right);
if (left < right)
{
_QuickSort(arr, left, div-1);
_QuickSort(arr, div + 1, right);
}
}
void QuickSort(int* arr, int size)
{
int left = 0;
int right = size-1;
_QuickSort(arr, left, right);
}
//////////////////////////////////////////////////////////////////////
//计数排序
int Range(int *arr, int size, int& max, int& min)
{
for (int i = 0; i < size; i++)
{
if (arr[i]>max)
max = arr[i];
if (arr[i] < min)
min = arr[i];
}
return (max - min+1);
}
void CountSort(int *arr, int size)
{
int maxData = arr[0];
int minData = arr[0];
int len= Range(arr, size, maxData, minData); //len为辅助空间的长度
int* temp = new int[len];
memset(temp, 0, sizeof(int)*len);
for (int i = 0; i <size; i++)
{
temp[arr[i] - minData]++;
}
int index = 0;
for (int j = 0; j < len; j++)
{
while (temp[j]--)
{
arr[index++] = j + minData;
}
}
delete[] temp;
}
///////////////////////////////////////////////////////////////////////////////
//归并排序
void Merge(int *cur,int left,int mid,int right,int *temp)
{
int set1 = left;
int set2 = mid;
int set = left;
while (set1 < mid&&set2 < right)
{
if (cur[set1] < cur[set2])
temp[set++] = cur[set1++];
else
temp[set++] = cur[set2++];
}
while (set1 < mid)
{
temp[set++] = cur[set1];
set1++;
}
while (set2 < right)
{
temp[set++] = cur[set2++];
}
memcpy(cur+left,temp+left,sizeof(int)*(right-left));
}
void _MergeSort(int* arr,int left,int right,int *temp)
{
if (left+1 < right)
{
int mid = left + (right - left) / 2; //区间是左闭右开
_MergeSort(arr, left, mid, temp);
_MergeSort(arr, mid, right, temp);
Merge(arr, left, mid, right, temp);
}
}
void MergeSort(int *array, int size)
{
int *temp = new int[size];
_MergeSort(array, 0, size, temp);
delete[] temp;
}
void Display(int arr[],int size)
{
for (int i = 0; i < size; i++)
{
cout << arr[i] << " ";
}
cout << endl;
}
/////////////////////////////////////////////////////////////////////////////////
void TestSort()
{
//int array[] = { 3, 2, 4, 1, 0, 8, 6, 7, 9, 5 };
int array[] = { 1, 3, 5, 4, 2, 1, 3, 6, 9, 9, 6, 8, 8, 0, 0 };
//int array[] = { 3, 4, 2, 1, 5 ,4,4,0};
int size = sizeof(array) / sizeof(array[0]);
CountSort(array, size); //计数排序
//QuickSort(array, size); //快速排序
//SelectSort1(array, size); //插入排序1
//ShellSort(array, size); //希尔排序
//BinaryInsert(array, size); //折半插入排序
//InsertSort(array, size); //插入排序2
//MergeSort(array,size); //归并排序
//SelectSort(array, size); //选择排序
Display(array, size);
}
【test.c】
#include"Sort.h"
int main()
{
TestSort();
system("pause");
return 0;
}