结合《王道》,整理了常用的排序算法,包括直接插入排序、希尔排序、冒泡排序、快速排序、简单选择排序、堆排序、二路归并排序。
各排序算法的性能平均表:
代码如下:
#include <iostream>
#define N 10
using namespace std;
void InsertSort(int arr[]);//直接插入排序,时间复杂度O(n2),空间复杂度O(1)
void ShellSort(int arr[]);//希尔排序
void BubbleSort(int arr[]);//冒泡排序,时间复杂度O(n2),空间复杂度O(1)
void QuickSort(int arr[]);//快速排序,时间复杂度O(nlogn),O(nlogn)
void quickSort(int arr[], int low, int high);
int Partition(int arr[], int low, int high);//划分算法,两个指针分别从首尾向中间
int Partition_l2r(int arr[], int low, int high);//划分算法,两个前后指针,从首向尾,左半部分顺序不变
int Partition_r2l(int arr[], int low, int high);//划分算法,两个前后指针,从尾向首,右半部分顺序不变
void SelectSort(int arr[]);//简单选择排序,时间复杂度O(n2),空间复杂度O(1)
void HeapSort(int arr[], int len);
void BuildMaxHeap(int arr[], int len);//构建大根堆,len为元素个数N-1(因为下标从0开始)
void AdjustDown(int arr[], int k, int len);//从上往下调整
void AdjustUp(int arr[], int k);//从下往上调整
void MergeSort(int arr[]);//归并排序
void mergeSort(int arr[], int low, int high);//原始归并变换
void Merge(int arr[], int low, int mid, int high);//合并两个有序数组(有辅助数组)
void Merge_b(int arr[], int low, int mid ,int high);//合并两个有序数组(无辅助数组)
void reverse(int arr[], int low, int high);//(翻转数组元素)
void exchange(int arr[], int low, int mid, int high);//(交换两个数组位置)
int main(){
int arr[] = {1, 6, 4, 9, 0, 5, 8, 2, 7, 3};
//int arr[] = {20, 18, 22, 16, 30, 19};
//int arr[] = {87, 45, 78, 32, 17, 65, 53, 9, 63};
//InsertSort(arr);
//ShellSort(arr);
//BubbleSort(arr);
//QuickSort(arr);
//SelectSort(arr);
//BuildMaxHeap(arr, N-1);
//HeapSort(arr, N-1);
//AdjustUp(arr, N-1);
MergeSort(arr);
for(int i=0; i<N; ++i)
cout << arr[i] << ' ';
cout << endl;
return 0;
}
void MergeSort(int arr[]){
int len = N-1;
mergeSort(arr, 0, len);
}
void mergeSort(int arr[], int low, int high){
if(low < high){
int mid = (low+high)/2;//分解
mergeSort(arr, low, mid);//
mergeSort(arr, mid+1, high);
//Merge(arr, low, mid, high);//合并(方式一)
Merge_b(arr, low, mid, high);//合并(方式二)
}
}
void Merge_b(int arr[], int low, int mid ,int high)
{
int i=low, j=mid+1, k = high;
while(i<= mid && j<= high){
int step=0;
while(i<=mid && arr[i]<=arr[j]) ++i;
while(j<=high && arr[j]<=arr[i]){
++j;
++step;
}
exchange(arr, i, mid, j-1);
i += step;
mid += step;
}
}
void reverse(int arr[], int low, int high){
int stop = (low+high)/2;
for(; low<=stop; ++low, --high){
int temp = arr[low];
arr[low] = arr[high];
arr[high] = temp;
}
}
void exchange(int arr[], int low, int mid, int high){
reverse(arr, low, mid);
reverse(arr, mid+1, high);
reverse(arr, low, high);
}
void Merge(int arr[], int low, int mid, int high){
int i=low, j=mid+1, k=low;
int *arr_temp = new int[high+1];//辅助数组
while(i<=mid && j<=high){//遍历两个子数组
if(arr[i] > arr[j]){//把较小的先放入辅助数组中
arr_temp[k] = arr[j];
++j;
++k;
}
else{
arr_temp[k] = arr[i];
++i;
++k;
}
}
while(i<=mid)//若左端子数组有剩余,把剩余的数字放入辅助数组
arr_temp[k++] = arr[i++];
while(j<=high)//若右端子数组有剩余,把剩余的数字放入辅助数组
arr_temp[k++] = arr[j++];
for(i=low; i<=high; ++i){//把辅助数组复制到arr中
arr[i] = arr_temp[i];
}
}
void HeapSort(int arr[], int len){
BuildMaxHeap(arr, len);
for(int i=len; i>0; --i){
int temp = arr[0];//交换堆顶和最后一个元素
arr[0] = arr[i];
arr[i] = temp;
AdjustDown(arr, 0, i-1);//注:这里一直k=0,即从堆顶开始向下把剩余i-1个数进行调整
}
}
void BuildMaxHeap(int arr[], int len){
for(int i=(len-1)/2; i>=0; --i){
AdjustDown(arr, i, len);
}
}
void AdjustDown(int arr[], int k, int len){
int temp = arr[k];
for(int i=2*k+1; i<=len; i = 2*i+1){
if(i<=len-1 && arr[i+1] > arr[i])
i++;
if(temp >= arr[i])//不交换
break;
else{
arr[k] = arr[i];//替换
k=i;//下移
}
}
arr[k] = temp;//替换
}
void AdjustUp(int arr[], int k){
int temp = arr[k];//暂存
int i = (k-1)/2;//初始化父节点
while(i>=0 && temp > arr[i]){//如果插入节点比父节点大
arr[k] = arr[i];
k = i;
i = (k-1)/2;
}
arr[k] = temp;
}
void SelectSort(int arr[]){
for(int i=0; i<N-1; ++i){
int min = i;
for(int j=i+1; j<N; ++j){
if(arr[j] < arr[min]){
int temp = arr[j];
arr[j] = arr[min];
arr[min] = temp;
}
}
}
}
void QuickSort(int arr[]){
quickSort(arr, 0, N-1);
}
void quickSort(int arr[], int low, int high){
if(low < high){
//int k = Partition(arr, low, high);
//int k = Partition_l2r(arr, low, high);
int k = Partition_r2l(arr, low, high);
quickSort(arr, low, k-1);//递归
quickSort(arr, k+1, high);
}
}
int Partition(int arr[], int low, int high){
int temp = arr[low];
while(low<high){
while(low < high && arr[high] > temp) --high;
arr[low] = arr[high];
while(low < high && arr[low] < temp) ++low;
arr[high] = arr[low];
}
arr[low] = temp;
return low;
}
int Partition_l2r(int arr[], int low, int high){
int temp = arr[high];
int i=low-1, j=low;
for(; j < high; ++j){
if(arr[j]<=temp){//控制升序降序
++i;
int t = arr[j];
arr[j] = arr[i];
arr[i] = t;
}
}
int t = arr[i+1];
arr[i+1] = arr[high];
arr[high] = t;
return i+1;
}
int Partition_r2l(int arr[], int low, int high){
int temp = arr[low];
int i=high, j=high+1;
for(; i > low; --i){
if(arr[i] >= temp){//控制升序降序
--j;
int t = arr[j];
arr[j] = arr[i];
arr[i] = t;
}
}
int t = arr[j-1];
arr[j-1] = arr[low];
arr[low] = t;
return j-1;
}
void BubbleSort(int arr[]){
int i, j;
for(i=1; i<N; ++i){
for(j=0; j<N-i; ++j){//每排序一轮,就确定一位较大的值,并放在次尾部
if(arr[j]>arr[j+1]){
int temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
}
void ShellSort(int arr[]){
int dist=N/2;
int temp;
int i, j;
for(;dist>0; dist/=2){//与直接排序的区别
for(i=dist+1; i<N; ++i){
if(arr[i]<arr[i-dist]){
temp = arr[i];
for(j=i-dist; arr[j]>temp; j-=dist)
arr[j+dist] = arr[j];
arr[j+dist] = temp;
}
}
}
}
void InsertSort(int arr[]){
int temp;
int i, j;
for(i=1; i< N; ++i){
if(arr[i] < arr[i-1]){
temp = arr[i];
for(j=i-1; arr[j]>temp; --j)
arr[j+1] = arr[j];
arr[j+1] = temp;
}
}
}