Java实现8种常见的排序算法

1、 排序算法的分类

在这里插入图片描述
在这里插入图片描述

2、冒泡排序

冒泡排序是一种简单的排序算法,它重复地走访过要排序的数列,一次比较两个元素,如果他们的前一个元素比后一个元素大就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端。
例如:将原始数据 3,9,-1,10,20 进行冒泡排序
在这里插入图片描述

在这里插入图片描述

代码实现

public class BubbleSort {
    public static void main(String[] args) {
        int[] arr = {3, 9, -1, 10, 20};
        bubbleSort(arr);
    }

    private static void bubbleSort(int[] arr) {
        int temp;
        for (int i = 0; i < arr.length - 1; i++) {
            for (int i1 = 0; i1 < arr.length - 1 - i; i1++) {
                if (arr[i1] > arr[i1 + 1]) {
                    temp = arr[i1];
                    arr[i1] = arr[i1 + 1];
                    arr[i1 + 1] = temp;
                }
            }
            System.out.println("第" + (i + 1) + "次排序是        " + Arrays.toString(arr));
        }
    }
}


输出结果
第1次排序是        [3, -1, 9, 10, 20]
第2次排序是        [-1, 3, 9, 10, 20]
第3次排序是        [-1, 3, 9, 10, 20]
第4次排序是        [-1, 3, 9, 10, 20]

冒泡排序的优化

代码实现

public class BubbleSort {
    public static void main(String[] args) {
        int[] arr = {3, 9, -1, 10, 20};
        bubbleSort(arr);
    }

    private static void bubbleSort(int[] arr) {
        int temp;
        boolean flag = false;
        for (int i = 0; i < arr.length - 1; i++) {
            for (int i1 = 0; i1 < arr.length - 1 - i; i1++) {
                if (arr[i1] > arr[i1 + 1]) {
                    flag = true;
                    temp = arr[i1];
                    arr[i1] = arr[i1 + 1];
                    arr[i1 + 1] = temp;
                }
            }
            if (!flag) {
                break;
            } else {
                flag = false;
            }
            System.out.println("第" + (i + 1) + "次排序是        " + Arrays.toString(arr));
        }
    }
}

结果
第1次排序是        [3, -1, 9, 10, 20]
第2次排序是        [-1, 3, 9, 10, 20]
3、选择排序

给定一个数组将第一个值看成最小值,然后和后续的比较找出最小值和下标,交换本次遍历的起始值和最小值。
说明:每次遍历的时候,将前面找出的最小值,看成一个有序的列表,后面的看成无序的列表,然后每次遍历无序列表找出最小值。

在这里插入图片描述

在这里插入图片描述

选择排序

public class BubbleSort {
    public static void main(String[] args) {
        int[] arr = {101, 24, 119, 1};
        selectSort(arr);
    }

    private static void selectSort(int[] arr) {
        // 101, 24, 119, 1
        // 假定第一个值为最小值    定义最小值索引
        int minIndex;
        int min;

        for (int i = 0; i < arr.length - 1; i++) {
            minIndex = i;
            min = arr[i];
            for (int i1 = i + 1; i1 < arr.length; i1++) {
                if (min > arr[i1]) {
                    minIndex = i1;
                    min = arr[i1];
                }
            }
            // 每次循环结束 进行数据交换
            if (minIndex != i) {
                arr[minIndex] = arr[i];
                arr[i] = min;
            }
            System.out.println("第" + (i + 1) + "次排序是        " + Arrays.toString(arr));
        }
    }
 }
 
第1次排序是        [1, 24, 119, 101]
第2次排序是        [1, 24, 119, 101]
第3次排序是        [1, 24, 101, 119]


4、插入排序

在这里插入图片描述

在这里插入图片描述

public class BubbleSort {
	public static void main(String[] args) {
	        int[] arr = {101, 24, 119, 1};
	        insertSort(arr);
	    }

