1. 冒泡排序

冒泡排序Bubble Sort)是一种简单的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端。

  1. int[] array = {5, 4, 3, 2, 1};
  2.  
  3. boolean isChanged = false;
  4. for (int i = 0; i < array.length; i++) {
  5. isChanged = false;
  6.  
  7. for (int j = 0; j < (array.length - i - 1); j++) {
  8. if (array[j] > array[j + 1]) {
  9. int temp = array[j];
  10. array[j] = array[j + 1];
  11. array[j + 1] = temp;
  12.  
  13. isChanged = true;
  14. }
  15. }
  16.  
  17. if (!isChanged) {
  18. break;
  19. }
  20. }
    四次遍历
    4 3 2 1 5
    3 2 1 4 5
    2 1 3 4 5
    1 2 3 4 5
    最大比较次数: n(n-1)/2 时间复杂度(最坏情况): O(2^n)
    最小比较次数: n-1 时间复杂度(最好情况): O(n)

2. 快速排序

是由东尼·霍尔所发展的一种排序算法   基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。

  1. public static void main(String[] args) {
  2. // 快速排序
  3. int[] array = {8, 2, 4 ,7 ,1 ,9 ,3 ,6, 5};
  4. sortMe(array, 0, array.length-1);
  5. for (int i = 0; i < array.length; i++) {
  6. System.out.print(array[i] + ",");
  7. }
  8. }
  9.  
  10. public static void sortMe(int[] array, int low,int high){
  11. if(low < high){
  12. // 将list数组进行一分为二
  13. int middle = getMiddle(array, low, high);
  14. // 对低字表进行递归排序
  15. sortMe(array, low, middle-1);
  16. // 对高字表进行递归排序
  17. sortMe(array, middle+1, high);
  18. }
  19. }
  20.  
  21. public static int getMiddle(int[] array, int low,int high){
  22. // 数组的第一个作为中轴
  23. int temp = array[low];
  24. while(low < high){
  25. while(low < high && array[high] > temp){
  26. high--;
  27. }
  28.  
  29. // 比中轴小的记录移到低端
  30. array[low] = array[high];
  31.  
  32. while(low < high && array[low] <= temp){
  33. low++;
  34. }
  35.  
  36. // 比中轴大的记录移到高端
  37. array[high] = array[low];
  38. }
  39.  
  40. array[low] = temp; //中轴记录到尾
  41.  
  42. return low; //返回中轴的位置
  43. }

3. 直接插入排序

1、算法概念。

  1. 每次从无序表中取出第一个元素,把它插入到有序表的合适位置,使有序表仍然有序。

2、算法思想。

 假设待排序的记录存放在数组R[1..n]中。初始时,R[1]自成1个有序区,无序区为R[2..n]。从i=2起直至i=n为止,依次将R[i]插入当前的有序区R[1..i-1]中,生成含n个记录的有序区。

3、实现思路。

①用一个临时变量temp存储第i个元素(i>=1,下标从0开始)。

②比较R[i] 和R[i+1],如果R[i+1].compareTo(R[i])<0,则R[i+1] = R[i],即比R[i+1]的集合元素依次往右移动一个单位。

③将temp的值赋给R[i].

  1. public static void main(String[] args) {
  2. // 直接插入排序
  3. int[] array = {8, 2, 4 ,7 ,1 ,9 ,3 ,6, 5};
  4. insertSort(array);
  5.  
  6. for (int i = 0; i < array.length; i++) {
  7. System.out.print(array[i] + ",");
  8. }
  9. }
  10.  
  11. public static void insertSort(int[] data)
  12. {
  13. int length = data.length;
  14.  
  15. for (int i = 1; i < length; i++)
  16. {
  17. int tmp = data[i];
  18. if (tmp < data[i - 1])
  19. {
  20. int j = i - 1;
  21. for (; j >= 0 && data[j] > tmp; j--)
  22. {
  23. data[j + 1] = data[j];
  24. }
  25. data[j + 1] = tmp;
  26. }
  27. }
  28. }

  

