2021-05-27 八大排序算法

目录

算法一,冒泡排序:

算法二:选择排序

算法三:插入排序

算法四:希尔排序

算法五:快速排序

算法六: 归并排序

算法七: 基数排序

算法八: 堆排序

八大排序算法对比




算法一,冒泡排序:

特点:第一次排序之后最大的数总是在最后一个,第二次排序除了最后一位最大的数排在倒数第二位

例:

代码实现:

int[] arr = {1,5,-1,-5,6,-8};
        int temp = 0;

        //数组有n个值,只需要循环n-1次
        for (int i = 0; i < (arr.length - 1); i++) {
            boolean flag = false;
            //每次排序之后,最大的数已经在最后,这个数不用参加循环,所以每次循环,次数都要再减1
            for (int j = 0; j < (arr.length - 1 - i); j++) {
                if (arr[j] > arr[j + 1]){
                    //如果进入if则代表有交换
                    flag = true;
                    temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                }
            }
            System.out.println(Arrays.toString(arr));
            if (!flag){
                return;
            }
        }
        System.out.println(Arrays.toString(arr));

算法二:选择排序

特点,每次选择数组中最小的数,和arr[ i ]交换,每一轮排序之后,最小的数总是在最前面

例子:

public static int[] get(int[] arr){
        //一共需要循环数组长度-1次
        for (int i = 0; i < (arr.length - 1); i++) {
            //设置下标为i  因为每到此循环说明已经遍历了一次,原有下标对应的值已经找到
            index = i;
            //假设temp的值都为下标对应的值
            temp = arr[index];
            //i + 1说明不和自身作比较
            for (int j = i + 1; j <= arr.length; j++) {
                if (arr[index] > arr[j]){
                    //如果进入此条件,说明满足交换原则
                    index = j;
                    temp = arr[j];
                }
            }
            //开始交换
            arr[index] = arr[i];
            arr[i] = temp;
            System.out.println(Arrays.toString(arr));
        }
        return arr;
    }

算法三:插入排序

把数组元素分为两个集合,第一个集合为有序,第二个集合为无序,每次从无序中取第一个元素和有序的第一个元素比较,如果大,则比第二个比较,只到遇到一个小于的值,插入。

例子:

代码实现:

int[] arr = {1,5,-1,-5,6,-8};

        for (int i = 1; i < arr.length; i++) {

            //下标,初始值为有序数组的最后一个
            int index = i - 1;
            //定义的最小值,初始值为无序数组的第一个
            int min = arr[i];

            //参数一:防止数组下标越界
            //参数二:如果定义的最小值(无序数组第一个)小于有序数组的最后一个
            while (index >= 0 && min < arr[index]){
                //交换位置
                //例: 1,-1  交换之后成为 1,1
                arr[index + 1] = arr[index];
                index--;
            }
            //赋值,将目标值移到有序数组
            arr[index + 1] = min;
        }
        System.out.println(Arrays.toString(arr));

算法四:希尔排序

通过两次划分,把不同的元素划分为不同的组,最后再合并,即可得到按照顺序排列的数组

例子:

代码实现:

代码之一:交换法

/**
 * 交换法
 */
public class Shell {
    public static void main(String[] args) {
        int[] arr = {8, 9, 1, 7, 2, 3, 5, 4, 6, 0};
        int temp = 0;
        int length = arr.length / 2;

        while (length >= 1){
            for (int i = length; i < arr.length; i++) {
                //由于i是从高位慢慢变向地位,所以当循环时,j -= length表示,从数组下标高的开始,向数组下标低的比较
                for (int j = i - length; j >= 0; j -= length){
                    if (arr[j] > arr[j + length]){
                        temp = arr [j + length];
                        arr[j + length] = arr[j];
                        arr[j] = temp;
                    }
                }
            }
            //每次遍历长度减半
            length = length / 2;
            System.out.println(Arrays.toString(arr));
        }
        System.out.println(Arrays.toString(arr));
    }
}

代码之二,移位法

//移位法
    public int[] shell(int[] arr) {
        int length = arr.length / 2;
        while (length >= 1) {
            for (int i = length; i < arr.length; i++) {
                int j = i;
                int temp = arr[j];
                while (j - i > 0 && temp < arr[j - i]) {
                    //开始移位例: 9,8,7,6,5,4,3,2,1,0  移位之后变成9,8,7,6,5,9,3,2,1,0
                    arr[j] = arr[j - i];
                    //减去步长
                    j = j - i;
                }
                //到这一步就是找到了,将temp的值赋值给最前面的
                //如上一步的数组,复制之后就变成了4,8,7,6,5,9,3,2,1,0
                arr[j] = temp;
            }
            length = length / 2;
        }
        return arr;
    }

算法五:快速排序

选取一个数作为基准,比这个数小的放在左面,比这个数大的放在右面,再以划分的两个数组中的一个数为基准,重复划分。。本质就是递归

图解:

代码实现:

public void quickSort(int[] arr,int left,int right){
        int l =left;
        int r = right;
        int middle = arr[(left + right) / 2];
        int temp = 0;

        while (l < r){
            //如果左边的数小于中间的数,就往前移位,如果不满足这个条件,就是找到了
            while (arr[l] < middle){
                l += 1;
            }
            //如果右边的数小于中间的数,就往后移位,如果不满足这个条件,就是找到了
            while (arr[r] > middle){
                r -= 1;
            }
            //两者相等,说明遍历完
            if (l >= r){
                break;
            }
            temp = arr[l];
            arr[l] = arr[r];
            arr[r] = temp;

            //不会出现死循环(不理解)
            if (arr[l] == middle){
                r -= 1;
            }
            //不会出现死循环(不理解)
            if (arr[r] == middle){
                l += 1;
            }
            System.out.println(Arrays.toString(arr));
        }
        //两者相等,跨过相等的数,继续遍历  不然会出现死循环
        //这里使l++,r--是为了让middle包含进去,如果是l--,r++,则middle不包含在其中
        if (l == r){
            l++;
            r--;
        }
        //向左遍历
        if (left < r){
            quickSort(arr,left,r);
        }
        //向右遍历
        if (right > l){
            quickSort(arr,l,right);
        }

    }