	    private static void insertSort(int[] arr) {
	        // 101, 34, 119, 1
	        for (int i = 1; i < arr.length; i++) {
	            // 定义待插入的数
	            int insertVal = arr[i];
	            // 定义带插入的索引
	            int insertIndex = i - 1;
	
	            // 判断
	            while (insertIndex >= 0 && insertVal < arr[insertIndex]) {
	                arr[insertIndex + 1] = arr[insertIndex];
	                insertIndex--;
	            }
	            // 插入最小值的位置
		       if (insertIndex + 1 != i) {
	                arr[insertIndex + 1] = insertVal;
	            }
	            System.out.println("第" + (i) + "次排序是        " + Arrays.toString(arr));
	        }
	    }
 }

第1次排序是        [24, 101, 119, 1]
第2次排序是        [24, 101, 119, 1]
第3次排序是        [1, 24, 101, 119]
5、希尔排序

基本上和插入排序一样的道理,不一样的地方在于,每次循环的步长,通过减半的方式来实现。
说明:基本原理和插入排序类似,不一样的地方在于。通过间隔多个数据来进行插入排序。
在这里插入图片描述

public class BubbleSort {
    public static void main(String[] args) {
        int[] arr = {8, 9, 1, 7, 2, 3, 5, 4, 6, 0};

        shellSort(arr);
    }

    private static void shellSort(int[] arr) {

        // 步长
        for (int stepLength = arr.length / 2; stepLength > 0; stepLength /= 2) {
            for (int i1 = stepLength; i1 < arr.length; i1++) {
                // 要插入的索引
                int insertIndex = i1;
                // 要插入的数据
                int insertVal = arr[insertIndex];
                // 分组前面的元素 大于后面的元素
                if (arr[insertIndex] < arr[insertIndex - stepLength]) {
                    while (insertIndex - stepLength >= 0 && insertVal < arr[insertIndex - stepLength]) {
                        arr[insertIndex] = arr[insertIndex - stepLength];
                        insertIndex -= stepLength;
                    }
                    // 将小的值赋值给前面的索引
                    arr[insertIndex] = insertVal;
                }
            }
            System.out.println("第" + (stepLength) + "次排序是        " + Arrays.toString(arr));
        }
    }
  }
6、快速排序

通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序。
在这里插入图片描述

package com.example.datastructureandalgorithm.datastructure.sort;

import java.util.Arrays;

/* *
 * @program: DataStructureAndAlgorithm
 * @description
 * @author: swq
 * @create: 2021-04-27 23:20
 **/
public class QuickSort {
    public static void main(String[] args) {
        int[] arr = {-9, 78, 0, 23, -567, 70};
        quickSort(arr, 0, arr.length - 1);
        System.out.println(Arrays.toString(arr));
    }

    private static void quickSort(int[] arr, int left, int right) {
        int l = left;  // 左下标
        int r = right;// 右下标
        //中值
        int pivot = arr[(left + right) / 2];
        int temp = 0;
        while (l < r) {
            // 中值的左边大于等于中值的数
            while (arr[l] < pivot) {
                l += 1;
            }
            // 中值的右边小于等于中值的数
            while (arr[r] > pivot) {
                r -= 1;
            }
            // l>=r 说明pivot的左右两边的值  已经按照左边全部是小于等于pivot的值 右边大于等于pivot的值
            if (l >= r) {
                break;
            }
            // 交换
            temp = arr[l];
            arr[l] = arr[r];
            arr[r] = temp;

            // 如果交换之后  发现 arr[l] == pivot 则 r向前移动
            if (arr[l] == pivot) {
                r -= 1;
            }
            // 如果交换之后  发现 arr[r] == pivot 则 l向后移动
            if (arr[r] == pivot) {
                l += 1;
            }

        }
        // 如果交换之后  发现 l==r 则 必须 l++,r--;
        if (l == r) {
            l += 1;
            r -= 1;
        }
        // 向左递归
        if (left < r) {
            quickSort(arr, left, r );
        }
        // 向右递归
        if (right > l) {
            quickSort(arr, l, right);
        }
    }
}

7、归并排序

归并排序(MERGE-SORT)是利用归并的思想实现的排序方法,该算法采用经典的分治(divide-and-conquer)策略(分治法将问题分(divide)成一些小的问题然后递归求解,而治(conquer)的阶段则将分的阶段得到的各答案"修补"在一起,即分而治之)。