4. 堆排序

堆排序的思想

利用大顶堆(小顶堆)堆顶记录的是最大关键字(最小关键字)这一特性,使得每次从无序中选择最大记录(最小记录)变得简单。

其基本思想为(大顶堆):

1)将初始待排序关键字序列(R1,R2....Rn)构建成大顶堆,此堆为初始的无序区;

2)将堆顶元素R[1]与最后一个元素R[n]交换,此时得到新的无序区(R1,R2,......Rn-1)和新的有序区(Rn),且满足R[1,2...n-1]<=R[n];

3)由于交换后新的堆顶R[1]可能违反堆的性质,因此需要对当前无序区(R1,R2,......Rn-1)调整为新堆,然后再次将R[1]与无序区最后一个元素交换,得到新的无序区(R1,R2....Rn-2)和新的有序区(Rn-1,Rn)。不断重复此过程直到有序区的元素个数为n-1,则整个排序过程完成。

操作过程如下:

1)初始化堆:将R[1..n]构造为堆;

2)将当前无序区的堆顶元素R[1]同该区间的最后一个记录交换,然后将新的无序区调整为新的堆。

因此对于堆排序,最重要的两个操作就是构造初始堆和调整堆,其实构造初始堆事实上也是调整堆的过程,只不过构造初始堆是对所有的非叶节点都进行调整。

下面举例说明:

给定一个整形数组a[]={16,7,3,20,17,8},对其进行堆排序。

首先根据该数组元素构建一个完全二叉树,得到

 

然后需要构造初始堆,则从最后一个非叶节点开始调整,调整过程如下:

20和16交换后导致16不满足堆的性质,因此需重新调整

这样就得到了初始堆。

即每次调整都是从父节点、左孩子节点、右孩子节点三者中选择最大者跟父节点进行交换(交换之后可能造成被交换的孩子节点不满足堆的性质,因此每次交换之后要重新对被交换的孩子节点进行调整)。有了初始堆之后就可以进行排序了。

