几种常用的排序(持续更)

参考链接:https://blog.csdn.net/xu__jun/article/details/78331111

 

1、简单的桶排序(Bucket Sort)

        arr []={ 5, 3, 5, 2, 8 }               待排数组

bucket[]={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }   空桶

                  0  1  2  3  4  5  6  7  8  9   桶编号(数组 bucket 的角标)

比如 arr[0]==5;bucket [5]++; 这表明,有一个数字5放在了5号桶。由此可推出,当 bucket[5]==2时,就表明有两个数字5,因为桶编号(数组的角标)是有序的,所以当 arr[] 中的元素全部统计好数量并存入木桶中时,就已经排好序了。现在就一起来看看c语言代码实现吧,加深理解^_^

#include <stdio.h>
int main(){
    int arr []={ 5, 3, 5, 2, 8 }; 
    int bucket[10]={0}; //初始化数组,空桶 
               
    for(i=0; i<5; i++){
       int num=arr[i];
       bucket[num]++; //将元素个数存入桶中 ,其角标值就是元素值 
    }
   
    for(int i=0; i<10; i++){
    	while(bucket[i]!=0){ //这个桶有数据!
             printf("%d ",i);
             bucket[i]--; //将桶中的元素个数全部输出 
        } 
    } 
    return 0;
}

图解

 

 

2、冒泡排序(Bubble Sort)

冒泡排序在一组需要排序的数组中,对两两数据顺序与要求顺序相反时,交换数据,使大的数据往后移,每趟排序将最大的数放在最后的位置上,如下: 

 

void bubbleSort(int arr[], int n){
    int i, j, tmp;
    for(i=0; i<n-1; i++){
        for(j=1; j <n; j++){
            if(arr[j]<arr[j-1]){
                tmp = arr[j];
                arr[j] = arr[j - 1];
                arr[j - 1] = tmp;
            }
        }
    }
}

如上是一种最简单的实现方式,需要注意的可能是 i, j 的边界问题,这种方式固定循环次数,肯定可以解决各种情况,不过算法的目的是为了提升效率,根据冒泡排序的过程图可以看出这个算法至少可以从两点进行优化: 
1)对于外层循环,如果当前序列已经有序,即不再进行交换,应该不再进行接下来的循环直接跳出。 
2)对于内层循环后面最大值已经有序的情况下应该不再进行循环。 

优化代码实现:

void bubbleSort_1(int arr[], int n){
    int i, nflag, tmp;
    do{
        nflag = 0;
        for(i=0; i<n-1; i++){
            if(arr[i]>arr[i+1]){
                tmp=arr[i];
                arr[i]=arr[i+1];
                arr[i+1]=tmp;
                nflag=i+1;
            }
        }
        n=nflag;
    }while(nflag);
}

 

3、选择排序(Select Sort)

选择排序是最简单的一种基于O(n2)时间复杂度的排序算法,基本思想是从i=0位置开始到i=n-1每次通过内循环找出i位置到n-1位置的最小(大)值。 

void selectSort(){
    int A[]={7,4,-2,19,13,6};
    for(int i=0; i<n; i++){
       int k=i;
       for(int j=i; j<=n; j++){
           if(A[j]<A[k])
              k=j;
       }
        int tmp=A[i];
        A[i]=A[k];
        A[k]=tmp;
    } 
} 

如实现所示,简单的选择排序复杂度固定为O(n2),每次内循环找出没有排序数列中的最小值,然后跟当前数据进行交换。由于选择排序通过查找最值的方式排序,循环次数几乎是固定的,一种优化方式是每次循环同时查找最大值和最小值可以是循环次数减少为(n/2),只是在循环中添加了记录最大值的操作,原理一样,本文不再对该方法进行实现。

 

4、插入排序\希尔排序(Insert Sort)

希尔排序的基本思想是先取一个小于n的整数d1作为第一个增量,把全部元素分组。所有距离为d1的倍数的记录放在同一个组中。先在各组内进行直接插入排序;然后,取第二个增量d2 < d1重复上述的分组和排序,直至所取的增量 =1( < …< d2 < d1),即所有记录放在同一组中进行直接插入排序为止,希尔排序主要是根据插入排序的以下两种性质对插入排序进行改进: 
1)插入排序在对几乎已经排好序的数据操作时,效率高,即可以达到线性排序的效率。 
2)但插入排序一般来说是低效的,因为插入排序每次只能将数据移动一位 

排序过程如下:

void InsertSort(int arr[], int n){
    int i, j, elem;
    int k=n/2;
    while(k>=1){
        for(i=k; i<n; i ++){
            elem=arr[i];
            for(j=i; j>= k; j-=k){
                if(elem<arr[j-k]){
                    arr[j]=arr[j-k];
                }else{
                    break;
                }
            }
            arr[j]=elem;
        }
        k=k/2;
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值