七大常见排序算法

1.直接插入排序

1.1思路

直接插入排序是以当前节点为起始点,向前遍历,并找到自己自己预期的位置。

1.2代码实现

package sort;

import java.util.Arrays;

/**
 * Created with IntelliJ IDEA.
 * Description:直接插入排序
 * User:吴博
 * Date:2021 06 20
 * Time:13:39
 */
public class DirectInsertionSort {
    public static void main(String[] args) {
        int[] num = {1,2,3,4,5,6,7,8,9};
        func(num);
        System.out.println(Arrays.toString(num));
    }
    //直接插入排序(从大到小)
    public static void func(int[] arr){
        //从下标为1的元素开始,因为我们要往前插入我们选定大小的值
        for (int i = 1; i < arr.length; i++) {
            int tmp = arr[i];
            int j = i - 1;
            for (; j  >= 0; j--) {
                //我们实现从大到小的排序
                //所以每次比较i和j位置的值,将大值放到j位置
                //修改此位置“<”,“>”可以改变排序的顺序
                if(tmp < arr[j]){
                    //j + 1的位置就是i的位置
                    //每次都时两两交换
                    arr[j + 1] = arr[j];
                }else{
                    //因为直接插入排序是一次一次插入的,所以一旦发现两个位置的大小顺序是对的,那就说明在此之前的大小顺序都是对的
                    break;
                }
            }
            //将tmp放入j + 1的位置,因为是j的位置是最后一个比他小的值,判断完后循环退出,所以要放在j+1的位置
            arr[j + 1] = tmp;
        }
    }
}

1.3复杂度分析

时间复杂福空间复杂度
最好平均最坏
O(1)O(n^2)O(n^2)O(1)
数据有序数据逆序

1.4稳定性

直接插入排序是稳定的排序

2.希尔排序

2.1思路

希尔排序与直接插入排序很像,只不过希尔排序使用了增量数组,意义是在指定的长度内调整数组,使数组逐渐趋于有序。
具体来说:先选定一个整数,把待排序文件中所有记录分成个组,所有距离为的记录分在同一组内,并对每一组内的记录进行排序。然后,取,重复上述分组和排序的工作,当到达=1时,所有记录在统一组内排好序。

  1. 希尔排序是对直接插入排序的优化。
  2. 当gap > 1时都是预排序,目的是让数组更接近于有序。当gap == 1时,数组已经接近有序的了,这样就会很快。这样整体而言,可以达到优化的效果。我们实现后可以进行性能测试的对比。
    在这里插入图片描述

2.2代码实现

package sort;

import java.util.Arrays;

/**
 * Created with IntelliJ IDEA.
 * Description:希尔排序
 * User:吴博
 * Date:2021 06 20
 * Time:14:15
 */
public class ShellSort {
    public static void main(String[] args) {
        int[] num = {1,2,3,4,5,6,7,8,9};
        func(num);
        System.out.println(Arrays.toString(num));
    }
    //希尔排序
    public static void func(int[] arr){
        //定义增量数组,最后一个元素必须是1
        int[] group = {5,3,1};
        for (int i = 0; i < group.length; i++) {
            shellSort(arr,group[i]);
        }
    }
    //希尔排序中的直接插入排序操作
    private static void shellSort(int[] arr, int group) {
        for (int i = group; i < arr.length; i++) {
            int tmp = arr[i];
            int j = i - group;
            for(; j >=0 ;j = j - group){
                if(tmp < arr[j]){
                    //比他小的元素后移
                    arr[j + group] = arr[j];
                }else {
                    break;
                }
            }
            //将大的元素插入到预期的位置
            arr[j + group] = tmp;
        }
    }
}

2.3复杂度分析

时间复杂福空间复杂度
最好平均最坏
O(n)O(n^1.3)O(n^2)O(1)
数据有序比较难构造(增量数组)

2.4稳定性

希尔排序是不稳定的,因为出现了跳跃式的交换。

3.直接选择排序

3.1思路

直接选择排序是遍历数组以当前元素的位置为起点,寻找之后元素中的最大值,并将其与该位置为的元素交换,每一个位置都重复此操作。

3.2代码实现

package sort;

import java.util.Arrays;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User:吴博
 * Date:2021 06 20
 * Time:14:31
 */