此时3位于堆顶不满堆的性质,则需调整继续调整

 这样整个区间便已经有序了。
    从上述过程可知,堆排序其实也是一种选择排序,是一种树形选择排序。只不过直接选择排序中,为了从R[1...n]中选择最大记录,需比较n-1次,然后从R[1...n-2]中选择最大记录需比较n-2次。事实上这n-2次比较中有很多已经在前面的n-1次比较中已经做过,而树形选择排序恰好利用树形的特点保存了部分前面的比较结果,因此可以减少比较次数。对于n个关键字序列,最坏情况下每个节点需比较log2(n)次,因此其最坏情况下时间复杂度为nlogn。堆排序为不稳定排序,不适合记录较少的排序。
  1. private static int[] sort = new int[] {
  2. 1, 0, 10, 20, 3, 5, 6, 4, 9, 8, 12,
  3. 17, 34, 11
  4. };
  5.  
  6. public static void main(String[] args) {
  7. buildMaxHeapify(sort);
  8. heapSort(sort);
  9. print(sort);
  10. }
  11.  
  12. private static void buildMaxHeapify(int[] data) {
  13. // 没有子节点的才需要创建最大堆,从最后一个的父节点开始
  14. int startIndex = getParentIndex(data.length - 1);
  15. // 从尾端开始创建最大堆,每次都是正确的堆
  16. for (int i = startIndex; i >= 0; i--) {
  17. maxHeapify(data, data.length, i);
  18. }
  19. }
  20.  
  21. /**
  22. * 创建最大堆
  23. *
  24. * @paramdata
  25. * @paramheapSize需要创建最大堆的大小,一般在sort的时候用到,因为最多值放在末尾,末尾就不再归入最大堆了
  26. * @paramindex当前需要创建最大堆的位置
  27. */
  28. private static void maxHeapify(int[] data, int heapSize, int index) {
  29. // 当前点与左右子节点比较
  30. int left = getChildLeftIndex(index);
  31. int right = getChildRightIndex(index);
  32.  
  33. int largest = index;
  34. if (left < heapSize && data[index] < data[left]) {
  35. largest = left;
  36. }
  37. if (right < heapSize && data[largest] < data[right]) {
  38. largest = right;
  39. }
  40. // 得到最大值后可能需要交换,如果交换了,其子节点可能就不是最大堆了,需要重新调整
  41. if (largest != index) {
  42. int temp = data[index];
  43. data[index] = data[largest];
  44. data[largest] = temp;
  45. maxHeapify(data, heapSize, largest);
  46. }
  47. }
  48.  
  49. /**
  50. * 排序,最大值放在末尾,data虽然是最大堆,在排序后就成了递增的
  51. *
  52. * @paramdata
  53. */
  54. private static void heapSort(int[] data) {
  55. // 末尾与头交换,交换后调整最大堆
  56. for (int i = data.length - 1; i > 0; i--) {
  57. int temp = data[0];
  58. data[0] = data[i];
  59. data[i] = temp;
  60. maxHeapify(data, i, 0);
  61. }
  62. }
  63.  
  64. /**
  65. * 父节点位置
  66. *
  67. * @paramcurrent
  68. * @return
  69. */
  70. private static int getParentIndex(int current) {
  71. return (current - 1) >> 1;
  72. }
  73.  
  74. /**
  75. * 左子节点position注意括号,加法优先级更高
  76. *
  77. * @paramcurrent
  78. * @return
  79. */
  80. private static int getChildLeftIndex(int current) {
  81. return (current << 1) + 1;
  82. }
  83.  
  84. /**
  85. * 右子节点position
  86. *
  87. * @paramcurrent
  88. * @return
  89. */
  90. private static int getChildRightIndex(int current) {
  91. return (current << 1) + 2;
  92. }
  93.  
  94. private static void print(int[] data) {
  95. int pre = -2;
  96. for (int i = 0; i < data.length; i++) {
  97. if (pre < (int) getLog(i + 1)) {
  98. pre = (int) getLog(i + 1);
  99. System.out.println();
  100. }
  101. System.out.print(data[i] + "|");
  102. }
  103. }
  104.  
  105. /**
  106. * 以2为底的对数
  107. *
  108. * @paramparam
  109. * @return
  110. */
  111. private static double getLog(double param) {
  112. return Math.log(param) / Math.log(2);
  113. }

  5.  归并排序

