排序 | 冒泡排序 & 简单选择排序

交换排序

交换排序的基本思想:

两两比较待排序记录的关键字,一旦发现两个记录不满足次序要求时则进行交换,直到整个序列全部满足要求为止。

冒泡排序是基于简单交换思想而实现的。

冒泡排序

冒泡排序(Bubble Sort)是一种最简单的交换排序方法。

通过两两比较相邻的关键字,如果发生逆序,则进行交换,从而使关键字小的记录(值较小的)如气泡一般逐渐往上“漂浮”(左移),或者说是使关键字大的记录(值较大的)如石块一样逐渐向下“坠落”(右移)。

算法步骤:

① 设待排序序列存放在数组arr[0...n-1]中(n为待排序序列的长度)。首先将第一个数(arr[0])和第二个数(arr[1])进行比较,若为逆序(即arr[0]>arr[1]),则交换两个值。然后比较第二个数(arr[1])和第三个数(arr[2])……以此类推,直到第n-1个数(arr[n-2])和第n个数(arr[n-1])进行比较为止。

上述过程称作一趟冒泡排序,其结果使得值最大的数(假设为max)被放置到最后一个位置上去(即arr[n-1]=max)。

② 然后进行第二趟冒泡排序,对前n-1个数进行同样的操作(同①过程),其结果使得值次大的数被放置到第n-2个位置上去。

③ 重复上诉比较和交换过程,第i趟是从arr[0]到arr[n-i]依次比较相邻两个数的值,并在“逆序”时交换相邻的数,其结果是这n-i+1个记录中值最大的数被交换到第n-i+1的位置上。

直到在某一趟排序过程中没有进行过交换操作,说明序列已全部达到排序要求,则排序完成。

图文说明:

排序 | 冒泡排序 & 简单选择排序_第1张图片
冒泡排序

实现代码:【C++版】

#include
#include
using namespace std;

int n;
int arr[200010];

// 冒泡排序
// O(N^2) 
// arr[]:存储待排序序列的数组
// length:待排序序列的长度 
void bubblesort(int arr[],int length)
{
    int m=length-1;
    int flag=1;
    while(m>0 && flag==1)
    {
        flag=0;
        for(int i=0;iarr[i+1])
            {
                swap(arr[i],arr[i+1]);// 交换的过程 
                /*
                int temp;
                temp=arr[i];
                arr[i]=arr[i+1];
                arr[i+1]=arr[i];
                */ 
                flag=1;// 标记,表示在此趟排序过程中有值的交换 
            }
        }
        m--;// 减一 
    }
}

int main()
{
    scanf("%d",&n);// 输入序列的长度n 
    for(int i=0;i
运行结果

算法分析:

(1) 时间复杂度:

  • 最好情况(初始序列为正序):只需要进行一趟排序,在排序过程中进行n-1次值的比较,且不移动对应值的位置。

  • 最坏情况(初始序列为逆序):需进行n-1趟排序,总的值的比较次数KCN和对应值位置的移动次数RCN(每次交换都要移动3次位置)分别为:
    KCN==
    RCN==
    所以,在平均情况下,冒泡排序的值的比较次数和位置移动次数分别约为和,时间复杂度为。

(2)空间复杂度:
冒泡排序只有在两个值交换位置时需要辅助空间用作暂存记录,所以空间复杂度为。

算法特点:

  • 是稳定排序。
  • 可用于顺序结构,也可用于链式存储结构。
  • 移动位置次数较多,算法平均时间性能比直接插入排序差。当初始记录无序,n较大时,此算法不宜采用。

选择排序

选择排序的基本思想:

每一趟从待排序的记录中选出关键字最小的记录,按顺序放在已排序的记录序列的后面,直到全部排完为止。

下面我们将介绍一种简单选择排序方法。

简单选择排序

简单选择排序(Simple Selection Sort)也称为直接选择排序。

算法步骤:

① 设待排序的记录存放在数组arr[0...n-1]中。第一趟从arr[0]开始,通过n-1次比较,从n个记录中选出关键字(值)最小的记录(数组下标),记为arr[k],交换arr[i]和arr[k]。
② 第二趟从arr[1]开始,通过n-2次循环,从n-1个记录中选出关键字(值)最小的记录(数组下标),记为arr[k],交换arr[1]和arr[k]。
③ 以此类推,第i趟从arr[i-1]开始,通过n-i次比较,从n-i+1个记录中选出关键字(值)最小的记录(数组下标),记为arr[k],交换arr[i-1]和arr[k]。
④ 经过n-1趟,排序完成。

图文说明:

排序 | 冒泡排序 & 简单选择排序_第2张图片
简单选择排序

实现代码:

#include
#include
using namespace std;

int n;
int arr[200010];

// 【简单选择排序】
// O(N^2)
// arr[]:存储待排序序列的数组
// length:待排序序列的长度 
void selectsort(int arr[],int length)
{
    int k;// 记录(数组下标) 
    // 在arr[0...length-1]中选择关键字(值)最小的记录(数组下标) 
    for(int i=0;i

算法分析:

(1)时间复杂度:
简单选择排序过程中,所需进行记录移动的次数较少。

  • 最好情况(正序):不移动。
  • 最坏情况(逆序):移动次。

然而,无论记录的初始排序如何,所需进行的关键字间的比较次数相同,均为
==

因此,简单选择排序的时间复杂度也是。

(2)空间复杂度:
同冒泡排序一样,只有在两个记录交换时需要一个辅助空间,所以空间复杂度为。

算法特点:

  • 就选择排序本身来讲,它是一种稳定的排序方法。但是,就程序中的简单选择排序,这是一种不稳定的排序(由于采用“交换记录”的策略造成的)。
  • 可用于链式存储结构。
  • 移动记录次数较少,当每一记录占用的空间较多时,此方法比直接插入排序快。

写在最后

上述两种排序方法的时间复杂度均为是最基础的两种排序方法,后面将逐步介绍一些更快、更高级的排序方法。

参考资料:

  • 《数据结构(C语言版) (第2版)》严蔚敏
  • 博客:https://www.cnblogs.com/chengxiao/p/6103002.html (部分图片来源)
  • 博客:https://www.cnblogs.com/jingmoxukong/p/4303289.html (部分图片来源)

如有错误,欢迎指正。

你可能感兴趣的:(排序 | 冒泡排序 & 简单选择排序)