#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
/*
直接插入排序:
枚举一个元素分别与前面的元素比较,直到遇到比自己更小的
时间复杂度O(n2),空间复杂度O(1),稳定
*/
void insertSort(int *a,int len){
for(int i=1;i<len;i++){
if(a[i]<a[i-1]){
int tmp=a[i];
int j=i-1;
while(j>=0&&a[j]>tmp){
a[j+1]=a[j];
j--;
}//j为前面第一个小于tmp的下标
a[j+1]=tmp;
}
}
}
/*
冒泡排序:
相邻两元素比较,按照要求交换顺序,共进行n-1次(原理,每次将最大值移到最后)
时间复杂度O(n2),空间复杂度O(1),稳定
*/
void bubbleSort(int *a,int n){
for(int i=0;i<n;i++)
for(int j=0;j<n-i;j++){
if(a[j]>a[j+1]){
int tmp=a[j];
a[j]=a[j+1];
a[j+1]=tmp;
}
}
}
/*
简单选择排序:
每次遍历未排序段选出最小值,插入到排序段
时间复杂度O(n2),空间复杂度O(1),不稳定
*/
void selectSort(int *a,int n){
for(int i=0;i<n;i++){
int k=i;
for(int j=i;j<n;j++)
if(a[j]<a[k])
k=j;
if(k!=i){//k为i---n-1中最小值的下标
int tmp=a[i];
a[i]=a[k];
a[k]=tmp;
}
}
}
/*
希尔排序:
将数组不断分块,将块与块的对应元素进行比较后排序,重复进行直到每块只含有一个数
有间隔的直接插入排序
时间复杂度O(n1.3),空间复杂度O(1),不稳定
*/
void shellSort(int *a,int n){
int dk=n;
while(dk/2){
dk/=2;
for(int i=dk;i<n;i++){//因为要与前dk比较,dk为起点,等价于间隔不为1的直接插入排序
if(a[i-dk]>a[i]){
int tmp=a[i];
int j=i-dk;
while(j>=0&&a[j]>tmp){
a[j+dk]=a[j];
j-=dk;
}
a[j+dk]=tmp;
}
}
}
}
/*
快速排序:
时间复杂度O(nlogn),空间复杂度O(logn),不稳定
*/
void quickSort(int *a,int st,int ed){
if(st>=ed)
return;
int x=st,y=ed;
int p=a[st];
while(x<y){
while(x<y&&a[y]>=p)
y--;
while(x<y&&a[x]<=p)
x++;
int tmp=a[x];
a[x]=a[y],a[y]=tmp;
}
a[st]=a[x];
a[x]=p;
quickSort(a,st,x-1);
quickSort(a,x+1,ed);
}
/*
堆排序:
将数组构建成大顶堆,堆顶元素为最大值,每次将堆顶元素与最后一个结点交换,然后再对前面的元素构建大顶堆,重复操作n-1次
6 9 4 7 8 3 2 5 1 10
1 8 4 7 6 3 2 5 9
1 7 4 5 6 3 2 8
2 6 4 5 1 3 7
3 5 4 2 1 6
1 3 4 2 5
2 3 1 4
1 2 3
1 2
1 2 3 4 5 6 7 8 9 10
*/
void heapfy(int *a,int root,int n){//对root结点构造大顶堆
int x=root*2+1,y=root*2+2;//左右子节点
int mx=root;//三个节点中最大的
if(x<n&&a[x]>a[mx])
mx=x;
if(y<n&&a[y]>a[mx])
mx=y;
if(mx!=root){//改变mx为下表的结点,并更新mx结点涉及的子树
int tmp=a[root];
a[root]=a[mx];
a[mx]=tmp;
heapfy(a,mx,n);
}
}
void buildHeap(int *a,int n){
for(int i=n/2-1;i>=0;i--)//含有子树的节点
heapfy(a,i,n);
}
void heapSort(int *a,int n){
if(n==1)
return;
buildHeap(a,n);
int tmp=a[0];
a[0]=a[n-1];
a[n-1]=tmp;
for(int i=0;i<n;i++){
printf("%d ",a[i]);
}
printf("\n");
heapSort(a,n-1);
}
/*
归并排序:
将序列不断二分直到个数为1,对比排序后再合并
*/
void merge(int *a,int st,int mid,int ed){//对st.mid.ed两段进行排序合并
int i=st,j=mid+1,k=0;
int *tmp;
tmp=(int *)malloc((ed-st+1)*sizeof(int));
while( i<=mid && j<=ed){
if(a[i]<a[j])
tmp[k++]=a[i++];
else
tmp[k++]=a[j++];
}
//多余的一段直接赋值给tmp
while(i<=mid)
tmp[k++]=a[i++];
while(j<=ed)
tmp[k++]=a[j++];
for(i=0;i<k;i++)
a[st+i]=tmp[i];
free(tmp);
}
void mergeSort(int *a,int st,int ed){
if(st>=ed){
return;
}else{
int mid=st+ed>>1;
mergeSort(a,st,mid);//前半段
mergeSort(a,mid+1,ed);//后半段
merge(a,st,mid,ed);//前后半段自身排序完成后合并排序
}
}
int main(){
int a[]={6,1,2,7,9,3,4,5,10,8};
int len=10;
//shellSort(a,len);
//quickSort(a,0,len-1);
//heapSort(a,len);
mergeSort(a,0,len-1);//0,9
for(int i=0;i<len;i++){
printf("%d ",a[i]);
}
printf("\n");
return 0;
}