#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#define swap(a,b){\
__typeof(a) __temp =a;\
a=b;b=__temp;\
}
#define TEST(arr, n, func,args...){\
int *num=(int *)malloc(sizeof(int)*n);\
memcpy(num,arr,sizeof(int) *n);\
output(num,n);\
printf("%s= ",#func);\
func(args);\ //因为不同的函数的参数不同所以使用args
output(num,n);\
free(num);\
}
void select_sort(int *num ,int n){
for(int i=0;i<n-1;i++){
int ind =i;
for(int j=i+1;j<n;j++){
if(num[j]<num[ind]) ind=j;
}
swap(num[i],num[ind]);
}
return;
}
void quick_sort(int *num,int l,int r){
if(l>r) return ;
int x=l,y=r,z=num[x];
while(x<y){ //循环到xy 重合退出循环 此位置为基准值
while(x<y && num[y]>z) y--;
if(x<y) num[x++] =num[y];
while(x<y && num[x]<z) x++;
if(x<y) num[y--] =num[x];
}
num[x]=z;
quick_sort(num,l,x-1);
quick_sort(num,x+1,r);
}
void randint(int *num,int n){
while (n--) num[n]=rand()%100;
return;
}
void output(int *num,int n){
printf("[");
for(int i=0; i<n;i++){
printf("%d ",num[i]);
}
printf("]\n");
}
int main()
{
srand(time(0));
#define max_n 20
int arr[max_n];
randint(arr,max_n);
TEST(arr,max_n,select_sort,num,max_n);
TEST(arr,max_n,quick_sort,num,0,max_n-1);
return 0;
}
不稳定排序
选择(内部) 前:已排序区;后:待排序区
- 每轮从待排序区中选择一个最小的元素与待排序区的第一个元素交换
- 可能会有自身与自身交换的情况,所以交换函数不能用异或了
- 不稳定:例如22’1,在第一次交换后,2就跑到了2’的后面,即12’2
- 时间复杂度(最优、最坏、平均都是):O(N^2) 一般情况下优于冒泡,两者比较次数差不多,但冒泡的交换太频繁
快排(内部)
【基准值、partition】
- 拿出第1个元素作为基准值
- 【尾指针】先从后往前找小于基准值的元素,放到第1个元素位置(已为空),【头指针】再从前往后找大于基准值的值,放到刚刚空出的位置,循环
- 最后头尾指针重合,指向一个空位置,放入基准值 再对基准值左右两部分分别进行以上操作
时间复杂度:O(NlogN)
逆序数列选第一个元素为基准值时,退化为选择排序,O(N^2)
【优化】
基准值随机选
减少递归的使用,用循环做
左右都找到一个要交换的值后,再交换
实现结果
快速排序的优化
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#define swap(a,b){\
__typeof(a) __temp =a;\
a=b;b=__temp;\
}
#define TEST(arr, n, func,args...){\
int *num=(int *)malloc(sizeof(int)*n);\
memcpy(num,arr,sizeof(int) *n);\
output(num,n);\
printf("%s= ",#func);\
func(args);\
output(num,n);\
free(num);\
}
void quick_sort(int *num,int l,int r){
while(l<r){
int x=l,y=r,z=num[(x+y)>>1];
do{
while(x<=y && num[x] <z) x++;
while(x<=y && num[y]>z) y--;
if(x<=y){
swap(num[x],num[y]);
x++,y--;
}
}while(x<=y);
quick_sort(num,x,r);
r=y;
}
return;
}
void randint(int *num,int n){
while (n--) num[n]=rand()%100;
return;
}
void output(int *num,int n){
printf("[");
for(int i=0; i<n;i++){
printf("%d ",num[i]);
}
printf("]\n");
}
int main()
{
srand(time(0));
#define max_n 20
int arr[max_n];
randint(arr,max_n);
TEST(arr,max_n,quick_sort,num,0,max_n-1);
return 0;
}
画横线的只是搞右边 真正的情况是需要回到刚开始进行左边的而不是陷入这个画横线的递归
结果