在这里插入图片描述

package com.example.datastructureandalgorithm.datastructure.sort;

import java.util.Arrays;

/* *
 * @program: DataStructureAndAlgorithm
 * @description 归并排序
 * @author: swq
 * @create: 2021-04-29 22:29
 **/
public class MergeSort {
    public static void main(String[] args) {

        int[] arr = {-9, 78, 0, 23, -567, 70};
        int[] temp = new int[arr.length];
        int left = 0;
        int right = arr.length - 1;

        mergeSort(arr, left, right, temp);

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


    /**
     * 分开 + 合并
     *
     * @param arr
     * @param left
     * @param right
     * @param temp
     */
    private static 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);

            // 合并
            meger(arr, left, mid, right, temp);
        }

    }

    /**
     * 合并
     *
     * @param arr   数组
     * @param left  左边索引
     * @param mid   中值
     * @param right 右边索引
     * @param temp  临时数组
     */
    private static void meger(int[] arr, int left, int mid, int right, int[] temp) {
        int i = left; // 初始化i, 左边有序序列的初始索引
        int j = mid + 1; //初始化j, 右边有序序列的初始索引
        int t = 0; // 指向temp数组的当前索引

        //(一)
        //先把左右两边(有序)的数据按照规则填充到temp数组
        //直到左右两边的有序序列,有一边处理完毕为止
        while (i <= mid && j <= right) {
            //如果左边的有序序列的当前元素,小于等于右边有序序列的当前元素
            //即将左边的当前元素,填充到 temp数组
            //然后 t++, i++
            if (arr[i] <= arr[j]) {
                temp[t] = arr[i];
                i+=1;
                t+=1;
            } else { //反之,将右边有序序列的当前元素,填充到temp数组
                temp[t] = arr[j];
                j+=1;
                t+=1;
            }
        }

        //(二)
        //把有剩余数据的一边的数据依次全部填充到temp

        while (i <= mid) { //左边的有序序列还有剩余的元素,就全部填充到temp
            temp[t] = arr[i];
            i+=1;
            t+=1;
        }

        while (j <= right) { //右边的有序序列还有剩余的元素,就全部填充到temp
            temp[t] = arr[j];
            j+=1;
            t+=1;
        }

        //(三)
        //将temp数组的元素拷贝到arr
        //注意,并不是每次都拷贝所有

        t = 0;
        int tempLeft = left;
        //第一次合并 tempLeft = 0 , right = 1 //  tempLeft = 2  right = 3 // tL=0 ri=3
        //最后一次 tempLeft = 0  right = 7
        while (tempLeft <= right) {
            arr[tempLeft] = temp[t];
            t += 1;
            tempLeft += 1;
        }
    }


}

8、基数排序

将所有待比较数值统一为同样的数位长度,数位较短的数前面补零。然后,从最低位开始,依次进行一次排序。这样从最低位排序一直到最高位排序完成以后, 数列就变成一个有序序列

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

package com.example.datastructureandalgorithm.datastructure.sort;

import java.sql.SQLOutput;
import java.util.Arrays;

/* *
 * @program: DataStructureAndAlgorithm
 * @description
 * @author: swq
 * @create: 2021-05-02 09:47
 **/
public class RadixSort {
    public static void main(String[] args) {
        int[] arr = {53, 3, 542, 748, 14, 214};
        radixSort(arr);

    }

