最近在看一些代码优化相关的东西,下午看到排序这块,常用的排序方式有冒泡排序、选择排序、快速排序等,这里记录下这三种排序的Java实现。最后附有2个测试这几种排序方式的时间的代码
一、几种常用排序方式介绍
1.冒泡排序
以升序排序为例,将序列看成一排竖着的气泡,最后一个元素与倒数第二个元素进行比较,小的往前移,再将倒数第二个元素与倒数第三个元素比较,依次类推,第一轮比较后,最小的就到了位置1,同样第二轮比较后第二小的到了位置二~
#PopSortDemo.java
/** * 冒泡排序 * * @author admin * */ public class PopSortDemo implements Sorted { public void sort(int[] array) { for (int i = 0; i < array.length; i++) { for (int j = array.length - 1; j > i; j--) { if (array[j] < array[j - 1]) { SortUtil.exchange(array, j, j-1); } } } } }
总结:
1). 需要比较的次数和数组长度有关[1+2+3+4~+(n-1)]
2). 需要排序数组长度越长,效率下降明显:n为10时需要比较45次,但n为100时比较次数直线上升到4950次,相差100多倍
2.冒泡排序(改进算法)
针对冒泡算法,如果有一轮没有发生交换,说明每个相邻位置不需要交换,即每个位置已经排好了,后面就可以不用继续了
#PopSortImproveDemo.java
/** * 冒泡排序算法(改进):如果有一轮没有发生交换,说明位置已经排好了,后面就可以不用继续了 * @author admin * */ public class PopSortImproveDemo implements Sorted { public void sort(int[] array) { boolean changed = true; for (int i = 0; i < array.length && changed; i++) { changed = false; for (int j = array.length - 1; j > i; j--) { if (array[j] < array[j - 1]) { changed = true; SortUtil.exchange(array, j, j - 1); } } } } }
总结:
1). 需要比较的次数和数组长度有关,最多比较[1+2+3+4~+(n-1)] 次,最少比较[n-1]次(初始就是有序的)
3.选择排序
先找出最小的数,放到第一个,找出后面数中,第二小的,放到第二个,以此类推。
/** * 选择排序 * * @author admin * */ public class SelectSortDemo implements Sorted { public void sort(int[] array) { int pos; for (int i = 0; i < array.length; i++) { pos=i; for (int j = i + 1; j < array.length; j++) { if (array[pos] > array[j]) { pos=j; } } if(pos!=i) SortUtil.exchange(array, pos, i); } } }
总结:
1). 比较次数和冒泡排序算法相同
2). 之前一直把选择排序记成冒泡排序,实际有区别的(*+﹏+*)~@
4.快速排序
选择一个基准元素,通常选择第一个元素或者最后一个元素,通过一趟扫描,将待排序列分成两部分,一部分比基准元素小,一部分大于等于基准元素,此时基准元素在其排好序后的正确位置,然后再用同样的方法递归地排序划分的两部分
/** * 快速排序:选择一个基准元素,通常选择第一个元素或者最后一个元素,通过一趟扫描,将待排序列分成两部分,一部分比基准元素小,一部分大于等于基准元素,此时基准元素在其排好序后的正确位置,然后再用同样的方法递归地排序划分的两部分 * @author admin * */ public class QuickSortDemo implements Sorted { public void sort(int[] array) { sort(array, 0, array.length - 1); } /** * 递归调用排序:排序基准位置前后子数组 * * @param array * @param start * @param end */ public void sort(int[] array, int start, int end) { if (start < end) { int pos = findMiddle(array, start, end); sort(array, start, pos - 1); sort(array, pos + 1, end); } } /** * 获取基准元素位置 */ public int findMiddle(int[] array, int start, int end) { int temp = array[start]; while (start < end) { // 结束位置递减,直到找到第一个比标准位置值小的 while (start < end && array[end] >= temp) { end--; } // 基准位置交换到end array[start] = array[end]; // 开始位置递增,直到找到第一个比标准位置值大的 while (start < end && array[start] <= temp) { start++; } // 基准位置交换到start array[end] = array[start]; } // 记录基准位置值 array[start] = temp; return start; } }
总结:
1) 速度比较快,当然前提是基准位置找的好\(`▽′)/
2) 最差的情况,需要找[n-1]次基准位置,找基准位置的过程中总共循环比较[1+2+3+4~+(n-1)]次
二、排序方式时间测试
几种排序的时间复杂度
排序法 |
最差时间分析 | 平均时间复杂度 | 稳定度 | 空间复杂度 |
冒泡排序 | O(n2) | O(n2) | 稳定 | O(1) |
快速排序 | O(n2) | O(n*log2n) | 不稳定 | O(log2n)~O(n) |
选择排序 | O(n2) | O(n2) | 稳定 | O(1) |
二叉树排序 | O(n2) | O(n*log2n) | 不一顶 | O(n) |
插入排序 |
O(n2) | O(n2) | 稳定 | O(1) |
堆排序 | O(n*log2n) | O(n*log2n) | 不稳定 | O(1) |
希尔排序 | O | O | 不稳定 | O(1) |
这里直接测试每种排序方式消耗的时间,采用两种方式:一种是每次排序都重新设置数组每个元素的值,第二种是不同的排序方式排序同一个数组
2. 不同排序方式,不同的数组
>测试代码:
/** * 排序测试,每种排序方式对不同随机数组排序多次,取平均时间 * * @author admin * */ public class RandomSortTest { private static Logger log = LogManager.getLogger(); public static void main(String[] args) { // 87, 76, 65, 51, 43, 31, 23, 17, 6, 3 // 6, 17, 23, 31, 43, 51, 65, 76, 87, 3 // 3, 6, 17, 23, 31, 43, 51, 65, 76, 87 // 数组长度 & 数组元素随机生成的最大值 & 每种排序方式测试次数 int len = 100000, numMax = 10000,sortTypeCount = 10; // 待排序数组 int[] arr = new int[len]; // 排序类 Sorted sorter = null; // 循环调用多个排序方法,每次调用getSorter()会返回不同的排序方法 while ((sorter = getSorter()) != null) { long time = 0; for (int i = 0; i < sortTypeCount; i++) { // 给每个数组元素设置随机值 SortUtil.insertRandomNumber(arr, numMax); // 排序,并返回排序时间 time += SortUtil.testSortTime(arr, sorter); } log.info("排序方法[{}],平均[{}/{}]耗时{}ms", sorter.getClass().getSimpleName(), time, sortTypeCount, time / sortTypeCount); } } /** * 排序方式:1、快速排序;2、选择排序;3、冒泡排序;4、冒泡排序(改进) */ private static int sortType = 1; private static Sorted getSorter() { Sorted sorter = null; // 1、快速排序;2、选择排序;3、冒泡排序;4、冒泡排序(改进) switch (sortType++) { case 1: sorter = new QuickSortDemo(); break; case 2: sorter = new SelectSortDemo(); break; case 3: sorter = new PopSortDemo(); break; case 4: sorter = new PopSortImproveDemo(); break; default: break; } return sorter; } }
>测试结果(len=10W):
2017-03-22 22:30:11.214 [main] INFO - 排序方法[QuickSortDemo],平均[92/10]耗时9ms cn.tinyf.demo.sort.RandomSortTest 2017-03-22 22:30:38.408 [main] INFO - 排序方法[SelectSortDemo],平均[27182/10]耗时2718ms cn.tinyf.demo.sort.RandomSortTest 2017-03-22 22:33:04.408 [main] INFO - 排序方法[PopSortDemo],平均[145987/10]耗时14598ms cn.tinyf.demo.sort.RandomSortTest 2017-03-22 22:35:26.352 [main] INFO - 排序方法[PopSortImproveDemo],平均[141931/10]耗时14193ms cn.tinyf.demo.sort.RandomSortTest
相关推荐
这里我们主要关注Java实现的七大经典排序算法:冒泡排序、插入排序、选择排序、希尔排序、快速排序、归并排序以及堆排序。 1. 冒泡排序(Bubble Sort): 冒泡排序是最简单的排序方法之一,它通过重复遍历待排序的...
本文将深入探讨标题"常用排序算法java演示"中涉及的知识点,包括排序算法的原理、Java实现方式以及其在实际应用中的图形演示。 首先,让我们逐一了解几种常见的排序算法: 1. **冒泡排序(Bubble Sort)**:这是一...
本篇文章将详细讲解标题中提到的六种常见排序算法的Java实现。 1. **冒泡排序**:冒泡排序是最基础的排序算法之一,它通过不断交换相邻的逆序元素来逐渐将较大的元素“浮”到数组的前端。在Java中,冒泡排序的基本...
本资源"常用各种排序算法Java的实现_差不多了__.rar"显然是一个包含了各种经典排序算法Java实现的压缩文件,对于学习和理解这些算法的开发者来说极具价值。 首先,我们来概述一下常见的排序算法: 1. 冒泡排序:是...
以上就是Java中实现的一些常用排序算法,它们各有优缺点,适用于不同的场景。理解并熟练掌握这些排序算法,有助于优化代码性能,提高编程能力。在实际开发中,应根据具体需求选择合适的排序算法,以达到最佳的效率和...
这里我们主要关注Java实现的排序算法,并结合一个PPT的动画演示来探讨其中的插入排序、直接插入排序和希尔排序。 首先,让我们深入理解插入排序。插入排序是一种简单的排序算法,其基本思想是将未排序的元素逐个...
虽然树形选择排序和堆排序在这次实现中未涵盖,但理解这四种排序算法的基本原理和Java实现方式对于提升编程技能至关重要。 首先,让我们来看看插入排序。插入排序是一种简单直观的排序算法,它的工作原理类似于人们...
### 常用排序算法分析与实现(Java版) #### 插入排序 **1. 直接插入排序** 直接插入排序是一种简单的排序方法,它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并...
这个名为"常用排序算法JAVA版"的压缩包文件很可能包含了Java实现的各种经典排序算法,如冒泡排序、选择排序、插入排序、快速排序、归并排序、堆排序等。 1. **冒泡排序**:是最简单的排序算法之一,通过不断交换...
以上就是六种常用的内部排序算法在Java语言中的实现。理解这些排序算法的原理和性能特点,有助于在实际编程中选择合适的排序方法,提高程序效率。对于面试或者笔试,熟练掌握这些算法将大大提高你的竞争力。在实践中...
冒泡排序和快速排序是两种基础但广泛使用的数据排序算法。冒泡排序由于其简单直观的特性,易于理解和实现,而快速排序则以其较高的效率在数据量较大时展现出优势。 首先,让我们来看冒泡排序算法。冒泡排序通过重复...
常用排序算法的Java实现源码,包括冒泡排序,快速排序,直接插入排序,希尔排序,直接选择排序,堆排序,归并排序,基数排序,计数排序。
在计算机科学中,排序算法是数据处理的重要组成部分,它们用于将一组无序的数据按照特定顺序进行排列。这里我们将深入探讨八大排序算法,并结合Java语言来理解它们的实现原理。 1. 冒泡排序(Bubble Sort) 冒泡...
在编程领域,排序算法是计算机科学中的核心概念,特别是在Java这样的高级编程语言中。排序算法是用来组织和优化数据结构的关键工具,使得数据按照特定规则(如升序或降序)排列。以下是对Java中几种常见排序算法的...
本资源提供了五种经典的排序算法的Java实现,包括选择排序(Selection Sort)、插入排序(Insertion Sort)、希尔排序(Shell Sort)、归并排序(Merge Sort)以及快速排序(Quick Sort)。 1. **选择排序**:选择排序是一种...
学习资料如"Java常用排序算法程序员必须掌握的8大排序算法Java开发Java经验技巧共16页.pdf"可以提供详细的讲解和示例,帮助你更好地理解和实践这些算法。同时,这些排序算法不仅限于Java,也广泛应用于Python、C语言...
### Java常用八大排序算法详解 #### 一、直接插入排序 **基本思想:** 直接插入排序的基本思路是在要排序的一组数中,假设前面 (n-1) [n>=2] 个数已经排好顺序,现在要把第 n 个数插入到前面的有序数列中,使得这 ...
这篇博客“常用排序算法小结(附Java实现)”提供了一种深入理解并掌握常见排序算法的途径,尤其对于Java开发者来说非常实用。文章可能涵盖了如冒泡排序、选择排序、插入排序、快速排序、归并排序、堆排序等多种经典...
本资料包聚焦于"Java常用排序算法"和"程序员必须掌握的8大排序算法",并深入探讨了"二分法查找"这一高效搜索技术。 首先,我们来看八大排序算法。这些算法包括: 1. **冒泡排序**:最简单的排序方法,通过不断交换...