07、常用排序算法(C基础)

这里简单总结一下常用的排序算法:

1、冒泡排序:两个数比较大小,较大的数下沉,较小的数冒起来。

  • 比较相邻的两个数据,如果第二个数小,就交换位置。
  • 从后向前两两比较,一直到比较最前两个数据。最终最小数被交换到起始的位置,这样第一个最小数的位置就排好了。
  • 继续重复上述过程,依次将第2.3...n-1个最小数排好位置。
比如对这个数组进行排序
第一次循环换呢4和5进行比较
[4,5],7,3,2,1   不用交换
4,[5,7],3,2,1   不用交换
4,5,[7,3],2,1   7比3大,交换
4,5,3,[7,2],1   7比2大,交换
4,5,3,2,[7,1]   7比1大,交换
4,5,3,2,1,7     进行了一次循环,吧最大的进行了排序
进行数组大小-1次循环就完成了排序  


void bubble(int *arr,int n){
    int temp = 0;
    for (int i = 0; i < n-1; i++)
    {
        for (int j = 0; j < n-i-1; j++)
        {
            if(arr[j] > arr[j+1]){
                temp = arr[j];
                arr[j] = arr[j+1];
                arr[j+1] = temp;
            }
        }
    }
}

/*拆开写或许更容易理解*/
void bubble(int arr[],int n){
    for(int i = 0;i < n - 1;i++){
        if(arr[i] > arr[i+1]){
            arr[i] = arr[i] ^ arr[i+1];
            arr[i+1] = arr[i] ^ arr[i+1];
            arr[i] = arr[i] ^ arr[i+1];
        }
    }
}
void bubble_sort(int arr[],int n){
    for(int i = n;i > 1;i--){
        bubble(arr,i);
    }
}

2、选择排序

将数组中最大的元素位置找出来,和最后一个元素进行交换。

然后再从前面n-1个元素中找出最大的元素,和倒数第二个进行交换,以此类推。(这里在交换元素的时候不能使用异或的交换算法,如果最大值恰好是自己的话,就会出现错误)

int find_max_pos(int arr[],int n){
    int max = arr[0];
    int pos = 0;
    for(int i = 0;i < n;i++){
        if(arr[i] > max){
            max = arr[i];
            pos = i;
        }
    }
    return pos;
}

void select_sort(int arr[],int n){
    int pos;
    for(int i = 0;i < n-1;i++ ){
        pos = find_max_pos(arr,n-i);
        int tmp = arr[pos];
        arr[pos] = arr[n-1-i];
        arr[n-1-i] = tmp;
    }
}

3、插入排序

第一个肯定是已经拍好顺序的,从数组的第二个开始依次向前面进行插入,知道最后。

void insert(int arr[],int n){
    int key = arr[n];
    int i = n;
    while (arr[i-1] > key)
    {
        arr[i] = arr[i-1];
        i--;
        if(i == 0)break;
    }
    arr[i] = key;
}
void insert_sort(int arr[],int n){
    for(int i = 1;i < n;i++){
        insert(arr,i);
    }
}

上面三种的平均时间复杂度都是一样的:下面讲解一一下时间复杂度低的;

4、快速排序

  • 先从数列中取出一个数作为key值;
  • 将比这个数小的数全部放在它的左边,大于或等于它的数全部放在它的右边;
  • 对左右两个小数列重复第二步,直至各区间只有1个数
void quick_sort(int *p_val,int n){
    int base = *p_val;        
    int *p_head = NULL,*p_tail = NULL;
    if(n <= 1) return ;         //如果数组小于等于1就是已经拍好顺序的,直接返回
    p_head = p_val;               //指向第一个存储区
    p_tail = p_val + n - 1;       //执向最后一个存储区
    while(p_head < p_tail){     //两个指针没有相遇,就还需要进行
        //一次先对尾指针进行比较
        while( (p_head < p_tail) && (*p_tail >= base)){
            p_tail--;
        }
        if(*p_tail < base){
            *p_head = *p_tail;
            p_head++;
        }
        while ((p_head < p_tail) && (*p_head <= base))
        {
            p_head++;
        }
        if(*p_head > base){
            *p_tail = *p_head;
            p_tail--;
        }
        
    }
    *p_head = base;        //最后对共同的指针进行复制
    quick_sort(p_val,p_head-p_val);
    quick_sort(p_head+1,n-(p_head - p_val)-1);
}

对于快去排序,C库中有写好的函数,我们可以直接去进行使用,下面介绍一下C语言库函数怎么使用快速排序。这样是不是快多了呢。

/*函数原型,这个函数的功能是对一个数组进行排序。
void qsort (void* base, size_t num, size_t size,int (*compar)(const void*,const void*));
base:是数组的首地址
num:数组的元素个数
size:每个元素所占的字节数
compare:函数指针

返回值	含义
<0	   元素P1排在P2前面
0	   不动
>0	   元素P1排在P2后面*/

//使用方式:
#define ARR_SZIE(arr) (sizeof(arr)/sizeof(arr[0]))
#define ARR_ELE_SZIE(arr) (sizeof(arr[0]))
int compare(const void *p1,const void *p2){
    return (* (int *)p1 - *(int *)p2);  //如果想从大到小进行排序,就倒过来减
}
int main(){
    int arr[10] = {4,8,6,2,8,3,6,8,1,6};
    qsort(arr,ARR_SZIE(arr),ARR_ELE_SZIE(arr),compare);
    for (int i = 0; i < 10; i++)
    {
        printf("%d\t",arr[i]);
    } 
}

//与之相对应的还以有一个查找函数,在这里就一并介绍了
//void* bsearch (const void* key, const void* base,size_t num, size_t size,
// int (*compar)(const void*,const void*));
//在使用这个函数之前的数组必须是已经排好顺序的。
//指向数组中与搜索键匹配的条目的指针。如果有多个匹配元素(即compar将返回0的元素),则可以指向
//它们中的任何一个(不一定是第一个)。 如果找不到键,则返回空指针。
    int key = 2;
    int *p = bsearch(&key,arr,ARR_SZIE(arr),ARR_ELE_SZIE(arr),compare);


 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值