    /* *
     * 基数排序
     * @param arr
     */
    private static void radixSort(int[] arr) {
        // 首先获取最大值
        int max = arr[0];
        for (int value : arr) {
            if (value > max) {
                max = value;
            }
        }

        // 获取最大值的长度
        int length = (max + "").length();
        // 创建二维数组
        int[][] buckets = new int[10][arr.length];
        //创建一维数组 存放的是每个桶中的个数
        int[] bucketCounts = new int[10];
        // 循环桶
        for (int bucket = 0; bucket < length; bucket++) {
            for (int arrIndex = 0; arrIndex < arr.length; arrIndex++) {
                // 获取个 十 百 的数值
                // 要存放桶下标的索引
                int pow = (int) Math.pow(10, bucket);
                int bucketIndex = (arr[arrIndex] / pow) % 10;
                // 存放数据
                buckets[bucketIndex][bucketCounts[bucketIndex]] = arr[arrIndex];
                bucketCounts[bucketIndex]++;
            }
            // 进行数据取出的操作
            // 循环遍历10个桶 如果有数据 则按照顺序取出
            int bucketLength = buckets.length;
            //存储数据的数组下表起始索引
            // 循环桶
            int index = 0;
            for (int i = 0; i < bucketLength; i++) {
                // 判断是否有数据
                if (buckets[i] != null) {
                    // 有数据 则取出
                    // 获取该桶的元素个数
                    int bucketCount = bucketCounts[i];
                    for (int i1 = 0; i1 < bucketCount; i1++) {
                        arr[index] = buckets[i][i1];
                        index++;
                    }
                }
                // 重置装有每个桶个数的一维数组
                bucketCounts[i] = 0;
            }
            System.out.println("第" + (bucket + 1) + "轮数据===========> " + Arrays.toString(arr));
        }
    }
}

9、堆排序

堆是具有一个的完全二叉树。

  • 每个结点的值都大于或等于其左右孩子结点的值,称为大顶堆, 注意 : 没有要求结点的左孩子的值和右孩子的值的大小关系。

在这里插入图片描述

  • 每个结点的值都小于或等于其左右孩子结点的值,称为小顶堆。

在这里插入图片描述
堆排序的基本思想是:

  • 将待排序序列构造成一个大顶堆
  • 此时,整个序列的最大值就是堆顶的根节点。
  • 将其与末尾元素进行交换,此时末尾就为最大值。
  • 然后将剩余 n-1 个元素重新构造成一个堆,这样会得到 n 个元素的次小值。如此反复执行,便能得到一个有序序列了。

例如:给你一个数组 {4,6,8,5,9} , 要求使用堆排序法,将数组升序排序

package com.example.datastructureandalgorithm.algorithm;

import java.util.Arrays;

/* *
 * @program: DataStructureAndAlgorithm
 * @description
 * @author: swq
 * @create: 2021-05-03 15:55
 **/
public class HeapSort {
    public static void main(String[] args) {
        //要求将数组进行升序排序
        int arr[] = {4, 6, 8, 5, 9};
        heapSort(arr);

    }

    //编写一个堆排序的方法
    public static void heapSort(int arr[]) {
        // 临时变量
        int temp = 0;
        //将无序序列构建成一个堆,根据升序降序需求选择大顶堆或小顶堆
        for(int i = arr.length / 2 -1; i >=0; i--) {
            adjustHeap(arr, i, arr.length);
        }

        		/*
		 * 2).将堆顶元素与末尾元素交换,将最大元素"沉"到数组末端;
  			3).重新调整结构,使其满足堆定义,然后继续交换堆顶元素与当前末尾元素,反复执行调整+交换步骤,直到整个序列有序。
		 */
        for(int j = arr.length-1;j >0; j--) {
            //交换
            temp = arr[j];
            arr[j] = arr[0];
            arr[0] = temp;
            adjustHeap(arr, 0, j);
        }
        System.out.println("数组=" + Arrays.toString(arr));
    }

    /**
     * 调节堆大小
     *
     * @param arr    数组
     * @param i      调整的起始索引
     * @param length 长度
     */
    public static void adjustHeap(int arr[], int i, int length) {
        //先取出当前元素的值,保存在临时变量
        int temp = arr[i];
        // 循环遍历堆
        for (int k = i * 2 + 1; k < length; k = k * 2 + 1) {
            //说明左子结点的值小于右子结点的值
            if (k + 1 < length && arr[k] < arr[k + 1]) {
                k++;  // k改为指向右子结点
            }
            //如果子结点大于父结点
            if (arr[k] > temp) {
                //把较大的值赋给当前结点
                arr[i] = arr[k];
                // i 指向 k,继续循环比较
                i = k;
            }else {
                break;
            }

            //当for 循环结束后,我们已经将以i 为父结点的树的最大值,放在了 最顶(局部)
            arr[i] = temp;//将temp值放到调整后的位置
        }
    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值