算法六: 归并排序

把排序的数组分为若干个数字,再把这些数字合并为数组。使用了分治算法的思想,然后使用递归算法合并为有顺序的数组

图解:

代码实现:

//代码调用
int[] arr = {8, 4, 5, 7, 1, 3, 6, 2};
int[] temp = new int[arr.length];
GuiBing guiBing = new GuiBing();
guiBing.mergeSort(arr, 0, arr.length - 1, temp);
//分+合的方法
    public void mergeSort(int[] arr, int left, int right, int[] temp) {
        if (left < right) {
            int mid = (left + right) / 2;
            //向左分解
            mergeSort(arr, left, mid, temp);
            //向右分解
            mergeSort(arr, mid + 1, right, temp);
            merge(arr, left, right, mid, temp);
        }
    }

/**
     * 合并的方法
     *
     * @param arr   排序初始数组
     * @param left  左下标
     * @param right 右下标
     * @param mid   中间索引
     * @param temp  中转数组
     */
    public void merge(int[] arr, int left, int right, int mid, int[] temp) {

        int l = left;
        int j = mid + 1;
        int t = 0;  //做temp的索引

        while (l <= mid && j <= right) {
            if (arr[l] <= arr[j]) {
                temp[t] = arr[l];
                t += 1;
                l += 1;
            } else {
                temp[t] = arr[j];
                t += 1;
                j += 1;
            }
        }
        //将还存在arr中的数取出
        while (j <= right) {
            temp[t] = arr[j];
            t += 1;
            j += 1;
        }
        while (l <= mid) {
            temp[t] = arr[l];
            t += 1;
            l += 1;
        }

        //将temp中的数据拷贝到arr中
        int tempLeft = left;
        t = 0;
        while (tempLeft <= right) {
            arr[tempLeft] = temp[t];
            tempLeft += 1;
            t += 1;
        }
        System.out.println(Arrays.toString(arr));
    }

算法七: 基数排序

将待排序数组按照个位从高到低,十位从高到低,百位从高到低。。。的顺序一次放入十个桶中,每个桶有相应的下标。该排序最大循环次数为最大的数的位数。

图解:

代码实现:

public static void main(String[] args) {
        int[] arr = {53, 3, 542, 748, 14, 214};
        sort(arr);
    }

    //算出数组最大值
    public static int max(int[] arr) {
        int max = arr[0];
        for (int i = 0; i < arr.length; i++) {
            if (max < arr[i]) {
                max = arr[i];
            }
        }
        return max;
    }

    //算出最大值的数是几位数
    public static int maxIndex(int max) {
        int index = 0;
        if (max != 0) {
            index++;
            max = max % 10;
        }
        return index;
    }
    public static void sort(int[] sort) {
        //二维数组代表桶  有十个桶
        int[][] arr = new int[10][sort.length];
        //一维数组是记录二位数字每个桶中有几个数
        int[] arrCounts = new int[10];
        int temp = 0;
        int max = max(sort);
        int num = maxIndex(max);
        boolean flag = true;
        while (flag) {
            for (int i = 0; i < sort.length; i++) {
                if (i != 0){
                    temp = (sort[i] / (10 * i)) % 10;
                }else{
                    temp = sort[i] % 10;
                }
                //arrCounts[temp] 刚开始为0,代表第temp个桶的第一个数是sort[i]
                arr[temp][arrCounts[temp]] = sort[i];
                arrCounts[temp]++;
            }
            int index = 0;
            for (int i = 0; i < arrCounts.length; i++) {
                if (arrCounts[i] != 0) {
                    for (int j = 0; j < arrCounts[i]; j++) {
                        sort[index] = arr[i][j];
                        index++;
                    }
                }
                //每次赋值结束之后要清零
                arrCounts[i] = 0;
            }
            num--;
            if (num <= 0) {
                System.out.println(Arrays.toString(sort));
                flag = false;
            }
        }
    }

算法八: 堆排序

public static void sort(){

        for (int i = arr.length / 2 - 1; i >= 0; i--) {
            largeSort(arr,i,arr.length);
        }
        System.out.println(Arrays.toString(arr));

        for (int j = arr.length - 1; j > 0; j--) {
            int temp = 0;
            temp = arr[j];
            arr[j] = arr[0];
            arr[0] = temp;
            largeSort(arr,0,j);
        }
    }
/**
     *
     * @param arr 传入的数组
     * @param i 非叶子节点在数组中的索引
     * @param length 数组长度
     */
    public static void largeSort(int[] arr,int i,int length){

        int temp = arr[i];

        for (int j = (2 * i + 1); j < length; j = (j * 2 + 1)) {
            //如果左节点比右节点小
            if (arr[j] < arr[j + 1] && j + 1 < length){
                j++;
            }
            //如果节点比头节点大
            if (arr[j] > temp){
                //把叶子节点的值赋给头节点
                arr[i] = arr[j];
                //下标后移
                i = j;
            }
            else {
                break;
            }
        }
        //将arr[i]这个值给最后一位
        arr[i]  = temp;
    }

八大排序算法对比

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值