排序算法
基础排序算法
排序本质:减小逆序对的过程
在基础排序算法中,将待排序序列分为相对有序区与相对无序区。
每次遍历到数组末尾称为一轮。
冒泡排序(无序区-有序区, O ( n 2 ) O(n^2) O(n2),稳定,就地)
在每一轮中,逐次与下一邻项比较,每次比较将最值者置后,因此每一轮都能将无序区的1个最值放到有序区末尾,最后一轮同时将2个元素完成排序,因此最多仅需遍历 n − 1 n-1 n−1次(n:数组元素个数)
extern int a[MAX];
void sort(){
for(int j=0;j<MAX-1;j++)//j:冒泡轮数=有序区元素个数
for(int i=0;i<MAX-1-j;i++)//i:当前工作指针 MAX-1-j:有序区首元素(无需再进入有序区)
if(a[i]>a[i+1]) swap(a[i],a[i+1]);//降序为<
}
简单选择排序(有序区-无序区, O ( n 2 ) O(n^2) O(n2),不稳定,就地)
每轮找到无序区中最值元素,并放到无序区首元素位置,无序区首元素成为有序区末尾
extern int a[MAX];
void sort(){
for(int j=0;j<MAX-1;j++) {//无序区首元素下标
int min=j;//默认无序区首元素为最小值
for(int i=j+1;i<MAX;i++)//遍历一趟无序区获取最小值下标
if(a[i]<a[min]) min=i;
swap(a[j],a[min]);//交换无序区首元素与无序区最小值
}
}
插入排序
直接插入排序(有序区-无序区, O ( n 2 ) O(n^2) O(n2),稳定,就地)
先默认数组首元素为有序区,其之后为无序区。顺序遍历无序区,每轮将无序区首元素,逆序遍历有序区以寻找元素插入点。
extern int a[MAX];
void sort(){
for(int j=1;j<MAX;j++){//j:无序区首元素
int temp=a[j],i;
for(i=j-1;i>=0;i--)//逆序遍历有序区,寻找插入点
if(temp<a[i]) a[i+1]=a[i];//a[i]后移
else break;//找到插入点
a[i+1]=temp;//a[i+1]>temp>a[i]
}
}
二分插入排序( O ( n 2 ) O(n^2) O(n2),稳定,就地)
由于有序区已经是有序的,因此寻找插入点时可采用二分优化。
extern int a[MAX];
void sort(){
for(int i=0;i<MAX;i++){
int temp=a[i],l=0,r=i-1,m;
while(l<=r){
m=l+r>>1;
if(t<a[m]) r=m-1;
else l=m+1;
}
//已找到插入点l
for(int j=i-1;j>=l;j--) a[j+1]=a[j];
a[l]=t;
}
}