public class SelectSort {
    public static void main(String[] args) {
        int[] num = {1,2,3,4,5,6,7,8,9};
        func(num);
        System.out.println(Arrays.toString(num));
    }
    //直接选择排序(每次从后面选择最大的值放入当前位置)
    public static void func(int[] arr) {
        for (int i = 0; i < arr.length; i++) {
            //每次从当前位置,往后去找到最大值放入当前位置
            for (int j = i; j < arr.length; j++) {
                if(arr[i] < arr[j]){
                    int tmp = arr[i];
                    arr[i] = arr[j];
                    arr[j] = tmp;
                }
            }
        }
    }
}

3.3复杂度分析

时间复杂度空间复杂度
O(n^2)O(1)
数据不敏感数据不敏感

3.4稳定性

直接选择排序是不稳定的,发生了跳跃式的交换。

4.冒泡排序

4.1思路

冒泡排序以从大到小举例,是两两交换,将大的元素往前移,小的元素往后移,一次循环过后,可以确定最后一个元素的位置,下次循环可以确定倒数第二个元素的位置,依次类推,所以需要循环数组长度/数组长度-1次,为什么二者都可以,因为最后一次循环判断是无效的,前面的所有循环已经将除了第一个元素外的所有元素都排序好了,剩下的最后一不用调整了,只剩他,他肯定就在那个位置。

4.2代码实现

package sort;

import java.util.Arrays;

/**
 * Created with IntelliJ IDEA.
 * Description:冒泡排序(从大到小)
 * User:吴博
 * Date:2021 06 20
 * Time:15:58
 */
public class BubbleSort {
    public static void main(String[] args) {
        int[] num = {1,2,3,4,5,6,7,8,9};
        func1(num);
        System.out.println(Arrays.toString(num));
    }
    //冒泡排序优化
    public static void func1(int[] arr){
        //大的循环,保证每个为位置都被判断过
        //这里i的最终值可以为arr.length - 1,可以少判断一次,因为最后一次只判断第一个和第二个元素,经过前面一步调整,他俩是有序的,所以可以省略最后一次
        for (int i = 0; i < arr.length; i++) {
            //内部循环,进行优化,减少判断元素的个数
            //因为每经过一次大循环都会确认一个元素的位置,第一次为最后一个,第二次为倒数第二个,以此类推
            //每次都会使判断数组长度-1,都会将一个在指定数组长度中最小的值放入正确的位置
            for (int j = 0; j < arr.length - i - 1; j++) {
                //注意这里可控制元素的下标一定是j不是i,i知识控制循环次数的
                if(arr[j] < arr[j + 1]){
                    int tmp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = tmp;
                }
            }
        }
    }

    //冒泡排序
    public static void func(int[] arr) {
        //最多循环count次就绝对有序
        int count = arr.length - 1;
        //每经过一次while循环都会有一个最小的元素的确认它的位置,第一次确认最后一个,第二次确认倒数第二个
        while(count-- != 0){
            for (int i = 0; i < arr.length - 1; i++) {
                //如果当前元素小于它的下一个元素,则交换位置,保证较大的元素都放在前面
                if(arr[i] < arr[i + 1]){
                    int tmp = arr[i];
                    arr[i] = arr[i + 1];
                    arr[i + 1] = tmp;
                }
            }
        }
    }
}

4.3复杂度

时间复杂福空间复杂度
最好平均最坏
O(n)O(n^2)O(n^2)O(1)
数据有序数据逆序

4.4稳定性

冒泡排序是稳定的排序。

5.堆排序

5.1思路

用到向下调整

5.2代码实现

package sort;

import java.util.Arrays;

/**
 * Created with IntelliJ IDEA.
 * Description:堆排序(升序建立大堆,降序建立小堆)
 * User:吴博
 * Date:2021 06 20
 * Time:16:31
 */
public class HeapSort {
    static int[] arr;
    static int heapSize = 0;

    public static void main(String[] args) {
        HeapSort sort = new HeapSort();
        int[] num = {27,15,19,18,28,34,65,49,25,37};
        createHeap(num);
        heapSort(num);
        show();
    }

    public static void heapSort(int[] num){
        int end = arr.length - 1;
        while(end > 0){
            //交换首尾元素
            int tmp = arr[0];
            arr[0] = arr[end];
            arr[end] = tmp;
            adjustDown(0,end);
            end--;
        }
    }

    //向下调整,建立小堆,走升序
    public static void adjustDown(int parent,int heapSize){
        int child = 2 * parent + 1;
        while(child < heapSize){
            if(child + 1 < heapSize && arr[child] > arr[child + 1]){
                child++;
            }
            if(arr[parent] > arr[child]){
                int tmp = arr[parent];
                arr[parent] = arr[child];
                arr[child] = tmp;
                parent = child;
                child = 2 * parent + 1;
            }else {
                break;
            }
        }
    }

