排序(一) - 内部排序

本文介绍了内部排序中的几种主要算法,包括插入排序(直接插入、折半插入、希尔排序)、交换排序(冒泡排序、快速排序)、选择排序(简单选择、堆排序)以及归并排序和基数排序。详细讨论了每种排序算法的基本思想、时间复杂度和稳定性,并指出快速排序在平均情况下性能最优,而基数排序不基于比较操作。
摘要由CSDN通过智能技术生成

Internal Sorting

基本概念

排序:重新排列列表中元素,使表中元素满足按关键字有序的过程。

算法稳定性:待排序表中的两个对应关键字相同的元素Ri和Rj,使用某一排序算法之后,Ri和Rj的相对位置保持不变。

算法是否具有稳定性不是衡量算法优劣的标准,只是对算法性质的描述。

算法的分类

分类标准:排序期间数据元素是否全部存放在内存中

  1. 内部排序 - 排序期间元素全部存放在内存中

  2. 外部排序 - 排序期间元素无法在全部同时存放在内存中(必须在排序过程中根据要求不断在内、外存之间移动

    一般,内部排序算法在执行过程中都要进行两种操作:比较移动
    但不是所有的内部排序算法都要基于比较操作(基数排序不基于比较)。

通常将排序算法分为以下五大类:

  1. 插入排序
  2. 交换排序
  3. 选择排序
  4. 归并排序
  5. 基数排序

不同的排序算法适合不同的环境,就全面性而言,很难提出一种被认为是最好的算法。

内部算法的性能取决于算法的时间复杂度和空间复杂度,而时间复杂度一般是由比较和移动的次数决定的。

插入排序

基本思想:每次将一个待排序的记录按其关键字大小插入到前面已排好序的子序列中,直到插入完成。

插入排序中的三种重要排序算法:直接插入排序折半插入算法希尔排序

直接插入算法

将元素L(i)插入到已有序的子序列L[i-1]中:

  1. 查找出L(i)L[1...i-1]中的插入位置k;
  2. L[k...i-1]中的所有元素依次往后移动一个位置;
  3. L(i)复制到L(k).

实现对L[1...n]的排序,可将L(2)~L(n)依次插入到前面已排好序的子序列中。

void InsertSort(Elemtype A[], int n) {
   
    int i, j;
    for(i = 2; i <= n; i++)
        if(A[i] < A[j]) {
          //若A[i]关键码大小小于其前驱,将A[i]插入有序表
            A[0] = A[i];        //复制为哨兵,A[0]不存放任何元素
            for(j = i - 1; A[0] < A[j]; --j)
                A[j+1] = A[j];  //向后挪位
            A[j + 1] = A[0];    //复制到插入位置
        }
}

注意上面“哨兵”的作用

空间效率:O(1)

时间效率:O(n^2)

稳定性:是一个稳定的排序算法(每次插入元素都是从后向前先比较再移动,所以不会出现相同元素相对位置发生变化的情况)

适用性:适用于顺序存储和链式存储的线性表

大部分排序算法都仅适用于顺序存储的线性表

折半插入排序

将比较和移动操作分离:先折半查找出元素的待插入位置,然后统一地移动代插入位置之后的所有元素。

因为折半查找仅适用于顺序表,所以折半插入排序也仅适用于顺序表。

void InsertSort(Elemtype A[], int n) {
   
    for(int i = 0; i <= n + 1; i++) {
   
        A[0] = A[i];                            //A[0]暂存到A[0]
        int low = 1, high = i - 1;              //折半查找
        while(low <= high) {
   
            int mid = (low + high) / 2;
            if(A[mid] > A[0]) high = mid - 1;
            else low = mid + 1;
        }
        for(int j = i - 1; j >= high + 1; --j)  //插入操作
            A[j + 1] = A[j];
        A[high + 1] 
  • 3
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AuthurLEE

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值