栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

JAVA 修炼秘籍第十一章:《排序,没有最好最全,只有更好更全》

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

JAVA 修炼秘籍第十一章:《排序,没有最好最全,只有更好更全》

往期:
JAVA 修炼秘籍第一章:《痛苦的折磨》
JAVA 修炼秘籍第二章:《逐渐魔化》
JAVA 修炼秘籍第三章:《绝地反击》
JAVA 修炼秘籍第四章:《闭关修炼》
JAVA 修炼秘籍第五章:《卧薪尝胆》
JAVA 修炼秘籍第六章:《鏖战》
JAVA 修炼秘籍第七章:《面向对象编程》
JAVA 修炼秘籍第八章:《String类》
JAVA 修炼秘籍第九章:《List / ArrayList / linkedList 》
JAVA 修炼秘籍第十章:《优先级队列(堆)PriorityQueue》
JAVA修炼秘籍(番外篇)第一章:《这四道代码题,你真的会吗?》
JAVA修炼秘籍(番外篇)第二章:《图书馆管理系统》


——————————————————————生活以痛吻我,我却报之以歌。

文章目录
  • 一、插入排序
  • 二、折半插入排序
  • 三、希尔排序
  • 四、选择排序
  • 五、双向选择排序
  • 六、堆排序
  • 七、冒泡排序
  • 八、快速排序(挖坑)
  • 九、快速排序(Hoare)
  • 十、快速排序(非递归)
  • 十一、归并排序(递归)
  • 十二、归并排序(非递归)


一、插入排序
  1. 时间复杂度:O(n²)。
  2. 空间复杂度:O(1)。
  3. 当一组数据,数据量不大且趋近于有序时,推荐使用插入排序更快
public static void InsertSort(int[] arr){
        for(int i=1;i=0;j--){
                if(arr[j]>tmp){
                    arr[j+1]=arr[j];
                }else{
                    break;
                }
            }
            arr[j+1]=tmp;
        }
    }
二、折半插入排序
  1. 时间复杂度:O(n²)。
  2. 空间复杂度:O(1)。
  3. 通过直接插入排序可以发现,每次比较时,i下标前的数据时有序的。
  4. 折半插入排序利用此特性将i下标的值与前面有序数据进行二分查找。
  5. 算是直接插入排序的一种优化。
public static void HalveInsertSort(int[] arr){
        for(int i=1;i=left){
                int mid=(left+right)/2;
                if(arr[mid]>tmp){
                    right=mid-1;
                }else{
                    left=mid+1;
                }
            }
            for(int j=i-1;j>right;j--){
                arr[j+1]=arr[j];
            }
            arr[right+1]=tmp;
        }
    }
三、希尔排序
  1. 时间复杂度:O(n1.3)。
  2. 空间复杂度:O(1)。
  3. 希尔排序的巧妙处与插入排序有异曲同工之处。
  4. 中心思想在于gap的取值,取值方法有很多中,但都大同小异,其余思想与插入排序无太大差别。
public static void shellSort(int[] arr){
        int gap=arr.length;
        while(gap>0){
            mySort(arr,gap);
            gap/=2;
        }
    }
    public static void mySort(int[] arr,int gap){
        for(int i=gap;i<=arr.length;i++){
            int tmp=arr[i];
            int j=i-gap;
            for(;j>=0;j-=gap){
                if(arr[j]>tmp){
                    arr[j+gap]=arr[j];
                }else{
                    break;
                }
            }
            arr[j+gap]=tmp;
        }
    }
四、选择排序
  1. 时间复杂度:O(n²)。
  2. 空间复杂度:O(1)。
  3. 顾名思义,选择排序,选择好了再排序。
  4. 每次从数组中选择一个最大或最小的数据与头或尾交换。
  5. 再将交换后的边界缩小。
public static void selectSort(int[] arr){
        for(int i=0;iarr[max]){
                    max=j;
                }
            }
            int tmp=arr[max];
            arr[max]=arr[arr.length-1-i];
            arr[arr.length-1-i]=tmp;
        }
    }
五、双向选择排序
  1. 时间复杂度:O(n²)。
  2. 空间复杂度:O(1)。
  3. 与选择排序中心思想相同,这次是一次找出最大与最小同时交换
  4. 此算法中而每次取值的最小值下标有头下标交换时,如果头下标的位置刚好时是最大值,此时交换后max下标指向则不是最大值而是最小值,最后的if()判断很重要。