    //初始化堆:先将数组数据存入arr,在进行向下调整
    public static void createHeap(int[] num){
        for (int i = 0; i < num.length; i++) {
            arr[i] = num[i];
            heapSize++;
        }
        //进行向下调整
        for (int i = (heapSize - 1 - 1 ) / 2; i >= 0; i--){
            //从最后一个结点的父节点算起,一个一个的调整
            adjustDown(i,heapSize);
        }
    }
    //打印堆
    public static void show(){
        System.out.println(Arrays.toString(arr));
    }
    //初始化
    public HeapSort(){
        arr = new int[10];
    }
    //判断是否空
    public boolean isEmpty(){
        return heapSize == 0;
    }
    //判断是否满
    public boolean ifFull(){
        return arr.length == heapSize;
    }
}

5.3复杂度分析

时间复杂度空间复杂度
O(n*log(n))O(1)
数据不敏感数据不敏感

5.4稳定性

堆排序是不稳定的。

6.快速选择排序

6.1思路

6.2代码实现

package sort;

import java.util.Arrays;

/**
 * Created with IntelliJ IDEA.
 * Description:快速排序(从大到小)
 * User:吴博
 * Date:2021 06 20
 * Time:17:49
 */
public class QuickSort {
    public static void main(String[] args) {
        int[] num = {1,2,3,4,5,6,7,8,9};
        quickSort(num);
        System.out.println(Arrays.toString(num));
    }

    private static void quickSort(int[] num) {
        quick(num,0,num.length - 1);
    }

    private static void quick(int[] num, int qStart, int qEnd) {
        if(qStart < qEnd){
            //找基准,找到后说明piv位置就确定了,不用去调整了,接下来去调整基准的左右(分别再找其左右递归实现)
            int piv = pivot(num,qStart,qEnd);
            //找左边的基准
            quick(num,qStart,piv - 1);
            //找右边的基准
            quick(num,piv + 1,qEnd);
        }
    }

    private static int pivot(int[] num, int start, int end) {
        //记录初始值
        int tmp = num[start];
        //只要start<end就一直走
        while(start < end){
            //保证下标合法的前提下,实现升序,从后找比tmp大的值
            while(start < end && num[end] <= tmp){
                end--;
            }
            //找到后将其赋值到start位置
            num[start] = num[end];
            保证下标合法的前提下,实现升序,从前找比tmp小的值
            while(start < end && num[start] >= tmp){
                start++;
            }
            //end
            num[end] = num[start];
        }
        //循环结束说明,start与end相遇了。这个位置就是tmp应该放的位置。
        num[start] = tmp;
        return start;
    }
}

6.3复杂度分析

时间复杂度空间复杂度
最好平均最坏最好平均最坏
O(n * log(n))O(n * log(n))O(n^2)O(log(n))O(log(n))O(n)

6.4稳定性

快排是不稳定的。

7.归并排序

7.1代码实现

package sort;

import java.util.Arrays;

/**
 * Created with IntelliJ IDEA.
 * Description:归并排序
 * User:吴博
 * Date:2021 06 20
 * Time:18:29
 */
public class MergeSort {
    public static void main(String[] args) {
        int[] arr = {4,5,2,1,3,9,8,7,6};
        mergeSort(arr);
        System.out.println(Arrays.toString(arr));
    }

    public static void merge(int[] array , int start , int mid , int end){
        int[] tmp = new int[end - start + 1];
        int k = 0;
        int s1 = start;
        int e1 = mid ;
        int s2 = mid + 1;
        int e2= end;
        while(s1 <= e1 && s2 <= e2){
            if(array[s1] <= array[s2]) {
                tmp[k++] = array[s1++];
            }else{
                tmp[k++] = array[s2++];
            }
        }
        while(s1 <= e1){
            tmp[k++] = array[s1++];
        }
        while (s2 <= e2){
            tmp[k++] = array[s2++];
        }

        for(int i = 0 ;i < tmp.length ; i++){
            array[i + start] = tmp[i];
        }
    }

    public static void mergeSortRec(int[] array , int start , int end ){
        if(start >= end){
            return;
        }
        int mid = (start + end)/2;
        mergeSortRec(array , start , mid);
        mergeSortRec(array , mid+1 , end);
        merge(array , start , mid , end);
    }

    public static void mergeSort(int[] array){
        mergeSortRec(array , 0 , array.length-1);
    }
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值