排序

1. 冒泡排序

时间复杂度:最好O(n),平均和最坏情况O(n2)
空间复杂度:O(1)
稳定排序
原理:从第一个元素开始,依次比较相邻两个元素,如果前者比后者大,那么就交换者两个元素,然后处理下一组,依次类推,直到排序完成。
实现:

  1. publicvoid bubbleSort(int[] arr){
  2. boolean isChanged =false;
  3. for(int i =0; i < arr.length -1; i++){
  4. isChanged =false;
  5. for(int j =0; j < arr.length -1- i; j++){
  6. if(arr[j]> arr[j+1]){
  7. int tmp = arr[j];
  8. arr[j]= arr[j+1];
  9. arr[j+1]= tmp;
  10. isChanged =true;
  11. }
  12. }
  13. if(!isChanged)break;//本次没有发生交换,说明已经排好序了
  14. }
  15. }
2. 选择排序

时间复杂度:最好、平均和最坏情况O(n2)
空间复杂度:O(1)
不是稳定排序
原理:从第一个元素开始,每次逐一扫描选择未排序部分的最小值,排在已排序部分后面,然后从下一个位置开始,继续进行相同的操作,直到排序完成。
实现:

  1. /**
  2. * 选择排序
  3. */
  4. publicstaticvoid sort(int[] arr){
  5. //判断arr是否为空
  6. if(arr ==null)return;
  7. int minIndex;
  8. for(int i =0; i < arr.length -1; i++){
  9. minIndex = i;
  10. for(int j = i +1; j < arr.length; j++){
  11. if(arr[j]< arr[minIndex]){
  12. minIndex = j;
  13. }
  14. }
  15. if(minIndex != i){//最小值不是当前值,需要交换
  16. int tmp = arr[i];
  17. arr[i]= arr[minIndex];
  18. arr[minIndex]= tmp;
  19. }
  20. }
  21. }
3. 快速排序

时间复杂度:最好、平均情况O(nlogn),最坏情况O(n2)
空间复杂度:平均情况O(logn),最坏情况O(n)
不是稳定排序
原理:每次选择一个数,将数组按照这个数分成左右两个部分,右边的比它大,左边的比他小然后对左右两部分分别进行同样的操作,直到数组排序完成
实现:

  1. publicstaticvoid sort(int[] arr){
  2. sortCore(arr,0, arr.length -1);
  3. }
  4. /**
  5. * @param arr 排序的数组
  6. * @param start 开始位置
  7. * @param end 结束位置
  8. */
  9. privatestaticvoid sortCore(int[] arr,int start,intend){
  10. int poiv = partion(arr, start,end);
  11. if(poiv > start){
  12. sortCore(arr, start, poiv -1);
  13. }
  14. if(poiv >= start && poiv <end){
  15. sortCore(arr, poiv +1,end);
  16. }
  17. }
  18. privatestaticint partion(int[] arr,int start,intend){
  19. int tmp = arr[start];
  20. while(start <end){
  21. while(start <end&& arr[end]>= tmp)end--;
  22. if(start <end){
  23. arr[start]= arr[end];
  24. }
  25. while(start <end&& arr[start]< tmp) start++;
  26. if(start <end){
  27. arr[end]= arr[start];
  28. }
  29. }
  30. arr[start]= tmp;
  31. return start;
  32. }
4. 归并排序

时间复杂度:最好、平均和最坏情况O(nlogn)
空间复杂度:O(n)
稳定排序
原理:首选将要排序的数组对半分,对各自部分进行排序。每部分继续进行相同的操作,直至最底层。然后合并两个相邻的部分,直到所有元素都排序完成
实现:

  1. publicstaticvoid sort(int[] arr){
  2. //创建数组,辅助排序
  3. int[] copy =newint[arr.length];
  4. sortCore(arr, copy,0, arr.length -1);
  5. }
  6. /**
  7. * 归并排序核心实现
  8. * @param arr 排序的数组
  9. * @param copy 辅助空间
  10. * @param start 开始位置
  11. * @param end 结束位置
  12. * @param offset 索引相对于原数组的偏移
  13. */
  14. privatestaticvoid sortCore(int[] arr,int[] copy,int start,intend){
  15. if(start ==end){
  16. copy[start]= arr[start];
  17. return;}
  18. int mid =(end- start)/2+ start;
  19. //分成两部分,递归
  20. sortCore(arr, copy, start, mid);
  21. sortCore(arr, copy, mid +1,end);
  22. //合并两个部分,将合并结果存入
  23. int forward = mid;
  24. int behand =end;
  25. intlast=end;
  26. while(forward >= start && behand > mid){
  27. if(copy[forward]> copy[behand]){
  28. arr[last--]= copy[forward --];
  29. }else{
  30. arr[last--]= copy[behand --];
  31. }
  32. }
  33. while(forward >= start){
  34. arr[last--]= copy[forward --];
  35. }
  36. while(behand > mid){
  37. arr[last--]= copy[behand --];
  38. }
  39. //拷贝到copy数组
  40. for(int i = start; i <=end; i++){
  41. copy[i]= arr[i];
  42. }
  43. }
