#include<stdio.h>
#include<math.h>
#include<stdlib.h>
#include<assert.h>
#include <time.h>
//归并排序
void Merge(int *arr,int len,int gap)
{
int *brr = (int *)malloc(sizeof(int)*len);
assert(brr != NULL);
int i = 0;//brr下标
int start1 = 0;
int end1 = start1 + gap-1;
int start2 = end1 + 1;
int end2 = start2 + gap - 1 < len - 1 ? start2 + gap -1 : len - 1;
//当有两个归并段时
while(start2 < len)
{
//当两个归并段还没有比较完的时候
while(start1 <= end1 && start2 <= end2)
{
if(arr[start1] <= arr[start2])
{
brr[i++] = arr[start1++];
}
else
{
brr[i++] = arr[start2++];
}
}
while(start1 <= end1)
{
brr[i++] = arr[start1++];
}
while(start2 <= end2)
{
brr[i++] = arr[start2++];
}
// 找两个新的归并段
start1 = end2 +1;
end1 = start1 + gap-1;
start2 = end1 + 1;
end2 = start2 + gap - 1 < len - 1 ? start2 + gap -1:len - 1;
}
while(start1 < len)
{
brr[i++] = arr[start1++];
}
for(int i = 0;i < len;i++)
{
arr[i] = brr[i];
}
}
void MergeSort(int *arr,int len)
{
for(int i = 1;i < len;i *= 2)
{
Merge(arr,len,i);
}
}
void Show(int *arr,int len)
{
for(int i = 0;i < len;i++)
{
printf("%d ",arr[i]);
}
printf("\n");
}
//快排的优化
int Partion(int *arr,int low,int high)
{
int tmp = arr[low];
while(low < high)
{
while(low < high && arr[high] >= tmp)
{
high--;
}
if(low >= high)
{
break;
}
else
{
arr[low] = arr[high];
}
while(low < high && arr[low] <= tmp)
{
low++;
}
if(low >= high)
{
break;
}
else
{
arr[high] = arr[low];
}
}
arr[low] = tmp;
return low;
}
void Swap(int *arr,int start,int end)
{
int tmp = arr[start];
arr[start] = arr[end];
arr[end] = tmp;
}
//优化方式一:当待排序的区间中,待排序的个数小于某一个数量级的时候,使用插入排序
// (插入排序越有序越快)
// 时间复杂度:O(n)
void InsertSort(int *arr,int low,int high)
{
for(int i = low+1;i <= high;i++)
{
int tmp = arr[i];
int j = 0;
for(j = i-1;j >= low;j--)
{
if(arr[j] > tmp)
{
arr[j+1] = arr[j];
}
else
{
break;
}
}
arr[j+1] = tmp;
}
}
void Quick1(int *arr,int start,int end)
{
//InsertSort(arr,start,end);
if((end-start)+1 <= 10000)
{
InsertSort(arr,start,end);
}
}
void QuickSort1(int *arr,int len)
{
Quick1(arr,0,len-1);
}
//排序方式2:随机选取基准法
void Quick2(int *arr,int start,int end)
{
srand((unsigned int)time(NULL));
Swap(arr, start,rand() % (end-start)+start);
int par = Partion(arr,start,end);//O(n)
//左边
if(par > start + 1)
{
Quick2(arr,start,par - 1);//log(2n)
}
//右边
if(par < end - 1)
{
Quick2(arr,par + 1,end);
}
}
void QuickSort2(int *arr,int len)
{
Quick2(arr,0,len-1);
}
//聚集相同元素基准法
void FocusNumPar(int *arr,int low,int par,int high,int *left,int *right)
{
if(low < high)
{
int parLeft = par-1;
for(int i = par - 1;i >= low;i--)
{
if(arr[i] == arr[par])
{
if(i != parLeft)
{
Swap(arr,i,parLeft);
parLeft--;
}
else
{
parLeft--;
}
}
}
*left = parLeft;
int parRight = par+1;
for(int i = par+1;i <= high;i++)
{
if(arr[i] == arr[par])
{
if(i != parRight)
{
Swap(arr,i,parRight);
parRight++;
}
else
{
parRight++;
}
}
}
*right = parRight;
}
}
void Quick3(int *arr,int start,int end)
{
int par = Partion(arr,start,end);//O(n)
int left = 0;
int right = 0;
FocusNumPar(arr,start,par,end,&left,&right);
//左边
if(left >= start+1)//说明左边有两个数据以上
{
Quick3(arr,start,left);
}
//右边
if(right <= end-1)
{
Quick3(arr,right,end);
}
}
void QuickSort3(int *arr,int len)
{
Quick3(arr,0,len-1);
}
//1 2 3 4 5 6
//排序方式3:三分取中法
void SelectPivotMedianOfThree(int *arr,int low,int high)
{
int mid = (high-low)/2 + low;//(high+low)>>1;
//arr[mid]<=arr[low]<=arr[high];
if(arr[mid] > arr[low])
{
Swap(arr,mid,low);
}//arr[mid] <= arr[low]
if(arr[low] > arr[high])
{
Swap(arr,low,high);
}//arr[low] <= arr[high]
if(arr[mid] > arr[high])
{
Swap(arr,mid,high);
}//arr[mid] <= arr[high]
}
void Quick4(int *arr,int start,int end)
{
int par = Partion(arr,start,end);
SelectPivotMedianOfThree(arr,start,end);
if(par >= start+1)//说明左边有两个数据以上
{
Quick4(arr,start,par-1);
}
if(par <= end-1)
{
Quick4(arr,par+1,end);
}
}
void QuickSort4(int *arr,int len)
{
Quick4(arr,0,len-1);
}
int main()
{
int arr[10000] = {};
int len = sizeof(arr)/sizeof(arr[0]);
srand(time(NULL));
for(int i = 0;i < len;i++)
{
arr[i] = rand()%10000;
}
//MergeSort(arr,len);
//QuickSort1(arr,len);
//QuickSort2(arr,len);
//QuickSort3(arr,len);
//QuickSort4(arr,len);
Show(arr,len);
return 0;
}