[算法基础] 一、排序算法总结

package com.sort;

import java.util.Arrays;

public class sortAll {
    
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        int[] arr = {26,47,50,2,3,46,47,38,5,15,19,44,4,27,36};
        //insertSort(arr);
        binaryInsertSort(arr);
        //selectSort(arr);
        //bubbleSort(arr);
        //shellSort(arr);
        //mergeSort(arr,0,arr.length-1);
        //quickSort(arr,0,arr.length-1);
        //arr = heapSort(arr);
        System.out.println(Arrays.toString(arr));
    }
    //===================================插入类排序================================================
    //==========================================================================================
    //直接插入排序
    public static void insertSort(int[] arr){
        for(int i = 1; i<arr.length; i++){ //第一个元素当做有序  从第二个元素开始进行插入 
            for(int j = i-1; j>=0; j--){ //每个元素依次 与其前面 有序的元素 进行比较   小于则交换
                if(arr[j] > arr[j+1]){  //这里  注意要用j+1 而不是i 因为我们跟踪 i的位置  需要用j来表示
                    int temp = arr[j+1];
                    arr[j+1] = arr[j];
                    arr[j] = temp;
                    //因为每次的插入都是有序数组  所以 在查找位置的时候 可以采用 折半查找   ----即 折半插入排序
                }
            }
        }
        System.out.print("直接插入排序: ");
    }
    //==========================================================================================
    //折半插入排序
    public static void binaryInsertSort(int[] arr){
        
        for(int i =1; i<arr.length; i++){
            int temp = arr[i]; //待插入的元素
            int low = 0; //折半查找的首尾
            int high = i-1;
            //折半查找
            while(low<=high){
                int mid = (low+high)/2;
                if(temp > arr[mid]){
                    low = mid +1;
                }else{
                    high = mid -1;
                }
            }
            //移动位置 空出待插入位置
            for(int j = i; j>low; j--){ //通过折半查找 low == high 即为待插入位置
                arr[j] = arr[j-1];
            }
            arr[low] = temp;//将元素放入最终位置
        }
        System.out.print("折半插入排序: ");
    }
    //==========================================================================================
    // 希尔排序--缩小增量排序
    public static void shellSort(int[] arr) {
        int n = arr.length;
        for (int h = n / 2; h > 0; h = h / 2) {  //其实就是在直接插入排序外边    将增量1  变为h
            // 内部是一个直接插入排序
            for (int i = h; i < n; i = i + h) {
                for (int j = i-h; j >= 0; j = j - h) {
                    if (arr[j] > arr[j+h]){
                        int temp = arr[j];
                        arr[j] = arr[j+h];
                        arr[j+h] = temp;
                    }
                }
            }
        }
        System.out.print("嘟嘟希尔排序: ");
    }
    //===================================交换类排序================================================
    //==========================================================================================
    //冒泡排序
    public static void bubbleSort(int[] arr){
        for(int i = 0; i< arr.length- 1; i++){ //第一个for循环表示的是循环轮数  最后一个元素不需要再进行循环轮次
            for(int j = 0; j< arr.length-1-i; j++){//从索引0开始,依次两两相比较 最后一个元素不需要  而且每经过一轮  就会有个元素达到最终位置 所以  是 arr.length-1-i
                if(arr[j]> arr [j+1]){//依次向后冒泡
                    int temp = arr[j];
                    arr[j] = arr[j+1];
                    arr[j+1] = temp;
                }
            }
        }
        System.out.print("嘟嘟冒泡排序: ");
    }
    //==========================================================================================
    //快速排序 
    public static void quickSort(int[] arr, int low, int high){
        int i = low;
        int j = high;
        int temp = 0;
        //一轮快速排序
        if(low<high){
            temp = arr[low];//
            while(i!=j){
                while(i<j && arr[j]>temp){//从右往左找到一个比temp小的值
                    j--;
                }
                if(i<j){ 
                    arr[i] = arr[j];//将该值放到temp左边zzzzzzzzzzzzzzzzzzzzzzl
                    i++;
                }
                while(i<j && arr[i]<temp){//从左往右找到一个比temp大的值
                    i++;
                }
                if(i<j){
                    arr[j] = arr[i];//将该值放到temp右边
                    j--;
                }
            }
            arr[i] = temp; //将temp放入最终位置
            //迭代中心点左右两边的序列
            quickSort(arr, low, i-1);
            quickSort(arr, i+1, high);
        }
        //只是为了仅仅打印一次这句话  与快速排序无关
        if(low==2){
            System.out.print("嘟嘟快速排序: ");
        }
    }
    //===================================选择类排序================================================
    //==========================================================================================
    //直接选择排序
    public static void selectSort(int[] arr){
        for(int i =0; i<arr.length-1; i++){ //从第一个元素开始 依次与后面所有元素 比较 选出最小的进行交换位置
            int minIndex = i;
            for(int j = i+1; j<arr.length; j++){
                if(arr[minIndex] > arr[j]){
                    minIndex = j; //当然也可以直接在这里交换 但是这样记录最小坐标 可以减少交换次数  
                }
            }
            int temp = arr[i];
            arr[i] = arr[minIndex];
            arr[minIndex] = temp;
        }
        System.out.print("直接选择排序: ");
    }
    //==========================================================================================
    //堆排序 
    public static int[] heapSort(int[] arr){
        int len = arr.length;
        int[] newarr = rebuildArr(arr); //重构数组 存储位置从索引1开始
        int temp = 0;
        for(int i = len/2; i>=1;--i){//建立初始堆 i= len/2 是第一个不为叶子结点的元素 
            shift(newarr, i, len);
        }
        for(int i=len; i>=2; --i){//进行n-1次循环 完成堆排序  每次循环
            //这三句完成 将堆顶的元素 放到最终位置   ---建立初始堆的时候  根节点已经就是最大的元素了
            temp = newarr[1];
            newarr[1] = newarr[i];
            newarr[i] = temp;
            
            shift(newarr, 1, i-1);//在减少了一个元素的无序序列中进行调整  而且需要调整的只有根节点一个元素
        }
        arr = recArr(newarr);
        System.out.print("嘟嘟嘟堆排序: ");
        return arr;
    }
      //调整位置low上节点的位置  使其满足大顶堆的定义
    public static void shift(int[] arr, int low, int high){
        int i = low;
        int j = 2*i;
        int temp = arr[i];
        while(j<=high){
            if(j<high&&arr[j]<arr[j+1]){//将j指向左右孩子中最大的那个
                j++;
            }
            if(temp<arr[j]){ //如果孩子比较大  就交换位置
                arr[i] = arr[j];
                i=j;
                j=2*i;
            }else{
                break;
            }
        }
        arr[i] = temp;
    }
      //因为堆排序采用的是 平衡二叉树的结构  从索引1开始存储 方便计算  
    public static int[] rebuildArr(int[] arr){
        int[] newarr = new int[arr.length+1];
        for(int i=0; i<arr.length; i++){
            newarr[i+1] = arr[i];
        }
        return newarr;
    }
      //还原数组
    public static int[] recArr(int[] newarr){
        int[] arr = new int[newarr.length-1];
        for(int i=0; i<arr.length; i++){
            arr[i] = newarr[i+1];
        }
        return arr;
    }
    //===================================归并类排序================================================
    //==========================================================================================
    //归并排序  分治策略   二路归并采用迭代的方法, 将每个子段依次进行合并  最终得到一个有序的最终序列
    public static void mergeSort(int[] arr, int low, int high){
        if(low<high){//递归条件
            int mid = (low+high)/2;
            mergeSort(arr, low, mid);
            mergeSort(arr, mid+1, high);
            merge(arr, low, mid, high);
        }
        
        //只是为了仅仅打印一次这句话  与归并排序无关
        if(low==1){
            System.out.print("二路归并排序: ");
        }
    }
    public static void merge(int[] arr, int low, int mid, int high){//合并两路有序序列
        
        int[] temp = arr.clone();//拷贝一个副本用于比较 原来的arr用于存放合并后的序列  所以归并排序的空间复杂度最大
        int i = low, j=mid+1, k=low; //将数组分为前后两段,i指向前半段,j指向后半段,k指向要保存的位置
        //二路比较
        while(i<=mid && j<=high){
            if(temp[i]<temp[j]){
                arr[k++] = temp[i++];
            }else {
                arr[k++] = temp[j++];
            }
        }
        
        while(i<=mid){//如果前半段有剩余  直接加入
            arr[k++] = temp[i++];
        }
        
        while(j<=high){//如果后半段有剩余 直接加入
            arr[k++] = temp[j++];
        }
    }

}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值