十 大 经 典 排 序 算 法 总 结 超 详 细
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
通过内层循环判定内部有序,直接跳出外层循环,因此时间复杂度为 O(n) 最坏情况便是如[5,4,3,2,1]这样的情况,每一次都需要把头部元素移
到尾部,因此时间复杂度为 O(n2) 选择排序 选择排序也是比较简单的一种排序方式,并且比冒泡排序更容易理解,
笔者刚入门时特别偏好这种排序方式 算法描述 核心思想: 每轮都把找出最大的元素的下标,再把该元素和最右边的元素交换,
实只要 n-1 次就够了,最后一次只剩下一个元素) 具体过程: 首先将数组从 a[0]到 a[n-1],通过一次次比较,把最大的元素移到最
右边的 a[n-1],此时 a[0]到 a[n-1]的最大的元素已经放到 a[n-1] 第二次将数组从 a[0]到 a[n-2],通过一次次比较,把最大的元素移到
groupNum -= 2; return array; 时间复杂度 最好情况 O(nlogn), 最坏情况 O(nlogn), 平均情况 O(nlogn) 关于希尔排序的时间复杂度的问题比较复杂,想要详细了解的同学可 以自行百度 归并排序 归并排序使用了分治法,将一个父问题拆分成多个子问题,先自顶向 下进行分割,然后再自底向上进行合并 算法描述 核心思想: 将序列分割为左右两半,然后递归对左右序列进行排序,再将有序的 左右序列使用 O(n)的合并算法合并为一个有序的合并序列。 具体过程: 分割的过程是自顶向下的: 0 [5,4,3,2,1] 1 [5,4] [3,2,1] 2 [5] [4] [3] [2,1] 3 [2] [1] 分治的过程如上图,一开始没有分割,然后分割为[5,4][3,2,1]两部 分,再对这两部分递归,随着逐步分割递归,形成了类似树一样的形式 合并的过程则是自底向上结束完成递归的:
数据结构七种排序算法讲解及其 Java 实现
【超实战追-女干货】【企鹅:1О ⒈⒍.x.9⒌⒉6】
数据结构七种排序算法讲解及其 Java 实现冒泡排序算法描述 Java 代 码时间复杂度选择排序算法描述 Java 代码时间复杂度插入排序算法描述 Java 代码时间复杂度希尔排序算法描述 Java 代码时间复杂度归并排序算 法描述 Java 代码时间复杂度快速排序算法描述 Java 代码时间复杂度堆排 序算法描述 Java 代码时间复杂度总结
for (int i = 0; i array.length; i++) { int selectedIndex = 0; int lastIndex = array.length - 1 - i; for (int j = 1; j = lastIndex; j++) { if (array[selectedIndex] array[j]) { selectedIndex = j; int tmp = array[lastIndex]; array[lastIndex] = array[selectedIndex]; array[selectedIndex] = tmp; return array; 时间复杂度 最好情况 O(n2), 最坏情况 O(n2), 平均情况 O(n2) 无论好坏,每一轮都需要把数组元素扫描一遍,求得最大值并进行交 换,共重复 n 轮,所以时间复杂度为 O(n2) 插入排序 算法描述 核心思想: 在保证 a[0]到 a[i]是有序的情况下,寻找一个合适的位置,把 a[i+1] 的元素插入其中,使得 a[0]到 a[i+1]也有序 有序数列[1,2,5,6,4],已知[1,2,5,6]有序,需要把 4 插入其中,首 先找到合适的位置,即 2 的后面、5 的前面,然后把 4 插进去,数列变成 [1,2,4,5,6],此时排序成功
再开始下一轮,从剩下的元素中继续挑选最大值继续交换到右边,这样的 操作重复 n 轮,即可完成排序(选择排序也只要 n-1 次就够了,最后一次 只剩下一个元素)
具体过程: 首先将数组从 a[0]到 a[n-1]扫描一遍,找到其中最大的元素并记录其 下标 x,交换 a[x]和 a[n-1]的元素值,此时 a[0]到 a[n-1]的最大的元素 已经放到 a[n-1] 第二次将数组从 a[0]到 a[n-2]扫描一遍,找到其中最大的元素并记录 其下标 x,交换 a[x]和 a[n-2]的元素值,此时 a[0]到 a[n-2]的最大的元 素已经放到 a[n-2] 第三次将数组从 a[0]到 a[n-3],… Java 代码 public int[] selectionSort(int[] array) {
[1,2,3,4,5,6,7,8],组内元素的下标相隔 groupNum ,从 a[0]到 a[n-1] 扫描一次数组,扫描的过程中对同组元素之间进行插入排序
按此过程进行排序,共需进行 logn 轮分组。 需要注意的是,分组数量并不唯一,可以一开始就选用 3 个元素一组, 然后 9 个元素一组,然后 27 个元素一组,这样也是可以的 Java 代码 public int[] shellSort(int[] array) {
首先看标号为 3 的那层,两个数组都长度为 1,不需要排序,直接返回 上一层调用
0 [5,4,3,2,1] 1 [5,4] [3,2,1] 2 [5] [4] [3] [2,1] 3 [2] [1] 然后看标号为 2 的那层,前面三个数组的长度都为 1,对于最后一个数 组,左半边排序完为[2],右半边排序完为[1],有序合并后为[1,2] 0 [5,4,3,2,1] 1 [5,4] [3,2,1] 2 [5] [4] [3] [1,2] 3 来自百度文库2] [1] 然后看标号为 1 的那层,对于[5,4],左半边排序完为[5],右半边排 序完为[4],有序合并后为[4,5],对于[3,2,1],左半边排序完为[3],右 半边排序完为[1,2],有序合并后为[1,2,3] 0 [5,4,3,2,1] 1 [4,5] [1,2,3] 2 [5] [4] [3] [1,2] 3 [2] [1] 然后看标号为 0 的那层,这是一开始的那层,对于[5,4,3,2,1],左半 边排序完为[4,5],右半边排序完为[1,2,3],有序合并后为[1,2,3,4,5], 至此,自底向上的合并完成,排序结束
for (int i = 0; i array.length - 1; i++) { int index = i; int insertionNum = array[i+1]; -- 从后往前扫描,一边寻找位置一边后移元素 -- 如果位置不合适那么就把元素后移一格,如果位置合适就退出循 环,向该位置放入需要插入的 insertionNum while (index =0 array[index] insertionNum ) { array[index+1] = array[index]; index--;
具体过程: 首先 a[0]只有一个元素,不需要排序 然后 a[0]到 a[1],已经保证 a[0]是有序的,只需要把 a[1]找一个合 适的地方插入即可 然后 a[0]到 a[2],已经保证 a[0]到 a[1]是有序的,只需要把 a[2]找 一个合适的地方插入即可 然后 a[0]到 a[i+1],已经保证 a[0]到 a[i]是有序的,把 a[i+1]插入 其中即可,令 insertionNum = a[i+1],insertionNum 插入数组后的位置 为 x,此时需要把数组中 a[x]到 a[i]的元素都后移一格,腾出 a[x]的空 间,并让 a[x] = insertionNum ,完成插入,使得 array[0]到 array[i+1] 有序 Java 代码 public int[] insertionSort(int[] array) {
数据结构的排序算法共有十种,本文仅给出其中七种算法,有空的话 会把剩下的三种(基数排序、计数排序、桶排序)补全。
本文代码使用的测试样例: int[] arr = {1,2,3,4,5}; int[] arr1 = {5,4,3,2,1}; int[] arr2 = {1,5,3,4,2}; 本文对于需要排序的数组为 a,类型为整形数组,假设其长度为 n,所 以数组下标范围为[0, n-1] 冒泡排序 冒泡排序可以说是我们最基础的排序方式了,可以说是排序题的暴力 解法 算法描述 核心思想: 每轮都把最大的元素移到最右边,再开始下一轮,从剩下的元素中继 续挑选最大值继续移动到右边,这样的操作重复 n 轮,即可完成排序(其
最右边的 a[n-2],此时 a[0]到 a[n-1]的第二大的元素已经放到 a[n-1] 第三次将数组从 a[0]到 a[n-3],… Java 代码 public int[] bubbleSort(int[] array) { for (int i = 0; i array.length; i++) { boolean isSwapped = false; for (int j = 0; j array.length - 1 - i; j++) { if (array[j] array[j+1]) { int tmp = array[j]; array[j] = array[j+1]; array[j+1] = tmp; isSwapped = true; if (!isSwapped) { return array; 时间复杂度 最好情况 O(n), 最坏情况 O(n2), 平均情况 O(n2) 最好情况便是如[1,2,3,4,5]这样的情况,外层循环只需要执行一次,
-- 最初是 2 个元素一组 int groupNum = array.length-2; -- 分组,共需进行 logn 次分组 while(groupNum 0) { -- 对组内元素进行插入排序, groupNum 为每组的第二个元素 -- 组内元素分别为: -- 0 groupNum 2*groupNum 3*groupNum -- 1 1+groupNum 1+2*groupNum 1+3*groupNum for (int i = groupNum; i array.length; i++) { int insertionNum = array[i]; int index = i - groupNum; while (index = 0 array[index] insertionNum ) { array[index + groupNum] = array[index]; index -= groupNum; array[index + groupNum] = insertionNum;
array[index+1] = insertionNum; return array; 时间复杂度 最好情况 O(n), 最坏情况 O(n2),平均情况 O(n2) 最好情况便是无需插入,数组自身有序,for 循环扫描一遍即可 最坏情况则是每次都需要把 a[i+1]这个元素插入到数组头,导致 a[0] 到 a[i]之间的元素都需要移动一格,腾出 a[0]用来放置需要插入的元素, for 循环跑满,内层的 while 循环也跑满,所以是 O(n2) 希尔排序 希尔排序可以说是插入排序的升级版,里面直接使用到插入排序 算法描述 核心思想: 按一定量进行分组,分组后对组内元素进行插入排序 具体过程: 假设数组为[1,2,3,4,5,6,7,8] 首先每两个元素一组,分组数量 groupNum = n-2,共分为[1,5]、[2,6]、 [3,7]、[4,8],组内元素的下标相隔 groupNum ,从 a[0]到 a[n-1]扫描一 次数组,扫描的过程中对同组元素之间进行插入排序 然后每四个元素一组,分组数量 groupNum = n-4,共分为[1,3,5,7]、 [2,4,6,8],组内元素的下标相隔 groupNum ,从 a[0]到 a[n-1]扫描一次 数组,扫描的过程中对同组元素之间进行插入排序 然 后 每 八 个 元 素 一 组 , 分 组 数 量 groupNum = n-8 , 只 有 一 组 ,