【排序及算法】冒泡/选择/插入/快速排序、顺序查找/折半查找算法

本文介绍了冒泡排序、选择排序、插入排序及快速排序等基本排序算法,并详细讲解了每种算法的工作原理与实现方式。同时,还探讨了顺序查找与折半查找这两种常用的查找算法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

【算法】
算法是用来解决常见问题的方法
同一个问题可以采用多种方法解决,不同方法使用于不同的环境

【排序算法】
排序指的是把一组数字按照某个顺序排列好
排序算法分很多次重复执行,每次负责把一个数字放在合适的位置上
为了实现以上效果可以"先确定数字,然后查找位置,反之也可以"
通过不断的调整两个数字的相互顺序最终把合适的数字放在合适的位置上

1. 冒泡排序算法(必须掌握)
每次把一个数字放在最前边或最后边的位置上(根据位置找数字)
不断调整相邻两个数字的顺序最终把一个数字放在最前或最后的位置上

<函数演示>
/*代码*/ "冒泡排序算法"
#include <stdio.h>
void bubble_sort(int *p_num, int size) {
    int i = 0, j = 0, tmp = 0;
    for(i = 1; i < size; i++) { //循环次数是 size - 1
        int flag = 1; //标记,如果本身有序就不执行内层循环
        for(j = 0; j < size - i; j++) { //轮数+当前轮循环次数=size
            if(*(p_num + j) > *(p_num + j + 1)) {
                tmp = *(p_num + j); 
                *(p_num + j) = *(p_num + j + 1); 
                *(p_num + j + 1) = tmp;
                flag = 0;
            }   
        }   
        if(flag)
            break;
    }   
}
int main() {
    int arr[] = {23, 15, 7, 17, 27, 5, 33, 25, 19};
    bubble_sort(arr, sizeof(arr)/sizeof(int));
    int i = 0;
    for(i = 0; i < sizeof(arr)/sizeof(int); i++) {
        printf("%d ", arr[i]);
    }   
    printf("\n");
    return 0;
}

2. 选择排序算法
void selectionSort(int[] list) {
    // 需要遍历获得最小值的次数
    // 要注意一点,当要排序 N 个数,已经经过 N-1 次遍历后,已经是有序数列
    for (int i = 0; i < list.length - 1; i++) {
        int temp = 0;
        int index = i; // 用来保存最小值得索引
         // 寻找第i个小的数值
        for (int j = i + 1; j < list.length; j++) {
            if (list[index] > list[j]) {
                index = j;
            }
        }
        // 将找到的第i个小的数值放在第i个位置上
        temp = list[index];
        list[index] = list[i];
        list[i] = temp;
        System.out.format("第 %d 趟:\t", i + 1);
        printAll(list);
    }
}

3. 插入排序算法
采用先确定数字然后找位置的方法,每次把第一个或最后一个排序好的数字作为选定数字,把它插入到已经排序好的数字中合适的位置
每次把选定数字和一个相邻存储区的内容做顺序调整,直到它被放在合适的位置上

<函数演示>
/*代码*/ "插入排序算法"
#include <stdio.h>
int *insert_sort(int *p_num, int size) {
    int num = 0, num1 = 0, tmp = 0;
    for(num = 1; num < size; num++) {
        //每次把下标为num的存储区内容插入到前面
        for(num1 = num; num1 >= 1; num1--) {
            //把下标为num1和num1-1的两个存储区内容做顺序调整
            if(*(p_num + num1 - 1) > *(p_num + num1)) {
                tmp = *(p_num + num1 - 1); 
                *(p_num + num1 - 1) = *(p_num + num1);
                *(p_num + num1) = tmp;
            }   
            else
                break; //把前面比它小的停止执行,不需要对比交换
        }
    }   
    return p_num;
}
int main() {
    int arr[] = {23, 15, 7, 17, 27, 5, 33, 25, 19};
    int num = 0;
    insert_sort(arr, 9); 
    for(num = 0; num < 9; num++) {
        printf("%d ", arr[num]); //5 7 15 17 19 23 25 27 33
    }   
    printf("\n");
    return 0;
}

4. 快速排序算法(最快最好,必须掌握)
采用"先确定数字然后找位置"的方法
从没有处理过的所有数字两端选择一个作为基准数字
把基准数字和所有其他数字进行顺序调整,比基准数字大的放一边,比基准数字小的放另一边
每次对没有处理过的数字中"两端的数字进行顺序调整"(这两端的数字一定包含基准数字)
在调整完两个数字的顺序后把不是基准数字的数字排除在外

