十种常见排序算法详解-java

排序算法


排序算法的稳定性
稳定性: 两个相等的数据排序前后,保持相对位置不变,该排序算法具有稳定性
稳定的可以变成不稳定的,不稳定的不能变成稳定的
快速判断:如果发生了跳跃式的交换就是不稳定的排序算法

插入排序
时间复杂度 O(n^2) 最好O(n),越有序,排的越快.
空间复杂度O(1)
稳定,但可以变成不稳定
原理:将前一个数保存在一个临时变量中,并与后面的所有的数相比较,最后找到合适的位置插入.

    public static void insertSort(int[] arr){
        for(int i = 1;i < arr.length;i++){
            int tmp = arr[i];
            int j = i-1;
            for(;j >= 0;j--){
                if(arr[j] > tmp){
                    arr[j+1] = arr[j];
                }else{
                    break;
                }
            }
            arr[j+1] = tmp;
        }
    }

希尔排序
时间复杂度:[和增量有关系]😮(n^1.3~n&1.5)
空间复杂度O(1)
不稳定
原理: 是对插入排序的升级,将所排序的所有元素进行均匀分组,对每组进行排序,可以选择跳跃分组,利用选择排序对每个分组进行排序,最后将每个元素进行分组,即整体进行选择排序.

public static void shellSort(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;
        }
    }

选择排序
时间复杂度O(n^2)
空间复杂度O(1)
不稳定
原理:每一次从无序区间选出最大(或最小)的一个元素,存放在无序区间的最后(或最前),直到全部待排序的数据元素
排完 .

    public static void main(String[] args){
        int[] arr = {6, 5, 1, 3, 2, 4, 8, 7, 9};
//        selectSort(arr);
//        System.out.println(Arrays.toString(arr));


        selectSort2(arr);
        System.out.println(Arrays.toString(arr));
    }

    public static void selectSort(int[] arr){
        for(int i = 0;i < arr.length;i++){
            for(int j = i+1;j <arr.length;j++){
                if(arr[i] > arr[j]){
                    swap(arr,i,j);
                }
            }
        }
    }

    public static void selectSort2(int[] arr){
        for(int i = 0 ;i< arr.length;i++){
            int minIndex = i;
            for(int j=i+1;j <arr.length;j++){
                if(arr[minIndex] > arr[j]){
                    minIndex = j;
                }
            }
            swap(arr,i,minIndex);
        }
    }

    public static void swap(int[] arr,int i,int j){
        int tmp = arr[i];
        arr[i] = arr[j];
        arr[j] = tmp;
    }

堆排序
时间复杂度O(n*logn)
空间复杂度O(1)
不稳定
原理:先将数组变为一个大根堆,再将数组的首尾元素交换(实际是将大根堆的最大元素与末尾元素交换),最后去除末尾最大元素占用数组的长度后向下调整,将除最后一个元素的数组变为大根堆,如此反复,直到最后一个元素.

public class Demo {
    public static void main(String[] args){
        int[] arr = {6,5,1,3,2,4,8,7,9};
        //建堆
        createHeap(arr);
        //排序
        headSort(arr);
        System.out.println(Arrays.toString(arr));
    }

    public static void createHeap(int[] arr){
        for(int parent = (arr.length - 1 -1)/2;parent >= 0;parent--){
            shiftDown(arr,parent,arr.length);
        }
    }

    public static void shiftDown(int[] arr,int parent,int len){
        int child = parent * 2 + 1;
        while(child < len){
            if(child +1 < len && arr[child] <arr[child+1]){
                child++;
            }
            if(arr[child] > arr[parent]){
                swap(arr,child,parent);
                parent = child;
                child = parent * 2 + 1;
            }else{
                break;
            }
        }
    }

    public static void swap(int[] arr,int i,int j){
        int tmp = arr[i];
        arr[i] = arr[j];
        arr[j] = tmp;
    }

    public static void headSort(int[] arr){
        int end = arr.length-1;
        while(end > 0){
             swap(arr,end,0);
             shiftDown(arr,0,end);
             end--;
        }
    }
}

冒泡排序
时间复杂度O(n^2),平均也是
空间复杂度O(1)
稳定排序
原理:每一次排序都将最大的一个数放到最后面(bubbleSort),优化(bubbleSort):但第二个for循环不进行交换是即已经排序完成.

public class Demo {
    public static void main(String[] args){
        int[] arr = {6, 5, 1, 3, 2, 4, 8, 7, 9};
//        bubbleSort(arr);
        bubbleSort2(arr);
        System.out.println(Arrays.toString(arr));
    }

    public static void bubbleSort(int[] arr){
        for(int i = 0 ;i <arr.length;i++){
            for(int j = 0;j < arr.length-1-i;j++){
                if(arr[j] > arr[j+1]){
                    swap(arr,j,j+1);
                }
            }
        }
    }

    public static void bubbleSort2(int[] arr){
        for(int i = 0 ;i <arr.length;i++){
            boolean key = true;
            for(int j = 0;j < arr.length-1-i;j++){
                if(arr[j] > arr[j+1]){
                    swap(arr,j,j+1);
                    key = false;
                }
            }
            if(key){
                break;
            }
        }
    }
    public static void swap(int[] arr,int i,int j){
        int tmp = arr[i];
        arr[i] = arr[j];
        arr[j] = tmp;
    }
}

快速排序:
时间复杂度O(n * log(n))
空间复杂度O(log(n))
不稳定.
原理:在数组中取一个数为基准,比基准值小的放到基准值的左边,将比基准值大的放到基准值的右边,对左右两个小区间按照同样的方式处理,直到小区间的长度 == 1,代表已经有序.

递归法:

public class Demo {
    public static void main(String[] args){
        int[] arr = {6, 5, 1, 3, 2, 4, 8, 7, 9};
        quickSort(arr,0,arr.length-1);
        System.out.println(Arrays.toString(arr));
    }
    public static void quickSort(int[] arr,int left,int right){
        if(left > right){
            return;
        }

        //优化2:当数据区间小于某个数据时,可以使用插排优化,插排数据越有序越快
        if(right -left < 140){
            //此时直接使用插排
            for(int i = left+1;i < right;i++){
                int tmp = arr[i];
                int j = i-1;
                for(;j >= 0;j--){
                    if(arr[j] > tmp){
                        arr[j+1] = arr[j];
                    }else{
                        break;
                    }
                }
                arr[j+1] = tmp;
            }
        }

        //优化1:三数取中
        int midMaxIndex = findMidMaxIndex(arr,left,right);
        swap(arr,left,right);
        int pivot = partition(arr,left,right);
        quickSort(arr,left,pivot-1);
        quickSort(arr,pivot+1,right);
    }

    private static int findMidMaxIndex(int[] arr, int left, int right) {
        int mid = left + ((right - left) >>> 1);
        int tmp = arr[left] > arr[right] ? left : right;
        return arr[left] > arr[mid] ? left : mid;
    }

    private static int partition(int[] arr, int left, int right) {
        int tmp = arr[left];
        while(left < right){
            while(left < right && arr[right] >= tmp){
                right--;
            }
            arr[left] = arr[right];

            while(left < right && arr[left] <= tmp){
                left++;
            }
            arr[right] = arr[left];
        }
        arr[right] = tmp;
        return right;
    }
    public static void swap(int[] array, int i, int j) {
        int t = array[i];
        array[i] = array[j];
        array[j] = t;
    }
}

非递归法:

public class Demo2 {
    public static void main(String[] args){
        int[] arr = {6,5,1,3,2,4,8,7,9};
        quick2(arr,0,arr.length-1);
        System.out.println(Arrays.toString(arr));
    }

    public static void quick2(int[] arr,int left,int right){
        Stack<Integer> stack = new Stack();
        int pivot = partition(arr,left,right);
        if(pivot > left + 1){
            stack.push(left);
            stack.push(pivot - 1);
        }
        if(pivot < right-1 ){
            stack.push(pivot + 1);
            stack.push(right);
        }

        while(!stack.isEmpty()){
            right = stack.pop();
            left = stack.pop();
            pivot = partition(arr,left,right);
            if(pivot > left + 1){
                stack.push(left);
                stack.push(pivot - 1);
            }
            if(pivot < right-1 ){
                stack.push(pivot + 1);
                stack.push(right);
            }
        }
    }

    public static int partition(int[] arr,int left,int right){
        int tmp = arr[left];
        while(left < right){
            while(left <right && arr[right] >= tmp){
                right--;
            }
            arr[left] = arr[right];
            while(left < right && arr[left] <= tmp){
                left++;
            }
            arr[right] = arr[left];
        }
        arr[left] = tmp;
        return left;
    }
}

归并排序
时间复杂度:O(n * log(n))
空间复杂度:O(n)
稳定
原理:将数组中的元素拆分成多个小块,对每个小块进行单独排序,最后将有序小块合并为整个有序数组
递归法:

public class Demo {
    public static void main(String[] args){
        int[] arr = {6, 5, 1, 3, 2, 4, 8, 7, 9,10};
        mergeSort(arr,0,arr.length-1);
        System.out.println(Arrays.toString(arr));
    }

    public static void mergeSort(int[] arr,int left,int right){
        if(left >= right){
            return;
        }
        int mid = left + ((right - left) >> 1);
        mergeSort(arr,left,mid);
        mergeSort(arr,mid + 1,right);
        merge(arr,left,mid,right);
    }

    public static void merge(int[] arr,int left,int mid,int right){
        int[] tmp = new int[right - left + 1];
        int k = 0;

        int s1 = left;
        int e1 = mid;

        int s2 = mid + 1;
        int e2 = right;

        while(s1 <= e1 && s2 <= e2){
            if(arr[s1] < arr[s2]){
                tmp[k++] = arr[s1++];
            }else{
                tmp[k++] = arr[s2++];
            }
        }

        while(s1 <= e1){
            tmp[k++] = arr[s1++];
        }

        while(s2 <= e2){
            tmp[k++] = arr[s2++];
        }

        for(int i = 0;i < k;i++){
            arr[i + left] = tmp[i];
        }
    }
}
  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Java排序算法是用于对一系列数据进行排列顺序的一种算法。在Java常见排序算法包括冒泡排序、选择排序、插入排序、快速排序、归并排序等。 冒泡排序是一种比较简单的排序算法,它通过对相邻的元素进行比较和交换来实现排序。该算法时间复杂度为O(n^2),属于比较低效的排序算法。选择排序是一种简单直观的排序算法,它通过选择最小的元素并放置在已排序的部分来实现排序。该算法时间复杂度也是O(n^2)。 插入排序是一种比较高效的排序算法,它通过将未排序的元素插入到已排序的部分来实现排序。该算法时间复杂度也是O(n^2)。快速排序是一种递归的排序算法,它通过选取一个基准值来对数组进行分区,并对每个分区进行排序来实现最终的排序。该算法时间复杂度为O(nlogn),是比较高效的排序算法之一。 归并排序是一种分治的排序算法,它将数组分成两个子数组,并对每个子数组进行排序,最后将两个子数组合并成一个有序数组。该算法时间复杂度也是O(nlogn)。在实际应用,我们通常会选择合适的排序算法来应对不同的排序需求,比如对于小规模数据可以选择简单的排序算法,对于大规模数据可以选择高效的排序算法。总之,了解Java排序算法的原理和性能表现对于编程人员来说是非常重要的。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值