常见排序算法基本原理、步骤及代码(含注释java版),小白也能看的懂!

本文所有排序均为从小到大排序,代码全部可跑通。

冒泡排序

思想:
依次比较相邻的两个数,小数在前,大数在后,每一轮最大的数都会放到数组最后。
步骤:
1、比较相邻的元素,如果第一个比第二个大,就交换。
2、对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对。
3、除了最后一个元素,所有的元素重复步骤1、步骤2,排序完成。
代码:

	public static void bubbleSort(int array[]){
        int t = 0; //用作交换
        for(int i = 0; i < array.length; i++){
            //每轮相邻两个做比较,最后一个不用比
            for(int j = 0; j < array.length-1; j++){
                //如果前一个比后一个大,则交换
                if(array[j] > array[j+1]){
                    t = array[j];
                    array[j] = array[j+1];
                    array[j+1] = t;
                }
            }
        }
    }

选择排序

思想:
每一轮找出最小的一个元素,与当前值交换,直到遍历结束。
步骤:
1、遍历数组,从当前值右边数组中找出一个最小值与当前值交换。
2、重复步骤1直至最后一个元素,排序完成。
代码:

    public static void selectSort(int array[]){
        int t = 0; //用于交换,默认第一个
        for(int i = 0; i < array.length; i++){
            int index = i;//存放当前值的下标
            //遍历当前值右边的数组,找出最小值
            for(int j = i+1; j < array.length; j++){
                //找到最小值的下标
                if(array[index] > array[j]) {
                    index = j;
                }
            }
            //若找到本轮最小值,则与当前值交换
            if(index != i){
                t = array[i];
                array[i] = array[index];
                array[index] = t;
            }
        }
    }

插入排序

思想:
每一步将一个待排序的数据插入到前面已经排好序的有序序列中,直到插完所有元素为止。
步骤:
1、从第二个元素开始遍历待排序数组。
2、当前元素与左边的每个元素从后到前依次进行比较。
3、若当前元素大,则不动;若当前元素小,则继续向前比较,直到遇到更小的元素时停下并插入。
4、步骤1的循环结束,数组排序完成。
代码:

    public static void insertionSort(int arr[]){
        //遍历
        for(int i = 0; i < arr.length; i++){
            //向左边找比它大的数,然后交换
            //一轮循环结束后,相当于把这个数插入到合适的位置了
            for(int j = i; j > 0; j--){
                if(arr[j] < arr[j-1]){
                    int temp = arr[j-1];
                    arr[j-1] = arr[j];
                    arr[j] = temp;
                }
            }
        }
    }

希尔排序

思想:
插入排序的优化排序,对数组先分组,再对分组里的数组进行插入排序,使得排序时间更稳定。
步骤:
1、默认分组数量为数组长度。
2、当前分组数量除以二,作为现在分组数量。
3、对数据进行分组,如数组长度为10,那么数组就被分为五组,每组内数据长度不一定一样。
4、分别对每个分组进行插入排序。
5、重复步骤2~4,当分组数量为1时,进行最后一次插入排序,数组排序完成。
代码:

    public static void shellSort(int arr[]){
        for(int step = arr.length / 2; step > 0; step /= 2){
            for(int i = step; i < arr.length;i++){
                int value = arr[i];
                int j;
                for(j = i - step; j >= 0 && arr[j] > value; j -= step){
                    arr[j + step] = arr[j];
                }
                arr[j + step] = value;
            }
        }
    }

基数排序

思想:
任何数的每个位数只有可能是0~9,也就是10个数,从个位开始到最高位结束。
步骤:
1、准备一个长度为10的二维数组,一维下标也就是0~9。
2、得到待排序数组最高位。
3、遍历数组,从个位开始截取,到最高位结束,将数字放到截取位数对应下标的二维数组中。
4、从二维数组中按顺序取出新的数组。
5、如果数字没有截取到位数,那就是已经排序好的了,循环步骤3~步骤4,直至排序完成。
代码:

public static void basicSort(int a[]){
        int max = 0;
        //找出最大值
        for(int i = 0; i < a.length; i++){
            if(a[i] > max){
                max = a[i];
            }
        }
        //找出最大位数
        int times = 0;
        while(max > 0){
            max = max / 10;
            times ++;
        }
        //创建9个集合,存放对应位数是0到9的数,相当于二维数组
        List<ArrayList> queen = new ArrayList<>();
        for(int i = 0; i < 10; i++){
            ArrayList q = new ArrayList();
            queen.add(q);
        }
        for(int i = 0; i < times; i++){
            for(int j = 0; j < a.length; j++) {
                //取出对应位数,x的值为0~9,放到对应list中
                int x = a[j] % (int) Math.pow(10, i + 1) / (int) Math.pow(10, i);
                ArrayList q = queen.get(x);
                q.add(a[j]);
            }
            int count = 0;
            for(int z = 0; z < 10; z++){
                //先进先出,将list数据从小到大放到数组中
                while (queen.get(z).size() > 0){
                    ArrayList<Integer> c = queen.get(z);
                    a[count] = c.get(0);
                    c.remove(0);
                    count ++;
                }
            }
        }
    }