public static void TwoWaySelectSort(int[] arr){
        int left=0;
        int right=arr.length-1;
        while(left<=right){
            int min=left;
            int max=left;
            for(int i=left+1;i<=right;i++){
                if(arr[i]>arr[max]){
                    max=i;
                }
                if(arr[i] 
六、堆排序 
  1. 时间复杂度:O(logn)。
  2. 空间复杂度:O(1)。
  3. 假设要排序升序,首先将数组变为大堆存储形式。
  4. 再循环从后向前把每个元素与0下标元素交换。
  5. 每次交换后都要进行一次大堆调整。
public static void shiftDown(int[] arr,int parent,int len){
        int child=parent*2+1;
        while(childarr[parent]){
                swap(arr,child,parent);
                parent=child;
                child=parent*2+1;
            }else{
                break;
            }
        }
    }
    public static void MySort(int[] arr){
        for(int i=(arr.length-1)/2;i>=0;i--){
            shiftDown(arr,i,arr.length);
        }
    }
    public static void heapSort(int[] arr){
        MySort(arr);
        int end=arr.length-1;
        while(end>0){
            swap(arr,0,end);
            shiftDown(arr,0,end);
            end--;
        }
    }
七、冒泡排序
  1. 时间复杂度:O(n²)。
  2. 空间复杂度:O(1)。
  3. 两两比较,最终将数组最大元素放在最后位置。
  4. 调整边界,因上次循环结束后最后以为已是有序,每次比较长度-1。
  5. 若一次循环下来,没有任何数据交换,此时证明当前数据集已经有序,可以直接结束循环。
public static void bubbleSort(int[] arr){
        for(int i=0;i 
八、快速排序(挖坑) 
  1. 时间复杂度:O(logn)。
  2. 空间复杂度:O(logn)。
  3. 顾名思义,选择一个基准值,将小于基准值大放到基准值左,大于基准值放在右。
public static int partition(int[] arr,int start,int end){
        int tmp=arr[start];
        while(start=tmp){
                end--;
            }
            arr[start]=arr[end];
            while(start=right){
            return;
        }
        int pivot=partition(arr,left,right);
        quickSorts(arr,left,pivot-1);
        quickSorts(arr,pivot+1,right);
    }
    public static void quickSort(int[] arr){
        quickSorts(arr,0,arr.length-1);
    }
九、快速排序(Hoare)
  1. 时间复杂度:O(logn)。
  2. 空间复杂度:O(logn)。
  3. 思想于挖坑法大致相同,此方法只是将每次的大于基准值与小于基准值同时交换。
public static int partition(int[] arr,int start,int end){
        int i=start;
        int j=end;
        int tmp=arr[i];
        while(i=tmp){
                j--;
            }
            while(i=right){
            return;
        }
        int pivot=partition(arr,left,right);
        quickSorts(arr,left,pivot-1);
        quickSorts(arr,pivot+1,right);
    }
    public static void quickSort(int[] arr){
        quickSorts(arr,0,arr.length-1);
    }
十、快速排序(非递归)
  1. 时间复杂度:O(logn)。
  2. 空间复杂度:O(logn)。
  3. 非递归思想需要借助一个栈来记录基准值左右的下标。
  4. 代码运行流程与递归无太大差别。
public static int partition(int[] arr,int start,int end){
        int tmp=arr[start];
        while(start=tmp){
                end--;
            }
            arr[start]=arr[end];
            while(start stack=new Stack<>();
        int pivot=partition(arr,left,right);
        if(left+1pivot){
            stack.add(pivot+1);
            stack.add(right);
        }
        while(!stack.isEmpty()){
            right=stack.pop();
            left=stack.pop();
            pivot=partition(arr,left,right);
            if(left+1pivot){
                stack.add(pivot+1);
                stack.add(right);
            }
        }
    }
十一、归并排序(递归)
  1. 时间复杂度:O(n logn)。
  2. 空间复杂度:O(n)。
  3. 把一个大问题拆分成一个一个的小问题,把每一个小问题都排序好,再组合。
public static void merge(int[] arr,int low,int mid,int high,int[] tmp){
        int i = 0;
        int j = low,k = mid+1; 
        while(j <= mid && k <= high){
            if(arr[j] < arr[k]){
                tmp[i++] = arr[j++];
            }else{
                tmp[i++] = arr[k++];
            }
        }
        while(j <= mid){
            tmp[i++] = arr[j++];
        }

        while(k <= high){
            tmp[i++] = arr[k++];
        }

        for(int t=0;t 
十二、归并排序(非递归) 
  1. 时间复杂度:O(nlogn)。
  2. 空间复杂度:O(n)。
  3. 控制好边界就好。
public static void mergeSorts(int[] arr,int gap){
        int s1=0;
        int e1=s1+gap-1;
        int s2=e1+1;
        int e2=Math.min(arr.length-1,s2+gap-1);
        int[] tmp=new int[arr.length];
        int k=0;
        while(s2
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/346200.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号