嵌入式学习22

【算法入门】冒泡、选择、插入、希尔、快速排序 + 查找 C语言总结

今日学习:冒泡排序、选择排序、插入排序、希尔排序、快速排序,顺序查找、二分查找。

🔍文章大纲

  • 1 冒泡排序
  • 2 选择排序
  • 3 直接插入排序
  • 4 希尔排序
  • 5 快速排序
  • 6 查找算法(顺序查找、二分查找)
  • 7 排序算法对比表
  • 8 学习总结

1. 冒泡排序

原理:相邻元素两两比较,大的往后交换,每轮把最大值"冒泡"到数组尾部;增加交换标记做优化,提前结束有序数组。

复杂度 :最好O(n),最坏/平均O(n²);空间O(1);稳定排序

复制代码
#include <stdio.h>

// 冒泡排序-优化版
void bubbleSort(int arr[], int n)
{
    for(int i = 0; i < n - 1; i++)
    {
        int swapFlag = 0;   //标记本轮是否发生交换
        for(int j = 0; j < n - 1 - i; j++)
        {
            if(arr[j] > arr[j+1])
            {
                int temp = arr[j];
                arr[j] = arr[j+1];
                arr[j+1] = temp;
                swapFlag = 1;
            }
        }
        if(swapFlag == 0) break; //没有交换,数组已有序,直接退出
    }
}

2. 选择排序

原理:划分有序区、无序区;每一轮在无序区找到最小值下标,和无序区第一个元素交换。

复杂度 :全部O(n²);空间O(1);不稳定排序

复制代码
void selectSort(int arr[], int n)
{
    for(int i = 0; i < n - 1; i++)
    {
        int minIdx = i;
        //找无序区间最小值下标
        for(int j = i + 1; j < n; j++)
        {
            if(arr[j] < arr[minIdx])
            {
                minIdx = j;
            }
        }
        //交换
        int temp = arr[i];
        arr[i] = arr[minIdx];
        arr[minIdx] = temp;
    }
}

3. 直接插入排序

原理:把数组分为有序区、无序区;依次取出无序区元素,向前插入到有序区合适位置,类似整理扑克牌。

复杂度 :最好O(n),最坏/平均O(n²);空间O(1);稳定排序

复制代码
void insertSort(int arr[], int n)
{
    for(int i = 1; i < n; i++)
    {
        int temp = arr[i];   //待插入元素
        int j;
        //有序区元素向后挪
        for(j = i - 1; j >= 0 && arr[j] > temp; j--)
        {
            arr[j+1] = arr[j];
        }
        arr[j+1] = temp;
    }
}

4. 希尔排序(插入排序优化)

原理:分组插入排序。设置增量gap,按gap分组组内插入排序;不断缩小gap,gap=1就是普通插入排序。

复杂度 :平均O(nlogn),最坏O(n²);空间O(1);不稳定排序

复制代码
void shellSort(int arr[], int n)
{
    int gap = n / 2;
    while(gap > 0)
    {
        //分组插入排序
        for(int i = gap; i < n; i++)
        {
            int temp = arr[i];
            int j;
            for(j = i - gap; j >= 0 && arr[j] > temp; j -= gap)
            {
                arr[j + gap] = arr[j];
            }
            arr[j + gap] = temp;
        }
        gap = gap / 2;
    }
}

5. 快速排序(分治思想)

原理:选基准pivot,将数组划分:小于基准放左边,大于基准放右边;递归处理左右子区间。

复杂度 :平均O(nlogn),最坏O(n²);空间O(logn)递归栈;不稳定排序

复制代码
//分区函数
int partition(int arr[], int left, int right)
{
    int pivot = arr[left];
    while(left < right)
    {
        while(left < right && arr[right] >= pivot) right--;
        arr[left] = arr[right];
        while(left < right && arr[left] <= pivot) left++;
        arr[right] = arr[left];
    }
    arr[left] = pivot;
    return left;
}

void quickSort(int arr[], int left, int right)
{
    if(left >= right) return;
    int mid = partition(arr, left, right);
    quickSort(arr, left, mid - 1);
    quickSort(arr, mid + 1, right);
}

6. 查找算法

6.1 顺序查找(线性查找)

数组不需要有序,逐个遍历对比

复制代码
//找到返回下标,找不到返回-1
int seqSearch(int arr[], int n, int key)
{
    for(int i = 0; i < n; i++)
    {
        if(arr[i] == key)
            return i;
    }
    return -1;
}

6.2 二分查找(折半查找)

⚠️数组必须有序,每次折半缩小查找范围;时间复杂度O(logn)

复制代码
//二分查找,有序数组,找到返回下标,找不到返回-1
int binarySearch(int arr[], int n, int key)
{
    int left = 0;
    int right = n - 1;
    while(left <= right)
    {
        int mid = left + (right - left)/2; //防止溢出,等价于(left+right)/2
        if(arr[mid] == key)
        {
            return mid;
        }
        else if(arr[mid] > key)
        {
            right = mid - 1;
        }
        else
        {
            left = mid + 1;
        }
    }
    return -1;
}

7. 排序算法对比表

排序算法 平均时间 最坏时间 空间 稳定性 适用场景
冒泡排序 O(n²) O(n²) O(1) 稳定 少量数据、基本有序
选择排序 O(n²) O(n²) O(1) 不稳定 少量数据
直接插入排序 O(n²) O(n²) O(1) 稳定 数据量小,大部分有序
希尔排序 O(nlogn) O(n²) O(1) 不稳定 中等规模数据
快速排序 O(nlogn) O(n²) O(logn) 不稳定 大数据,最常用

8. 学习总结

今天学习了5种经典排序与两种基础查找算法:

  1. 冒泡、选择、插入属于简单排序,时间复杂度O(n²),适合小规模数据,用来理解排序思想。
  2. 希尔排序是插入排序的优化,通过分组降低移动次数。
  3. 快速排序基于分治,实际工程使用最多,但要注意最坏情况。
  4. 查找:顺序查找不要求有序;二分查找效率很高,但前提必须数组有序。
  5. 稳定性概念:相等元素排序后相对位置不变就是稳定排序。

完整测试main函数(直接复制运行)

复制代码
//测试main
int main()
{
    int arr[] = {8,3,6,2,9,1,5};
    int n = sizeof(arr)/sizeof(arr[0]);

    //bubbleSort(arr,n);
    //selectSort(arr,n);
    //insertSort(arr,n);
    //shellSort(arr,n);
    //quickSort(arr,0,n-1);

    for(int i=0;i<n;i++){
        printf("%d ",arr[i]);
    }

    int pos = binarySearch(arr,n,6);
    printf("\n查找6的下标:%d\n",pos);
    return 0;
}
相关推荐
我是苏苏1 小时前
C#基础:不写for循环的五种方式
数据结构·算法·c#
三8442 小时前
webshell缓存绕过/哈希碰撞
算法·哈希算法
致Great9 小时前
Pi 的上下文压缩,到底是怎么工作的?
算法
Linux-lucky9 小时前
21-Linux学习之旅之HTTPS和安全加固
linux·运维·学习·ubuntu·https
wuyk55510 小时前
4.树:一对多的层次数据结构
开发语言·数据结构·stm32·单片机
watersink10 小时前
机器学习聚类算法
算法·机器学习·聚类
luj_176811 小时前
桥牌思维启示:系统设计的模块化架构
c语言·开发语言·c++·经验分享·算法
学运维的Kysan11 小时前
暑假运维学习打卡第二十六天8.17
学习