归并排序

思想:
将一个数组从中间分开,再将左右两个数组分别排序后合并起来。通过递归,最后的两个部分就是两个数,比较大小后交换,层层向上合并即可完成排序。
步骤:
1、取得中间值下标mid
2、对mid左边右边数组分别进行步骤1,直到左边右边各一个数。
3、比较这两个数,如果右边比左边大,就交换。
4、交换完合并这两个数成为一个数组,向上层层合并。
代码:

public static int[] mergeSort(int[] a,int low,int high){
        int mid = (low + high) / 2;
        if(low < high){
            mergeSort(a,low,mid);
            mergeSort(a,mid + 1,high);
            merge(a,low,mid,high);
        }
        return a;
    }
    public static void merge(int[] a,int low,int mid,int high){
        int[] temp = new int[high - low + 1];
        int i = low;
        int j = mid + 1;
        int k = 0;
        while(i <= mid && j <= high){
            if(a[i] < a[j]){
                temp[k++] = a[i++];
            }else{
                temp[k++] = a[j++];
            }
        }
        while (i <= mid){
            temp[k++] = a[i++];
        }
        while(j <= high){
            temp[k++] = a[j++];
        }
        for(int x = 0; x < temp.length; x++){
            a[x+low] = temp[x];
        }
    }

堆排序

思想:
首先需要了解堆的概念,先做出一个大顶堆,再通过顶和底的交换完成排序。
步骤:
1、将数组构建成一个大顶堆。
2、将堆顶与末尾交换,交换后,堆顶元素变到堆底,然后从堆中取出,这个数就是整个堆中的最大值,放到存放排序结果的数组中。
3、重复步骤1和步骤2,最后堆没有了,全部存放到排序数组中,已经是排好序的了。
代码:

public static void adjustHeap(int[] a, int i, int len) {
        int temp, j;
        temp = a[i];
        for (j = 2 * i; j < len; j *= 2) {// 沿关键字较大的孩子结点向下筛选
            if (j < len && a[j] < a[j + 1])
                ++j; // j为关键字中较大记录的下标
            if (temp >= a[j])
                break;
            a[i] = a[j];
            i = j;
        }
        a[i] = temp;
    }

    public static void heapSort(int[] a) {
        int i;
        for (i = a.length / 2 - 1; i >= 0; i--) {// 构建一个大顶堆
            adjustHeap(a, i, a.length - 1);
        }
        for (i = a.length - 1; i >= 0; i--) {// 将堆顶记录和当前未经排序子序列的最后一个记录交换
            int temp = a[0];
            a[0] = a[i];
            a[i] = temp;
            adjustHeap(a, 0, i - 1);// 将a中前i-1个记录重新调整为大顶堆
        }
    }

快速排序

思想:
选举一个数,使得左边都比它小,右边都比它大,重复直至排序完成。
步骤:
1、在数组中随机选一个数作A。
2、有两个指针,L,R分别指向除去A后的数组头和尾。
3、L指针向右移动,如果L指针指向的数比A大,则R指针向左移动。
4、如果R指针指向的数比A小,交换L,R两个指针所指向的数。
5、交换后,L,R指针位置不变,继续重复3、4步骤,直至LR指针重合。
6、将A与LR指针重合指向的数交换,这样不论是否有序,A左边的数都比A小,右边的数都比A大。
7、将A左边的数组,和右边的数组分别循环进行步骤1~步骤6,退出循环的条件是数组左边只有一个数。
代码:

 public static void quickSort(int[] arr,int low,int high) {
        int i, j, temp, t;
        //全部都进行过一轮了
        if (low > high) {
            return;
        }
        //一个指针指向低位,一个指向高位
        i = low;
        j = high;
        //temp就是标定比大小的数
        temp = arr[low];
        while (i < j) {
            //从右往左找到比标定数小的
            while (temp <= arr[j] && i < j) {
                j--;
            }
            //从左往右找到比标定数大的
            while (temp >= arr[i] && i < j) {
                i++;
            }
            //交换这两个数
            if (i < j) {
                t = arr[j];
                arr[j] = arr[i];
                arr[i] = t;
            }
        }
        //左右两个指针重合了,也就是i = j了
        //将标定数插入到重合位置,就是相当于交换位置
        arr[low] = arr[i];
        arr[i] = temp;
        //这样arr[i]左边都比它小,右边都比它大
        //递归调用左半数组
        quickSort(arr, low, j - 1);
        //递归调用右半数组
        quickSort(arr, j + 1, high);
    }

创作不易,不管看没看得懂,先点个赞呗~

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值