• 【ARM 嵌入式 C 入门及渐进 10 -- 冒泡排序 选择排序 插入排序 快速排序 归并排序 堆排序 比较介绍】



    在这里插入图片描述

    排序算法小结

    C语言中常用的排序算法包括冒泡排序、选择排序、插入排序、快速排序、归并排序、堆排序。下面我们来一一介绍:

    • 冒泡排序(Bubble Sort):冒泡排序是通过比较相邻元素的大小进行排序。如果当前元素比下一个元素大,就交换它们两个的位置。重复这个过程直到最后,最大的元素就会“”到数组的最后。然后再从头开始重复这个过程,但是最后一个元素不再考虑。这个过程会一直进行,直到没有元素需要交换,也就是整个数组已经排序完成。冒泡排序需要两层for循环,所示它的时间复杂度是O(n^2)
    • 选择排序(Selection Sort):选择排序是每次从未排序的元素中选择最小(或最大)的元素放到未排序元素的开始位置,直到所有元素都已排序。选择排序的时间复杂度也是O(n^2)
    • 插入排序(Insertion Sort):插入排序的思路是将未排序的元素依次插入到已排序元素的适当位置。开始时,第一个元素被认为已排序,然后将第二个元素和它比较,决定第二个元素在已排序元素中的位置,然后再将第三个元素和已排序的元素比较,依次进行。插入排序的时间复杂度也是O(n^2)
    • 快速排序(Quick Sort):快速排序是一种使用分治策略的排序算法。它的基本思想是选择一个基准元素,将数组分为两部分,一部分的元素都比基准元素小,另一部分的元素都比基准元素大。然后对这两部分再分别进行快速排序。快速排序最坏的时间复杂度是O(n^2),但是在平均情况下,快速排序的时间复杂度是O(n log n)
    • 归并排序(Merge Sort):归并排序也是一种使用分治策略的排序算法。它的基本思想是将数组分为两半,分别对它们进行归并排序,然后将两个已排序的子数组合并成一个完整的已排序数组。归并排序的时间复杂度是O(n log n)
    • 堆排序(Heap Sort):堆排序是基于二叉堆的一种排序方法。首先将数组构建成一个最大堆或最小堆,然后依次移除堆顶的元素,并调整堆以保持堆的性质,直到堆为空,此时数组已排序。堆排序的时间复杂度是O(n log n)

    总的来说,这些排序算法各有各的优点和适用场景,例如,冒泡排序、选择排序和插入排序适用于小规模数据或者部分有序数据,而快速排序、归并排序和堆排序通常适用于大规模数据排序。

    排序算法C实现

    冒泡排序算法

    #include 
    
    void bubbleSort(int arr[], int n)
    {
        int i, j;
    
        for (i = 0; i < n-1; i++) {
            for (j = 0; j < n-i-1; j++) {
                if (arr[j] > arr[j+1]) {
                    int temp = arr[j];
                    arr[j] = arr[j+1];
                    arr[j+1] = temp;
                }
            }
        }
    }
    
    void main(void)
    {
    	int arr[] = {2, 5, 6, 9, 3, 8, 1, 4, 7};
    	
    	bubbleSort(arr, sizeof(arr) / sizeof(arr[0]));
    
    	for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
    	
    	printf("%d", arr[i]);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    由于冒泡排序算法过于简单,这里就不详细分析代码逻辑了,需要注意的是两层循环中循环次数的配置。

    选择排序算法

    void selectionSort(int arr[], int n)
    {
        int i, j, minIndex, temp;
    
        for (i = 0; i < n-1; i++) {
            minIndex = i;
            for (j = i+1; j < n; j++) {
            	if (arr[j] < arr[minIndex]) {
                    minIndex = j;
                }
            }
    
            temp = arr[minIndex];
            arr[minIndex] = arr[i];
            arr[i] = temp;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • void selectionsort(int arr[], int n) :这是一个名为 selectionsort 的函数,它接受一个整型数组和一个整数作为参数。整型数组是要被排序的数据,整数代表数组的长度。
    • int i, j, minindex, temp; :声明四个整型变量,i和j用于循环遍历,minindex用于保存当前最小元素的索引,temp用于交换元素。
    • for (i = 0; i < n-1; i++) :外层循环,用于遍历数组。由于选择排序是每次从未排序元素中选择最小(或最大)的元素放到已排序序列的末尾,所以只需要遍历到倒数第二个元素,最后一个元素自然就是最大(或最小)的。
    • minindex = i; :将当前遍历的元素索引赋值给 minindex,假设当前元素就是未排序元素中最小的。
    • for (j = i+1; j < n; j++) :内层循环,用于遍历i之后的所有元素,寻找真正的最小元素。
    • if (arr[j] < arr[minindex]) :如果找到一个元素小于当前最小元素,就更新最小元素。
    • minindex = j; :将新的最小元素的索引赋值给 minindex
    • temp = arr[minindex]; arr[minindex] = arr[i]; arr[i] = temp; :交换当前遍历的元素(arr[i])和最小元素(arr[minindex]),将最小元素放到已排序序列的末尾。

    通过以上的步骤,整个数组经过n-1次遍历后,就会被排序完成。这就是选择排序的基本思想。

    插入排序算法

    void insertionSort(int arr[], int n)
    {
        int i, key, j;
    
        for (i = 1; i < n; i++) {
            key = arr[i];
            j = i - 1;
    
            while (j >= 0 && arr[j] > key) {
                arr[j + 1] = arr[j];
                j = j - 1;
            }
    
            arr[j + 1] = key;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • void insertionsort(int arr[], int n):这是一个名为insertionsort的函数,它接受一个整型数组和一个整数作为参数。整型数组是要被排序的数据,整数用于表示数组的长度。
    • int i, key, j;:声明并初始化三个整型变量,ij用于循环遍历,key用于保存当前要插入的元素。
    • for (i = 1; i < n; i++):外层循环,用于遍历数组。由于插入排序的原理是将未排序的元素依次插入到已排序的数组中,因此从数组的第二个元素开始遍历。
    • key = arr[i];:保存当前要插入的元素。
    • j = i - 1;:j 用于遍历已排序的数组,从最后一个已排序的元素开始。
    • while (j >= 0 && arr[j] > key):内层循环,如果已排序的元素大于要插入的元素,就将已排序的元素向后移动。
    • arr[j + 1] = arr[j];:将大于要插入元素的值向后移动。
    • j = j - 1;:移动到已排序数组的前一个元素。
    • arr[j + 1] = key;:当已排序的元素不大于要插入的元素或已经没有元素可以比较时,就将要插入的元素放到正确的位置。

    通过以上的步骤,整个数组经过n-1次遍历后,就会被排序完成。这就是插入排序的基本思想。

    快速排序算法

    int partition(int arr[], int low, int high)
    {
        int pivot = arr[high];
        int i = (low - 1);
    
        for (int j = low; j <= high- 1; j++) {
            if (arr[j] <= pivot) {
                i++;
                swap(&arr[i], &arr[j]);
            }
        }
    
        swap(&arr[i + 1], &arr[high]);
        return (i + 1);
    }
    void quickSort(int arr[], int low, int high)
    {
        if (low < high) {
            int pi = partition(arr, low, high);
            quickSort(arr, low, pi - 1);
            quickSort(arr, pi + 1, high);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    归并排序算法

    void merge(int arr[], int l, int m, int r)
    {
        int i, j, k;
        int n1 = m - l + 1;
        int n2 = r - m;
        int L[n1], R[n2];
    
        for (i = 0; i < n1; i++) {
            L[i] = arr[l + i];
        }
    
        for (j = 0; j < n2; j++) {
            R[j] = arr[m + 1+ j];
        }
    
        i = 0;
        j = 0;
        k = l;
    
        while (i < n1 && j < n2) {
            if (L[i] <= R[j]) {
                arr[k] = L[i];
                i++;
            } else {
                arr[k] = R[j];
                j++;
            }
    
            k++;
        }
    
        while (i < n1) {
            arr[k] = L[i];
            i++;
            k++;
        }
    
        while (j < n2) {
            arr[k] = R[j];
            j++;
            k++;
        }
    }
    void mergeSort(int arr[], int l, int r)
    {
        if (l < r) {
            int m = l+(r-l)/2;
            mergeSort(arr, l, m);
            mergeSort(arr, m+1, r);
            merge(arr, l, m, r);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52

    堆排序算法

    void heapify(int arr[], int n, int i)
    {
        int largest = i;
        int l = 2*i + 1;
        int r = 2*i + 2;
    
        if (l < n && arr[l] > arr[largest]) {
            largest = l;
        }
    
        if (r < n && arr[r] > arr[largest]) {
            largest = r;
        }
    
        if (largest != i) {
            swap(&arr[i], &arr[largest]);
            heapify(arr, n, largest);
        }
    }
    void heapSort(int arr[], int n)
    {
        for (int i = n / 2 - 1; i >= 0; i--) {
            heapify(arr, n, i);
        }
    
        for (int i=n-1; i>=0; i--) {
            swap(&arr[0], &arr[i]);
            heapify(arr, i, 0);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    排序方法的稳定性

    用某排序方法对一个关键码序列进行递增排序时,对于其中关键码相同的元素,若该方法可保证在排序前后这些元素的相对位置不变,则称该排序方法是稳定的。
    在这里插入图片描述

  • 相关阅读:
    流水线中便捷迭代,鲲鹏DevKit 23.0新能力抢先看
    关闭禁用chrome浏览器的阅读清单/强力书签
    使用虚拟机安装ikuai软路由系统,搭建pppoe拨号服务器
    《Python等级考试(1~6级)历届真题解析》专栏总目录
    玩转doxygen 之RT-THREAD
    关于Coinbase成长历程的感悟 2021-04-15
    VSCode配置 C/C++ 环境
    Springsecurity的授权流程
    zookeeper源码(06)ZooKeeperServer及子类
    C++第二十三弹---深入理解STL中list的使用
  • 原文地址:https://blog.csdn.net/sinat_32960911/article/details/134054630