选择排序 和 冒泡排序

 参考:《数据结构教程》李春葆

 

 

一,选择排序

0,有序区

  有序区:数组中已经排序好的连续区间

1,算法思想(升序)

  将有序区设在数组的开头 / 末尾,然后从无序区中选择一个最小值 / 最大值,交换到无区序的第一个元素 / 最后一个元素,作为新选择出来的元素添加到有序区。一直循环到无序区为空

2,算法步骤(升序)

  ① 有序区在数组前面

    用 i 从 0 遍历到 n-1:i 指向无序区的第一个元素 且 遍历 n-1 个元素表示需要找到 n-1 个当前无序区的最大值

    用 j 遍历无序区 (i ~ n-1),找到当前的最小值

  ② 有序区在数组后面

    用 i 从 n-1 遍历到 1:i 指向无序区的最后一个元素 且 遍历 n-1 个元素表示需要找到 n-1 个当前无序区的最大值

    用 j 遍历无序区 (0 ~ i),找到当前的最小值

3,代码

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#define N 110
int a[N];
void swap(int i, int j)
{
    int t = a[i];
    a[i] = a[j];
    a[j] = t;
}
void selectSort1(int n) // 升序,有序区在前面
{
    for (int i = 0; i < n; i++)
    {
        int k = i;
        for (int j = i; j < n; j++)
            if (a[j] < a[k])
                k = j;
        swap(i, k);
    }
}
void selectSort2(int n)  //  升序,有序区在后面
{
    for (int i = n - 1; i > 0; i--)
    {
        int k = i;
        for (int j = 0; j <= i; j++)
            if (a[j] > a[k])
                k = j;
        swap(i, k);
    }
}
int main(void)
{
    int n;
    while (scanf("%d", &n) != EOF)
    {
        for (int i = 0; i < n; i++)
            scanf("%d", &a[i]);

        selectSort1(n);
        selectSort2(n);
        for (int i = 0; i < n; i++)
            printf("%d ", a[i]);
        puts("");
    }
}
View Code

4,算法分析

  空间复杂度:仅用常数个辅助单元,所以空间复杂度为 O(1)

  时间复杂度:

     比较次数:无论数组的状态如何,每一次循环总是要进行比较的,而外层循环需要循环 n 次(n-1 也按 n 算),对于外层的第 i 次循环,需要循环  i 次内循环,所以比较次数为 n * (n -1) / 2

     移动次数:元素的移动只在外层循环中要交换元素的时候移动,每次交换需要移动 3 个元素,最多需要交换 m-1 次,因为最后一次必定不用交换,所以移动次数最多需要 3 * (m - 1) 次

     所以时间复杂度为 O(n2)

  稳定性:

    在进行交换元素的时候,可能会导致第 i 个元素与其它含有相同值的元素的相对位置发生改变,所以选择排序是一种不稳定的排序算法

 

 

 二,冒泡排序

1,算法思想

  从后往前/从前往后两两比较相邻元素的值,若为逆序,则交换它们,直到某一趟没有发生交换或者序列比较完

2,算法步骤(升序)

  ① 有序区在数组前面

    用 i 从 0 遍历到 n-1:i 指向无序区的第一个元素 且 遍历 n-1 个元素表示需要找到 n-1 个当前无序区的最大值

    用 j 遍历无序区 (i ~ n-1),找到当前的最小值

  ② 有序区在数组后面

    用 i 从 n-1 遍历到 1:i 指向无序区的最后一个元素 且 遍历 n-1 个元素表示需要找到 n-1 个当前无序区的最大值

    用 j 遍历无序区 (0 ~ i),找到当前的最小值

3,代码

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#define N 110
int a[N];
void swap(int i, int j)
{
    int t = a[i];
    a[i] = a[j];
    a[j] = t;
}
void bubbleSort(int n) // 升序,有序区在后面
{
    for (int i = n - 1; i > 0; i--)
    {
        for (int j = 0; j < i; j++) // 两两比较,注意 j+1 不要越界
            if (a[j] > a[j + 1])
                swap(j, j + 1);
    }
}
int main(void)
{
    int n;
    while (scanf("%d", &n) != EOF)
    {
        for (int i = 0; i < n; i++)
            scanf("%d", &a[i]);

        bubbleSort(n);
        for (int i = 0; i < n; i++)
            printf("%d ", a[i]);
        puts("");
    }
}
View Code

 

4,算法分析

  空间复杂度:仅用常数个辅助单元,所以空间复杂度为 O(1)

  时间复杂度:

    最坏时间复杂度:O(n2),逆序序列,比较次数,n(n-1)/2,移动次数,3n(n-1)/2

    平均时间复杂度:O(n2)

  稳定性:

    因为冒泡排序只交换相邻的逆序对,所以不可能越过相等的元素,造成不稳定现象。即当 i > j,a[i] = a[j] 时,不会发生交换

 

三,比较

  两者外层循环一模一样,内层循环的目的一样但实现方式不同:

    选择排序是通过选择实现的,冒泡排序是通过比较实现的

 

 

=========== ========= ======== ======== ====== ===== ==== === == =
  青玉案·元夕  宋 辛弃疾
东风夜放花千树,更吹风,星如雨。
宝马雕车香满路,凤箫声动,玉壶光转,一夜鱼龙舞。
蛾儿雪柳黄金缕。笑语盈盈暗香去。
众里寻他千百度,蓦然回首,那人却在,灯火阑珊处。
 
 

 

posted @ 2020-03-12 23:56  叫我妖道  阅读(226)  评论(0编辑  收藏  举报
~~加载中~~