选择排序 快速排序

#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;
}

不稳定排序

选择(内部) 前:已排序区;后:待排序区

  1. 每轮从待排序区中选择一个最小的元素与待排序区的第一个元素交换
  2. 可能会有自身与自身交换的情况,所以交换函数不能用异或了
  3. 不稳定:例如22’1,在第一次交换后,2就跑到了2’的后面,即12’2
  4. 时间复杂度(最优、最坏、平均都是):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;
}

在这里插入图片描述

画横线的只是搞右边 真正的情况是需要回到刚开始进行左边的而不是陷入这个画横线的递归

结果
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值