《数据结构与算法之美》专栏阅读笔记3——排序算法

上周排计划,说花个一天的时间看完好了(藐视脸)~然后每天回家看一会,看了一个星期……做人,要多照镜子好嘛

1、简单排序

1.1 如何分析排序算法

从以下几个方方面入手。

执行效率
  • 最好情况、最坏情况、平均情况时间复杂度
  • 时间复杂度的系数、常数、低阶
    时间复杂度反映的时数据规模较大的时候的增长趋势。但实际开发中,也存在很多小规模的数据,此事稀疏、常数和低阶的占比较大,需要进行考虑。
  • 比较次数和交换次数
内存消耗

可以通过空间复杂度来衡量。新概念:原地排序。特指空间复杂度为O(1)的排序算法。

稳定性

对于同一序列,排序的结果相同。
因为实际比较中,更多的是对对象进行排序。

2、排序算法

2.1、冒泡

原理:重复地走访过要排序的元素列,依次比较两个相邻的元素,如果他们的顺序错误就把他们交换过来。重复地进行直到没有相邻元素需要交换,直到排序完成。

要点:

  • 对N个待排序元素,要排序的序列是0 ~ (N-已排序个数)。
  • 如果一次排序中没有进行任何元素交换,说明序列已经是有序的,可以停止比较。

分析:
顺便复习下均摊时间复杂度的使用场景:

  • 大部分情况下,时间复杂度都很低,只有个别情况下,时间复杂度较高。
  • 操作之间存在前后连贯的时序关系
    对排序算法的平均复杂度分析,可以使用有序度逆序度来进行分析。
  • 有序度:数组中具有有序关系的元素对的个数。
  • 满序度:完全有序的大小为n的数组的有序度,为n*(n-1)/2
  • 逆序度:与有序度相反。

关键公式:逆序度 = 满有序度 - 有序度。

排序的过程就是达到满有序度的过程

结论:交换的次数等于逆序度。
平均交换次数 = [0(最好) + n*(n-1)/2(最坏)]/2 = n*(n-1)/4

在作者给的基础上再来一点优化:

public static <T extends Comparable<T>> void BubbleSort(T[] values, int length) {
        if (length <= 1)
            return;
        int flag = length;
        while (flag > 0) {
            int end = flag - 1;
            flag = 0;
            for (int j = 0; j < end; j++) {
                if (values[j].compareTo(values[j+1]) > 0) {
                    T tmp = values[j];
                    values[j] = values[j+1];
                    values[j+1] = tmp;
                    flag = j + 1;
                }
            }
        }
    }

通过flag来缩短要排序序列

2.2、插入

原理:取未排序区间中的元素,在已排序区间中找到合适的插入位置将其插入,并保证已排序区间数据一直有序。

要点:
插入是通过移动来达到满序度的,所以移动的次数等于逆序度。

public static <T extends Comparable<T>> void InsSort(T[] values, int length) {
        if (length <= 1)
            return;
        for (int i = 0; i < length; i++) {
            T v = values[i];
            int j = i - 1;
            for (; j >= 0; --j) {
                if (values[j].compareTo(v) > 0) {
                    values[j+1] = values[j];
                } else {
                    break;
                }
            }
            values[j+1] = v;
        }
    }

直接插入排序,因为是要在已排序的序列中找到插入位置,所以需要移动是主节

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值