c入门第十二篇——成绩差的往前坐(简单排序)

书接前文,师弟说道他喜欢的一个女生,让他实现一个算法,对班上的学生成绩进行排序。排序,这不是一件很简单的事情么?为什么这么说呢?因为她并没有对时间复杂度有要求。如果对时间复杂度,有要求,那就要用更高深一点的算法了。现在我们可以用最简单的2种排序算法。

选择排序

选择排序是一种简单直观的排序算法。它的工作原理是不断地选择剩余元素之中的最小或最大者,将其放置在已排序序列的末尾。

选择排序的算法步骤如下:(以从小到大排序说明,从大到小原理一样)

  1. 从数组未排序的部分中找到最小(或最大)元素。
  2. 将其存放到数组的起始位置作为已排序序列的末尾。
  3. 从剩余未排序元素中继续寻找最小(或最大)元素,然后放到已排序序列的末尾。
  4. 重复第3步,直到所有元素均排序完毕。
    选择排序的时间复杂度为 O(n^2),其中 n 是数组长度。这是因为每次选出最小元素都要遍历比较所有未排序的元素。
    示例说明:
    原始数据: 5 3 2 4 1
    一轮选择: 从0号位置开始找到最小的,1 3 2 4 5
    二轮选择: 从1号位置开始找到最小的,1 2 3 4 5
    三轮选择: 从2号位置开始找到最小的,1 2 3 4 5
    四轮选择: 从3号位置开始找到最小的,1 2 3 4 5 //结束排序
void swap(int *a, int *b)
{
    int tmp = *a;
    *a = *b;
    *b = tmp;
}

void select_sort(int arr[], int n)
{
    int i, j, min_idx;

    for (i=0; i<n-1; i++) { // 移动边界未排序子数组
        min_idx = i;  // 未排序子数组中最小元素的索引
        for (j=i+1; j<n; j++) {
            if (arr[j] < arr[min_idx]) {
                min_idx = j;
            }
        }

        // 将找到的最小元素与第一个未排序元素进行交换
        swap(&arr[min_idx], &arr[i]);

        // 打印排序的详细过程
        int k;
        for (k=0; k<n; k++) {
            printf("%d ", arr[k]);
        }
        printf("\n");
    }
}

冒泡排序

冒泡排序是一种简单的排序算法,它重复地遍历要排序的列表,比较相邻的两个项,如果相邻不是预期的顺序时交换它们。这个算法的名称由来是因为较小的元素会像"气泡"一样逐渐"浮"到列表的顶端。

下面是冒泡排序算法的步骤:(以从小到大排序说明,从大到小原理一样)

  1. 比较相邻的元素。如果第一个比第二个大,就交换它们两个。
  2. 对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对。做完这步后,最后的元素会是最大的数。
  3. 针对所有的元素重复以上的步骤,除了最后一个。
  4. 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
    冒泡排序的时间复杂度是 O(n^2),其中 n 是列表中元素的数量。

示例说明:
原始数据: 5 3 2 4 1
一轮冒泡: 5>3,冒泡,3 5 2 4 1; 5>2,冒泡,3 2 5 4 1;5>4,冒泡,3 2 4 5 1;5>1,冒泡,3 2 4 1 5 //一轮找出最大值
二轮冒泡: 2 3 1 4 5 //二轮找出第二大值
三轮冒泡: 2 1 3 4 5 //三轮找出第三大值
四轮冒泡: 1 2 3 4 5 //四轮完成排序

void swap(int *a, int *b)
{
    int tmp = *a;
    *a = *b;
    *b = tmp;
}

void bubble_sort(int arr[], int n)
{
    int i, j;

    for (i = 0; i < n-1; i++) {
        for (j = 0; j < n-i-1; j++) { // 最后 i 个已经排序好了, 遍历未排序的部分
            if (arr[j] > arr[j+1]) {
                // 如果当前元素大于后面的元素,交换它们
                swap(&arr[j], &arr[j+1]);
            }
        }

        // 打印排序的详细过程
        int k;
        for (k=0; k<n; k++) {
            printf("%d ", arr[k]);
        }
        printf("\n");
    }
}

师弟有如获得绝世秘籍一般,回去吭哧吭哧,写了起来,沙漠中前行,远处的白杨树,显得那么的小,却也逐渐清晰的样子。

这里介绍的只是入门级排序,如果只是对于少量数据排序,且又对时间消耗没有严格的要求,是可以使用的。如果对时间有严格要求,则需要更优的排序,如快速排序、堆排序、归并排序等。

你可能感兴趣的:(c语言入门,c语言,算法,排序算法)