【C语言】排序算法 + 查找算法

前言

本篇文章共讲述五个排序算法与两个查找算法,其中包括了算法思想与实现代码等等…
请大家耐心观看,感谢!!!

排序算法

排序是计算机程序设计中一个非常重要的操作,它将一个数据元素的任意序列重新排列成一个按关键字有序的序列。在有序的序列中查找元素的效率很高。

这就谈到效率问题,那么时间复杂度正是反应这一问题最直观的结果,如下图:

冒泡排序

首先我们需要定义外层循环,目的是为了控制循环比较的次数,也就是说一共需要排序几次,然后再定义内部循环,而它的目的则是为了控制比较元素的个数,即比较次数。
思想:将相邻两个元素相互比较,并按照关键字排成有序序列。

具体实现代码如下:

void bubbleSort(int arr[], int length){

    //这里 i<length-1 是为了能够减少循环次数,因为提取1个数据与其余剩下9个数据做对比,如果还比较10次话 会浪费时间,无形中增加了时间复杂度。
    for(int i=0; i<length-1; i++){

        //这里 j<length-i-1 用来控制比较值的个数
        for(int j=0; j<length-i-1; j++){

            if(arr[j] > arr[j+1]){
                
                int temp = arr[j];
                arr[j] = arr[j+1];
                arr[j+1] = temp;

            }

        }
    
    }

}

选择排序

待排序元素 一步一步与 其之后的元素进行比较,若满足判断则进行交换,若一直为满足判断则一直走到最后。
思想:找 最大 或 最小 的元素,往前放,分成 "已排序" 和 "待排序" 序列。

具体实现代码如下:

void selectSort(int arr[], int length){
    
    int i, j ,temp, min;
    
    for(i=0 ; i< length ; i++){
        
        min = i;                //min 标记 未排序第一个元素的位置
        
        for(j=i+1; j< length ; j++){        //找 比 min位置 还小的元素
            
            if(arr[j] < arr[min]){
                min=j;
            }
            
        }
       
        if(min != i){
            temp = arr[min];
            arr[min] = arr[i];
            arr[i] = temp;
        }
        
    }
    
}

插入排序

又名"直接插入排序",直接插入排序,是在有序基础上,速度最快且最稳定的排序方法。
思想:由后向前 查找 确定的位置,并插入元素。

具体实现代码如下:

void insertSort(int arr, int length){
    
    int i, j, temp;
    
    for( i=1; i < length ; i++ ){    // 从1开始,0位置当作有序序列
        
        temp = arr[i];        // temp记录未排序的第一个元素
        
        for(j=i-1; j>=0 && arr[j]>temp ;j--){
            
            arr[j+1] = arr[j];        // 元素后移,为 待插入元素 腾空位置
            
        

        arr[j+1] = temp;        // 插入 比较的后一位

    }
    
}

希尔排序

希尔排序是由插入排序升级而来,又称 "缩小增量排序"。把直接插入方法分成插入步长由大到小不同的若干趟来进行,一开始步长较大,相当于把序列分成几个子表。对每个子表来说,因为其结点少,直接插入排序的效率会很高。以后各趟逐步减少步长,子表的结点也越来越多,但是子表中的结点已经进行过前一趟的大步长的直接插入排序,有相当多的结点已基本有序。这使得后一趟的插入排序能充分利用前一趟的排序结果。当步长降到1时,只要对基本有序的线性表进行一趟直接插入排序即可。
思想:按照 步长 进行分组,然后每一组的 第 几个 元素 进行排序。

按照上述方法排序后结果为:

具体实现代码如下:

// dk我们这里用作步长
void shellSort(int arr[],int length,int dk){

    int d[3] = {5,2,1};        //定义步长

    for(i=0;i<3;i++){    //这里为步长的循环

        dk=t[i];    //使dk接收步长值,即第i+1个元素为第二模块

        for(j=i-dk;j<length;j++){    //这里i-dk是第一模块的起始位置

            //判断 每个模块的 第几个元素大小
            if(arr[j]<arr[j-dk]){    //后面模块 小于 前面模块

                temp=arr[j];

                for(k=j-dk;k>=0 && arr[k]>temp;k-=dk){
                    arr[k+dk]=arr[k];        //将前面的值 给到 后面
                }

                arr[k+dk] = temp;

            }

        }

    }

}

快速排序

思想:定义基准值,头部从前向后找,比基准值大的元素,尾部从后向前找,找比基准值小的元素。
通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序。

具体实现代码如下:

int getPivot(int arr[], int low, int high){
    
    //定义基准值
    int pivot = arr[low];
    
    while( low < high ){        //保持尾部大于头部
        
        // 尾部 从后向前找,比基准值小的元素
        while( low < high && arr[high] >= pivot ){
            high--;
        }
        
        // 找到了 比基准值小的元素,将 元素 给到 头部 位置
        arr[low] = arr[high];
        
        // 头部 从前向后找,找比 基准值 大 的元素
        while( low < high && arr[low] <= pivot ){
            low++;
        }
        
        arr[high] = arr[low];
        
    }
    
    // 找到了 比基准值大的元素,将 元素 给到 尾部 位置
    arr[low] = pivot;
        
    //返回基准值位置
    return low;
    
}

void quickSort(int arr[], int low, int high){
    if(low < high){
        //基准值位置的变量
        int pivot = getPivot(arr, low, high);
        
        //递归 对 基准值位置 左边 进行快速排序
        quickSort(arr, low, pivot-1);
        
        //递归 对 基准值位置 右边 进行快速排序
        quickSort(arr, pivot+1, high);
    }
}

//这里为了能够让大家更清晰的了解所以这里写了主函数
int main(){
    int arr[]={4,2,7,5,9};
    quickSort( arr, 0, sizeof(arr)/sizeof(int)-1 );    //这里因为需要传参值是尾部下标所以减一
}


查找算法

时间复杂度:

算法名称

时间复杂度

前提条件

顺序查找

O(n)

//

二分查找

O(logn)

有序数组

顺序查找

思想:通过遍历数组一步步进行比较。
void find(int arr[], int length){

    int value;
    printf("请输入待查找数据");
    scanf("%d",&value);

    for(int i=0; i<length ;i++){

        if(arr[i] == value){
            printf("%d存在数组中,其下标为:%d",value, i);
        }
    
    }

}

二分查找

二分查找 又名 "折半查找",通过取中间值对其中一半进行查找,该查找还可分为递归与非递归两种写法。
思想:查找过程从数组的中间元素开始,如果中间元素正好是要查找的元素,则搜素过程结束;如果某一特定元素大于或者小于中间元素,则在数组大于或小于中间元素的那一半中查找,而且跟开始一样从中间元素开始比较。如果在某一步骤数组为空,则代表找不到。

具体实现代码如下:

//非递归编写方法
int binarySearch(int arr[], int low, int high, int key){        //low 左值, high 右值, key 待查找数据
    
    int mid;    //定义中间值下标
    
    while( low <= high ){
        
        mid = (low+high)/2;     //计算中间值下标
        
        if( key == arr[mid] ){
            return mid;               //返回下标
        } else if( key > arr[mid] ){
            low = mid + 1;            //key 大于中间值,头移动至中间值后一位
        } else {
            high = low - 1;           //key 小于中间值,尾移动至中间值前一位
        }
        
    }
    //没有找到待查找数据
    return -1;
    
}
//递归编写方法,思想同上
int binarySearch(int arr[], int low, int high, int key){

    int mid;

    if( low <= high ){
        mid = (low+high)/2;

        if( key == arr[mid] ){
            return mid;        //递归出口
        } else if( key >= arr[mid] ){
            return binarySearch(arr, mid+1, high);    //这里重新调用了该函数,将头部参数改变为中间值的后一位
        }else {
            return binarySearch(arr, low, mid-1);     //这里也是重新调用了该函数,将尾部参数改变为中间值的前一位
        }

    }

    //未找到该数据
    return -1;

}

本篇文章草草结束啦,希望大家喜欢~~

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Discord_lim

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值