5. 插入排序

时间复杂度:最好O(n),平均和最外情况O(n2)
空间复杂度:O(1)
稳定排序
原理:从数组第一个元素开始,依次比较前面已经排序的部分,插入合适的位置,前面排序部分比当前值大的部分向后移动一个。
实现:

  1. publicstaticvoid sort(int[] arr){
  2. int tmp;//每次排序,存储当前的值
  3. for(int i =1; i < arr.length; i++){
  4. tmp = arr[i];//保存当前值
  5. int j;
  6. for(j = i; j >= fromIndex && tmp < arr[j -1]; j --){//遇到比当前值大的元素,则元素后移一位
  7. arr[j]= arr[j-1];
  8. }
  9. arr[j]= tmp;|
  10. }
  11. }
6. 希尔排序

时间复杂度:平均情况O(n1.25)
空间复杂度:O(1)
不是稳定排序
原理:将无序数组分割为若干个子序列,子序列不是逐段分割的,而是相隔特定的增量的子序列,对各个子序列进行插入排序;然后再选择一个更小的增量,再将数组分割为多个子序列进行排序……最后选择增量为1,即使用直接插入排序,使最终数组成为有序。
实现:

  1. publicstaticvoid sort(int[] arr){
  2. //checkRange(arr.length, fromIndex, toIndex);
  3. int adder = arr.length /2;//增量
  4. while(adder >0){
  5. //从adder开始,每次排序均与前面的adder(当adder是1时就是插入排序)处的元素比较
  6. for(int i = adder ; i < arr.length; i++){
  7. int j;
  8. int tmp = arr[i];
  9. for(j = i; j >= adder && tmp < arr[j - adder]; j = j - adder){
  10. arr[j]= arr[j - adder];
  11. }
  12. arr[j]= tmp;
  13. }
  14. adder /=2;
  15. }
  16. }
7. 堆排序

时间复杂度:最好、平均和最坏情况均为O(nlogn)
空间复杂度:O(1)
不是稳定排序
原理:建立初始堆,从最后一个非叶结点开始,往前遍历,判断以该节点的开始的堆是否是符合,不符合则调整需要建立大顶堆,每次将子节点中较大地一个数往上移动,直到叶结点(堆:结点n的父节点为(n-1)/ 2,其左右子节点为2n+1和2n+2大根堆为根结点的值大于等于左右子结点的值),然后依次将堆顶值与为排序的最后一个值交换,然后调整前面的值为大顶堆,每次将最大的值排好序。
实现:

  1. /**
  2. * 堆排序
  3. */
  4. publicstaticvoid sort(int[] arr){
  5. //建立初始堆,从最后一个非叶结点开始,往前遍历,判断以该节点的开始的堆是否是符合,不符合则调整
  6. //需要建立大顶堆,每次将子节点中较大地一个数往上移动,直到叶结点
  7. //节点n的父节点为(n-1)/ 2,其左右子节点为2*n+1和2*n+2
  8. //大根堆为根结点的值大于等于左右子结点的值
  9. for(int i =(arr.length -1-1)/2; i >=0; i--){
  10. adjustHeap(arr, i, arr.length-1);
  11. }
  12. //依次将堆顶值与为排序的最后一个值交换,然后调整前面的值为大顶堆
  13. for(int i = arr.length -1; i >=1; i--){
  14. //交换
  15. arr[0]^= arr[i];
  16. arr[i]^= arr[0];
  17. arr[0]^= arr[i];
  18. //调整
  19. adjustHeap(arr,0, i -1);
  20. }
  21. }
  22. /**
  23. * 调整为大顶堆
  24. * @param arr
  25. * @param i 以i为堆的堆顶
  26. * @param last 堆顶的最后一个结点的索引
  27. */
  28. privatestaticvoid adjustHeap(int[] arr,int i,intlast){
  29. //建立以i结点为根的堆,判断子结点是否大于该节点,并将较大地值拷贝,然后继续判断
  30. int tmp = arr[i];
  31. for(int j = i *2; j <=last; j *=2){
  32. //获得左右子树中较大的一个数的下标
  33. if(j <last&& arr[j]< arr[j+1]) j++;//存在右子结点且右子结点较大
  34. if(tmp >= arr[j])break;//根结点比较大,则完成
  35. //将较大的值作为根
  36. arr[i]= arr[j];
  37. i = j;//继续往下判断,j的位置的值是最初的根结点
  38. }
  39. arr[i]= tmp;//最后确定的位置,没有子结点或者比子结点的值大;
  40. }





原文地址:https://www.cnblogs.com/ggmfengyangdi/p/5703260.html