数据结构与算法-排序(一)

数据结构与算法-排序(一)

​ 排序算法有很多种,此处仅介绍五种最经典通用的排序算法:冒泡排序、插入排序、选择排序、归并排序、快速排序。篇幅有限,本篇仅介绍前三种。

最好时间复杂度 最坏时间复杂度 平均时间复杂度 稳定排序 原地排序
冒泡排序 O(n) O(n^2) O(n^2)
插入排序 O(n) O(n^2) O(n^2)
选择排序 O(n^2) O(n^2) O(n^2)
归并排序 O(nlogn) O(nlogn) O(nlogn)
快速排序 O(nlogn) O(n^2) O(nlogn)

一、分析

​ 既然排序算法有很多种,那么为了比较不同算法之间区别评价优劣,便需要从算法的时间消耗,空间消耗与稳定性三方面入手。

1.1 时间消耗

​ 可以通过时间复杂度来分析算法的时间消耗,最好、最坏和平均时间复杂度都不可缺。同时,还要获知最好、最坏时间复杂度对应要排序的初始数据集的特点。因为数据的有序度不同,例如有的接近有序,有的完全无序,这对于排序的执行时间自然是有影响的,知道排序算法在不同数据下的性能表现有助相互对比分析。

​ 另外,当计算时间复杂度时,默认n值很大,此时会忽略它的系数、低阶和常数,但当n比较小时便不可忽略。因此,在对同一阶时间复杂度的排序算法性能进行对比时,系数、低阶和常数便要考虑进来。

​ 在排序过程中,会频繁进行比较与元素移动操作,在对排序算法进行效率分析时也应当考虑在内。

1.2 空间消耗

​ 空间消耗可以通过空间复杂度来衡量。其中,对于空间复杂度为O(1)的排序算法,称为原地排序算法。

1.3 稳定性

​ 除了时间复杂度与空间复杂度外,排序算法还有一个重要的分析指标,即稳定性,意思是如果待排序序列中存在数值相等的元素,排序结束后相等元素之间原有的顺序保持不变。举例来说,有一组序列 8, 5, 6, 9, 6, 4, 其中存在值相等的元素6,为便于区分,将前一个6记为6a,后一个6记为6b,即 8, 5, 6a, 9, 6b, 4 , 若排序后两个6顺序没变,即 4, 5, 6a, 6b, 8, 9, 则称这种排序算法是稳定的排序算法,否则称为不稳定的排序算法。

​ 需要注意的是,在某些业务场景中,稳定性是很重要的。例如,有一组学生信息序列,每个学生的信息包括学生学号与成绩。要求将学生成绩进行排序,对于成绩相同的学生按学号进行排序。当然,可以先对成绩进行排序,然后再针对相同成绩的学生进行学号排序,但这样的实现比较复杂。简单的,可以先对学号进行排序,再对成绩进行排序。若排序算法是稳定的,第二次的排序结束后相同成绩的学生已经是有序的。

二、简单排序算法简介

2.1 冒泡排序

​ 不断遍历待排序序列,依次比较相邻元素大小,看是否满足大小关系要求。若不满足,则互换位置。如下图第一次遍历过程,首先,8与5比较,8比5大,互换位置,接着,8与6比较,互换,8与9比较,不变,9与6比较,互换,9与4比较,互换,第一次遍历结束,9归位。
在这里插入图片描述

​ 可以发现,在一次遍历结束时,算法会将未排序(黑色数字表示)中的最大值移至未排序区间的末尾,接着将该元素并入已排序(红色数字表示)区域。一次冒泡会让至少一个元素移动到它应该在的位置,重复 n 次,就完成了 n 个数据的排序工作。
在这里插入图片描述

​ 但是,当考察最好情况下(即待排序序列已经完全有序)算法表现时,会发现算法的效率不尽如人意。如下图所示,当第二次遍历结束时,序列已经实现有序,但算法本身却没有察觉,仍然继续遍历直至n次结束。事实上,如果在第三次遍历时,会发现此次遍历没有进行数据交换,说明序列本身已经实现有序,后续操作不必执行。要达到这一目的,只需引入一个标记位即可。
在这里插入图片描述

代码简单示例如下:

public void bubbleSort(int[] a, int n){
   
    if(n <= 1) return;
	for(int i = 0; i < n; i++){
   
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
排序是计算机科学中常见的操作,它将一组元素按照特定的顺序重新排列。排序算法的目标通常是将元素按照升序或降序排列。 常见的排序算法有很多种,每种算法都有不同的时间复杂度和空间复杂度。以下是几种常见的排序算法: 1. 冒泡排序(Bubble Sort):比较相邻的两个元素,如果顺序不正确就交换位置,每次遍历将一个最大(最小)的元素移到最后(最前)。时间复杂度为O(n^2)。 2. 插入排序(Insertion Sort):将数组分为已排序和未排序两部分,每次从未排序部分取出一个元素,插入已排序部分的适当位置。时间复杂度为O(n^2)。 3. 选择排序(Selection Sort):每次从未排序部分选择一个最小(最大)的元素放到已排序部分的末尾。时间复杂度为O(n^2)。 4. 快速排序(Quick Sort):选取一个基准元素,将数组划分为两个子数组,小于基准元素的放在左边,大于基准元素的放在右边,然后对子数组进行递归排序。时间复杂度平均情况下为O(nlogn),最坏情况下为O(n^2)。 5. 归并排序(Merge Sort):将数组递归分成两个子数组,然后对子数组进行排序,最后将两个已排序的子数组合并成一个有序数组。时间复杂度为O(nlogn)。 6. 堆排序(Heap Sort):将数组构建成一个最大(最小)堆,每次从堆顶取出最大(最小)元素放到已排序部分的末尾,然后调整堆使其满足堆的性质。时间复杂度为O(nlogn)。 这里只介绍了几种常见的排序算法,每种算法都有其适用的场景和优缺点。在实际应用中,根据数据规模和性能要求选择合适的排序算法非常重要。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值