<模拟快速排序过程>
[40]50 20 30 60 80 70[90] - 40(基准数字)
[40]50 20 30 60 80[70]90
[40]50 20 30 60[80]70 90
[40]50 20 30[60]80 70 90
[40]50 20[30]60 80 70 90
 30[50]20[40]60 80 70 90
 30[40|20]50 60 80 70 90
 30 20[40]50 60 80 70 90 //40就在排序好的正确位置上
[30|20]40 50 60 80 70 90 - 30(基准数字)
[20|30]40 50 60 80 70 90
 20 30 40 50 60[80|70]90 - 20/50/60/不动 - 80(基准数字)
 20 30 40 50 60[70|80]90 //排好序

<函数演示>
/*代码*/ "快速排序算法"
#include <stdio.h>
int *quick_sort(int *p_num, int size) {
    int base = *p_num; //数组第一个存储区的数字作为基准数字
    int *p_start = p_num, *p_end = p_num + size - 1, tmp = 0;
    if(size <= 1) { //处理不可分解的情况,没有元素和只有1个元素
        return p_num;
    }   
    while(p_start < p_end) { //指针移动的位置还没有向中间碰到一起
        if(*p_start > *p_end) { //对没处理过的数字中前>后的进行调换
            tmp = *p_start;
            *p_start  = *p_end;
            *p_end = tmp;
        }   
        if(*p_start == base) { //把两端数字中非基准数字排除在外
            p_end--; //基准数字在前
        }   
        else {
            p_start++; //基准数字在后
        }   
    }   
    quick_sort(p_num, p_start - p_num); //递归左半边快速排序
    quick_sort(p_start + 1, size - (p_start - p_num + 1)); //递归右
    return p_num;
}
int main() {
    int arr[] = {23, 15, 7, 17, 27, 5, 33, 25, 19};
    int num = 0;
    quick_sort(arr, 9); 
    for(num = 0; num < 9; num++) {
        printf("%d ", arr[num]); //5 7 15 17 19 23 25 27 33
    }   
    printf("\n");
    return 0;
}

【查找算法】
查找算法可以从一组数字里找到某一个数字所在的位置

1. 顺序查找
依次把每个数字和要查找的数字做对比,直到找到为止
如果"数字的排列没有规律"就只能采用这种方法查找

2. 折半查找算法
如果所有"数字已经按照某种顺序排列好"就可以用中间位置的数字和目标数字做对比,这样可以一次排除掉一半的数字
重复这个过程就可以很快找到目标数字的位置
<函数演示>
/*代码*/
#include <stdio.h>
//折半查找法,找到的是目标数字的位置
int *half_search(int *p_num, int size, int num) {
    int *p_start = p_num, *p_end = p_num + size - 1, *p_mid = NULL;
    while(p_start <= p_end) { //如果没找到循环就退出
        p_mid = p_start + (p_end - p_start + 1) / 2; //中间位置
        if(*p_mid == num) { //中间位置存储区内容就是要查找的数字
            return p_mid;
        }
        else if(*p_mid > num) { //中间位置存储区内容比查找的数字大
            p_end = p_mid - 1;
        }
        else { //中间位置存储区内容比要查找的数字小
            p_start = p_mid + 1;
        }
    }
    return NULL;
}
//递归函数改写
int *half_search_rec(int *p_start, int *p_end, int num) {
    int *p_mid = NULL;
    if(p_start > p_end) {
        return NULL;
    }
    p_mid = p_start + (p_end - p_start + 1)/2;
    if(*p_mid == num) {
        return p_mid;
    }
    else if(*p_mid > num) {
        return half_search_rec(p_start, p_mid - 1, num);
    }
    else {
        return half_search_rec(p_mid + 1, p_end, num);
    }
}
int main() {
    int arr[] = {3, 8, 11, 13, 16, 19, 21, 25, 32, 36, 44};
    int *p_num = half_search(arr, sizeof(arr)/sizeof(int), 11);
    int *p_num1 = half_search_rec(arr, arr+sizeof(arr)/sizeof(int), 32);
    if(p_num) {
        printf("找到的结果是 %d \n", *p_num);
    }
    else
        printf("没有数字%d\n", *p_num);
    if(p_num1) {
        printf("找到的结果是 %d \n", *p_num1);
    }
    else
        printf("没有数字%d\n", *p_num1);
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

姜源Jerry

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

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

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

打赏作者

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

抵扣说明:

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

余额充值