九大排序算法Demo的更多相关文章

  1. 九大排序算法Java实现

    之前学习数据结构与算法时花了三天时间整理九大排序算法,并采用Java语言来实现,今天第一次写博客,刚好可以把这些东西从总结的文档中拿出来与大家分享一下,同时作为自己以后的备忘录. 1.排序算法时间复杂 ...

  2. C语言实现九大排序算法

    C语言实现九大排序算法 直接插入排序 折半插入排序 希尔排序 冒泡排序 快速排序 直接选择排序 堆排序 归并排序 基数排序 C语言实现九大排序算法 直接插入排序 将数组分为两个部分,一个是有序部分,一 ...

  3. 【转】九大排序算法-C语言实现及详解

    概述 排序有内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部的排序记录,在排序过程中需要访问外存. 我们这里说说八大排序就是内部排序. 当n较大, ...

  4. 你需要知道的九大排序算法【Python实现】之堆排序

    六.堆排序 ​堆排序是一种树形选择排序,是对直接选择排序的有效改进. ​堆的定义下:具有n个元素的序列 (h1,h2,...,hn),当且仅当满足(hi>=h2i,hi>=2i+1)或(h ...

  5. 你需要知道的九大排序算法【Python实现】之插入排序

    三.插入排序 基本思想:插入排序的基本操作就是将一个数据插入到已经排好序的有序数据中,从而得到一个新的.个数加一的有序数据,算法适用于少量数据的排序,时间复杂度为O(n^2).是稳定的排序方法.插入算 ...

  6. 你需要知道的九大排序算法【Python实现】之基数排序

    八.基数排序 基本思想:基数排序(radix sort)属于"分配式排序"(distribution sort),又称"桶子法"(bucket sort)或bi ...

  7. 你需要知道的九大排序算法【Python实现】之快速排序

    五.快速排序 基本思想:  通过一趟排序将待排序记录分割成独立的两部分,其中一部分记录的关键字均比另一部分关键字小,则分别对这两部分继续进行排序,直到整个序列有序. 算法实现: ​ #coding: ...

  8. 你需要知道的九大排序算法【Python实现】之归并排序

    四.归并排序 基本思想:归并(Merge)排序法是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,每个子序列是有序的.然后再把有序子序列合并为整体有序序列.归并过程:比 ...

  9. 你需要知道的九大排序算法【Python实现】之冒泡排序

    二.冒泡排序 基本思想:它的思路很有特点循环,两两向后比较.它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来.走访数列的工作是重复地进行直到没有再需要交换,也就是说该数 ...

随机推荐

  1. 201521123083《Java程序设计》第8周学习总结

    1. 本周学习总结 这周因为一些事情耽搁了,几乎没什么打java代码,这几天尽量补过来 2. 书面作业 1.List中指定元素的删除 1.1 实验总结 不贴大段代码了,简要总结一下.切割成数组,主要用 ...

  2. 201521123099 《Java程序设计》第4周学习总结

    1. 本周学习总结 2. 书面作业 注释的应用 使用类的注释与方法的注释为前面编写的类与方法进行注释,并在Eclipse中查看.(截图) 面向对象设计(大作业1,非常重要) 2.1 将在网上商城购物或 ...

  3. 201521123110第二周Java学习总结

    1.本章学习总结 本周的Java学习相对前一周更进了一步,初步学习了Java简单的输入和输出,String类的对象创建后不能修改,它是不可变的,在Java中浮点型默认是double型与C中的int型不 ...

  4. java课程设计--猜数字(团队博客)

    java课程设计--猜数字(团队博客) 1.团队名称以及团队成员介绍 团队名称:cz 团队成员:陈伟泽,詹昌锦 团队照片: 2.项目git地址 http://git.oschina.net/Devil ...

  5. 201521123013 《Java程序设计》第10周学习总结

    1. 本章学习总结 2. 书面作业 Q1.finally题目4-2 1.1 截图你的提交结果(出现学号) 1.2 4-2中finally中捕获异常需要注意什么? finally块中的异常必须在fina ...

  6. Eclipse rap 富客户端开发总结(8) : 发布到tomcat后解决rap编码和字符集的问题

    1 .解决 rap 字符集乱码的问题 字符集问题,解决办法:   在plugin.xml - build.properties 中添加 javacDefaultEncoding.. = UTF-8   ...

  7. dd命令

    前言 dd命令文件处理 dd命令用于复制文件并对原文件的内容进行转换和格式化处理.dd命令功能很强大的,对于一些比较底层的问题,使用dd命令往往可以得到出人意料的效果. dd命令 转换拷贝一个文件,特 ...

  8. 将数据转成JSON

    前言 前面我们在使用Strus2的时候,Struts2自带了组件能够让JavaBean对象.集合转成是JSON,不用我们自己拼接-这是非常方便的.但是,我们不一定使用Struts2框架来做开发呀.因此 ...

  9. activiti07- Task

    任务 用户任务: 用户任务,用来对那些需要人参与完成的工作进行建模.当流程执行到这样的用户任务时,会在被分配到该任务的用户或用户组的任务列表中创建新的任务. 用户任务中可以包含描述.事实上,任何BPM ...

  10. 开始使用ASP.NET Core - 创建第一个Web应用

    .NET Core 是.NET Framework的新一代跨平台应用程序开发框架,是微软在一开始发展时就开源的软件平台,由于 .NET Core 的开发目标是跨平台的 .NET 平台,因此 .NET ...