1、插入排序
大概步骤如上图,下面实现代码
void InsertSort(int* arr,size_t n)//插入排序
{
assert(arr);
for(size_t index=1;index<n;index++)
{
size_t tmp=arr[index];
int pos=index-1;
while (pos>=0&&arr[pos]>tmp)
{
arr[pos+1]=arr[pos];
pos--;
}
arr[pos+1]=tmp;
}
}
2、希尔排序
void ShellSort(int* arr,size_t n)//希尔排序
{
int gap=n/3+1;
for(size_t index=gap;index<n;index++)
{
size_t tmp=arr[index];
int pos=index-gap;
while(pos>=0&&arr[pos]>tmp)
{
arr[pos+gap]=arr[pos];
pos-=gap;
}
arr[pos+gap]=tmp;
}
}
3、冒泡排序
重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。
不再做过多解释,直接上代码
void PopSort(int* arr,size_t n)//冒泡排序
{
for(int i=0;i<n;i++)
{
for(int j=i+1;j<n;j++)
{
if(arr[i]>arr[i+1])
{
int tmp=arr[i];
arr[i]=arr[i+1];
arr[i+1]=tmp;
}
}
}
}
4、选择排序
每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完。
代码如下
void selectSort(int*arr ,size_t n)
{
int min;
int tmp;
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
min=i;
if(arr[min]>arr[j])
{
min=j;
}
tmp=arr[min];
arr[min]=arr[j];
arr[j]=tmp;
}
}
}
优化的选择排序
每次选一个最小值放最前面,选最大一个值放后面
代码如下
void SelectSort2(int* arr,int n)
{
assert(arr);
int left=0;
int right=n-1;
while (left<right)
{
int min=left;
int max=right;
for (int i=left;i<=right;++i)
{
if (arr[min]>=arr[i])
{
min=i;
}
if(arr[max]<=arr[i])
{
max=i;
}
}
swap(arr[left],arr[min]);
if (left==max)
{
max=min;
}
swap(arr[right],arr[max]);
left++;
right--;
}
}
5、快速排序
通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
挖坑法块排,选第一数做比较
void FastSort(int* arr,int low,int high)//设置一个低位一个高位,进行快速排序
{
if(low>=high)
return;
int first=low;
int last=high;
int mid=ThreeMid(arr,first,last);
swap(arr[mid],arr[first]);
int key=arr[first];//用挖坑法
while (first<last)
{
while(first<last&&arr[last]>=key)
{
--last;
}
arr[first]=arr[last];
while (first<last&&arr[first]<=key)
{
++first;
}
arr[last]=arr[first];
}
arr[first]=key;
FastSort(arr,low,first-1);
FastSort(arr,first+1,high);
}
挖坑法选最后数做比较
单趟:
int PartSort2(int* arr,int first,int last)//挖坑法
{
int left=first;
int right=last;
int key=ThreeMid(arr,first,last);
swap(arr[key],arr[last]);
int tmp=arr[last];
while (left<right)
{
while (left<right&&arr[left]<=tmp)
{
++left;
}
arr[right]=arr[left];
while(left<right&&arr[right]>=tmp)
{
--right;
}
arr[left]=arr[right];
}
arr[left]=tmp;
return left;
}
递归
void QuickSort2(int* arr,int first,int last)
{
if(first<last)
{
int key=PartSort2(arr,first,last);
QuickSort2(arr,first,key-1);
QuickSort2(arr,key+1,last);
}
}
快排优化
当数组数超过13个进行快排,否则插入排序
void QuickSort2(int* arr,int first,int last)
{
if(first<last)
{
if ((last-first)>=13)
{
int key=PartSort2(arr,first,last);
QuickSort2(arr,first,key-1);
QuickSort2(arr,key+1,last);
}
else
InsertSort(arr,sizeof(arr)/sizeof(arr[0]));
}
}
前后指针法,数组前后个一个指针,同时进行排序
int PartSort(int* arr,int left,int right)
{
int mid=ThreeMid(arr,left,right);
swap(arr[mid],arr[right]);
int key=arr[right];
int first=left;
int last=right-1;
while(first<last)
{
while (first<last&&arr[first]<=key)
{
++first;
}
while (first<last&&arr[last]>=key)
{
--right;
}
swap(arr[first],arr[last]);
}
if(arr[first]>arr[right]);
swap(arr[first],arr[right]);
return first;
}
void QuickSort3(int* arr,int left,int right)
{
while (left<right)
{
int mid=PartSort(arr,left,right);
QuickSort3(arr,left,mid-1);
QuickSort3(arr,mid+1,right);
}
}
6、堆排序
堆分为大根堆和小根堆,是完全二叉树。大根堆的要求是每个节点的值都不大于其父节点的值,即A[PARENT[i]] >= A[i]。在数组的非降序排序中,需要使用的就是大根堆,因为根据大根堆的要求可知,最大的值一定在堆顶。
建堆
void AdjustDown(int* arr,int index,int n)
{
int parent=index;
int child=2*parent+1;
while (child<n)
{
if(child<n&&arr[child]<arr[child+1])
child++;
if (child<n&&arr[child]>arr[parent])
{
swap(arr[parent],arr[child]);
parent=child;
child=2*parent+1;
}
else
break;
}
child=parent;
}
堆排序
void HeapSort(int* arr,int n)
{
for(int i=n/2-1;i>=0;--i)
{
AdjustDown(arr,i,n);
}
for(int j=n-1;j>0;--j)
{
swap(arr[j],arr[0]);
AdjustDown(arr,0,j);
}
if(arr[0]>arr[1])
swap(arr[0],arr[1]);
}
7、归并排序
归并过程为:比较a[i]和a[j]的大小,若a[i]≤a[j],则将第一个有序表中的元素a[i]复制到r[k]中,并令i和k分别加上1;否则将第二个有序表中的元素a[j]复制到r[k]中,并令j和k分别加上1,如此循环下去,直到其中一个有序表取完,然后再将另一个有序表中剩余的元素复制到r中从下标k到下标t的单元。归并排序的算法我们通常用递归实现,先把待排序区间[s,t]以中点二分,接着把左边子区间排序,再把右边子区间排序,最后把左区间和右区间用一次归并操作合并成有序的区间[s,t]。
单趟排序
void Merge(int* arr,int* tmp,int first,int mid,int last)//归并
{
int i=first;int j=mid+1;int k=first;
while (i!=mid+1&&j!=last+1)
{
if(arr[i]>arr[j])
tmp[k++]=arr[j++];
else
tmp[k++]=arr[i++];
}
while(i!=mid+1)
{
tmp[k++]=arr[i++];
}
while (j!=last+1)
{
tmp[k++]=arr[j++];
}
for(i=first;i<=last;i++)
arr[i]=tmp[i];
}
递归归并
void MergeSort(int* arr,int* tmp,int first,int last)//归并排序
{
int mid;
if (first<last)
{
mid= first+((last-first)>>1);
MergeSort(arr,tmp,first,mid);
MergeSort(arr,tmp,mid+1,last);
Merge(arr,tmp,first,mid,last);
}
}
三数求中法
int ThreeMid(int* arr,int left,int right)//找首位,末尾和中点中中间的数
{
int mid=left+((right-left)>>1);
while (left<right)
{
if(arr[left]<arr[right])
{
if(arr[mid]<arr[left])
return left;
else if(arr[right]<arr[mid])
return right;
else
return mid;
}
if(arr[left]>arr[right])
{
if(arr[mid]<arr[right])
return right;
else if(arr[mid]>arr[left])
return left;
else
return mid;
}
}
return mid;
}
三数中中间值进行比较避免了用最后一位比较时最后一位是最大值或用第一位比较时第一位是最小值,降低了时间复杂度。
测试代码
int main()
{
int arr[]={9,3,5,1,4,7,8,0};
int tmp[8];
//int arr[]={2,3,6,5,4,13,56};
cout<<"原数组 : ";
Print(arr,sizeof(arr)/sizeof(arr[0]));
InsertSort(arr,sizeof(arr)/sizeof(arr[0]));
cout<<"插入排序: ";
Print(arr,sizeof(arr)/sizeof(arr[0]));
ShellSort(arr,sizeof(arr)/sizeof(arr[0]));
cout<<"希尔排序: ";
Print(arr,sizeof(arr)/sizeof(arr[0]));
PopSort(arr,sizeof(arr)/sizeof(arr[0]));
cout<<"冒泡排序: ";
Print(arr,sizeof(arr)/sizeof(arr[0]));
selectSort(arr,sizeof(arr)/sizeof(arr[0]));
cout<<"选择排序: ";
Print(arr,sizeof(arr)/sizeof(arr[0]));
FastSort(arr,0,sizeof(arr)/sizeof(arr[0])-1);
cout<<"快速排序: ";
Print(arr,sizeof(arr)/sizeof(arr[0]));
SelectSort2(arr,sizeof(arr)/sizeof(arr[0]));
cout<<"选择排序2:";
Print(arr,sizeof(arr)/sizeof(arr[0]));
HeapSort(arr,sizeof(arr)/sizeof(arr[0]));
cout<<"堆排序: ";
Print(arr,sizeof(arr)/sizeof(arr[0]));
QuickSort2(arr,0,sizeof(arr)/sizeof(arr[0])-1);
cout<<"快速排序2: ";
Print(arr,sizeof(arr)/sizeof(arr[0]));
MergeSort(arr,tmp,0,sizeof(arr)/sizeof(arr[0])-1);
cout<<"归并排序: ";
Print(arr,sizeof(arr)/sizeof(arr[0]));
QuickSort2(arr,0,sizeof(arr)/sizeof(arr[0])-1);
cout<<"快速排序3:";
Print(arr,sizeof(arr)/sizeof(arr[0]));
system("pause");
return 0;
}
测试用例
int arr[]={9,3,5,1,4,7,8,0};
测试用例
int arr[]={2,3,6,5,4,13,56};
欢迎补充