算法与数据结构(11)―― 堆排序(原地排序)

匿名 (未验证) 提交于 2019-12-03 00:22:01

原地排序:

之前两种的都是从索引1开始计算的,而原地排序不需要额外的辅助空间,即不用去创造堆,那么索引从0开始的~

注意一下 最后一个非叶子结点的索引是(count - 2)/ 2

public class HeapSort {     private HeapSort() {     }      public static void sort(Comparable[] arr){          int n = arr.length;          // 注意,此时我们的堆是从0开始索引的         // 从(最后一个元素的索引-1)/2开始         // 最后一个元素的索引 = n-1         for( int i = (n-1-1)/2 ; i >= 0 ; i -- )             shiftDown2(arr, n, i);          //  ---- 此时已经形成一个堆了 ----          for( int i = n-1; i > 0 ; i-- ){             swap( arr, 0, i);             shiftDown2(arr, i, 0);         }     }     // 交换堆中索引为i和j的两个元素     private static void swap(Object[] arr, int i, int j){         Object t = arr[i];         arr[i] = arr[j];         arr[j] = t;     }      // 原始的shiftDown过程     private static void shiftDown(Comparable[] arr, int n, int k){          while( 2*k+1 < n ){             int j = 2*k+1;             if( j+1 < n && arr[j+1].compareTo(arr[j]) > 0 )                 j += 1;              if( arr[k].compareTo(arr[j]) >= 0 )break;              swap( arr, k, j);             k = j;         }     }      // 优化的shiftDown过程, 使用赋值的方式取代不断的swap,     // 该优化思想和我们之前对插入排序进行优化的思路是一致的     private static void shiftDown2(Comparable[] arr, int n, int k){          Comparable e = arr[k];         while( 2*k+1 < n ){             int j = 2*k+1;             if( j+1 < n && arr[j+1].compareTo(arr[j]) > 0 )                 j += 1;              if( e.compareTo(arr[j]) >= 0 )                 break;              arr[k] = arr[j];             k = j;         }          arr[k] = e;     } }


排序算法总结


  • 时间复杂度:一般来说同等级别的快排系数比较小,较优
  • 原地排序:快速排序是有递归的,递归了logn层,需要栈空间来保存变量,而归并也有递归,是O(n)+O(logn),尽管归并也有原地排序,但是之后时间复杂度会上来,所以不推荐。
  • 空间复杂度:
    • 对于插入排序和堆排序而言,使用的额外空间就是数组上交换元素,所以所耗空间为O(1)级别,即常数级别。
    • 而归并排序需要O(n)级别空间,即数组同等长度空间来辅助完成归并过程。
    • 快速排序所需O(logn)额外空间,因为它采用递归方式来进行排序,递归有logn层,所以需要O(logn)空间来保证每一层的临时变量以供递归返回时继续使用。
  • 稳定排序:
    • 稳定排序
      • 插入排序:算法中有后面元素与前面元素相比较,若小于则前移,否则不动。所以相同元素之间位置不会发生改变。
      • 归并排序:在归并过程中,左右子数组已经有序,需要归并到一起,其核心也是判断当后面元素小于前面元素才前移,否则不动。所以相同元素之间位置不会发生改变。
    • 不稳定排序
      • 快速排序:算法核心中会随机选择一个标志点来进行大于、小于判断排序,所以很有可能使得后面相等元素到前面来。所以相同元素之间位置会发生改变。
      • 堆排序:将整个数组整理成堆的过程中会破坏掉稳定性。所以相同元素之间位置会发生改变。
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!