【数据结构】Java代码实现七大排序算法

冒泡排序


 public static void bubble(int[] arr){

        for (int i = 0; i < arr.length - 1; i++){
            //System.out.println("第"+ (i+1) + "趟排序");
            boolean flag = false;
            for (int j = 0; j < arr.length - 1 - i; j++){
                if (arr[j] > arr[j+1]){
                    int temp = arr[j+1];
                    arr[j+1] = arr[j];
                    arr[j] = temp;
                    flag = true;
                }
            }

            if (!flag){
                break;
            }
        }
    }

选择排序

  public static void selectSort1(int[] arr){

        for (int i = 0;i < arr.length - 1;i++){
            for (int j = i + 1; j < arr.length; j++){
                if (arr[j] < arr[i]){
                    //选取更小的往前替换
                    int temp = arr[j];
                    arr[j] = arr[i];
                    arr[i] = temp;
                }
            }
        }

    }
//选择排序
    public static void selectSort2(int[] arr) {
        //每次选取后面的最小元素与之替换
        for (int i = 0; i < arr.length - 1; i++) {
            int minIndex = i;
            int min = arr[i];
            //向后遍历扫描最小元素
            for (int j = i + 1; j < arr.length; j++) {
                if (min > arr[j]) { // 说明假定的最小值,并不是最小
                    min = arr[j]; // 重置min
                    minIndex = j; // 重置minIndex
                }
            }
            // 将最小值,放在arr[i], 即交换
            if (minIndex != i) {
                arr[minIndex] = arr[i];
                arr[i] = min;
            }

        }
    }

插入排序

  /**
     * 插入排序,将无序列的数据插入到有序列
     * 采用移动元素的算法
     * @param arr
     */
    public static void insertSort(int[] arr){

        for (int i = 1; i < arr.length; i++){
            if (arr[i] < arr[i-1]){
                //将当前元素插入到前面,依次判断前面的元素大小,越小越往前,直到比某个数大
                int temp = arr[i];
                int j;
                //挪动元素
                for (j = i -1; j >= 0 && temp < arr[j] ; j--){
                    //大数后移
                    arr[j+1] = arr[j];
                }
                //当temp >= arr[j]时扫描结束,在arr[j]的后面插入temp
                arr[j+1] = temp;

            }
        }
    }

希尔排序

/**
 * 希尔排序:改进的插入排序
 * 采用:步长分组+分组内插入排序算法
 */
public class ShellSort {
    public static void main(String[] args) {
        int[] arr = {8,9,1,7,2,3,5,4,6,0};
        shellSort2(arr);
        System.out.println(Arrays.toString(arr));

    }

    /**
    * 希尔排序之交换法
     */
    public static void shellSort(int[] arr){

        for (int gap = arr.length/2; gap > 0; gap/= 2){
            for (int i = gap; i < arr.length; i++){
                int j = i;//用于分组扫描
                //同组以每隔一个步长扫描上一个元素并比较大小
                while (j-gap >= 0 && arr[j-gap] > arr[j]){
                    //交换
                    int temp = arr[j];
                    arr[j] = arr[j-gap];
                    arr[j-gap] = temp;
                    //j继续向前扫描同组上一个元素
                    j -= gap;
                }
            }
        }
    }


    /**
     * 希尔排序之移动法
     */
    public static void shellSort2(int arr[]){
        for (int gap = arr.length/2; gap > 0; gap /= 2){
            for (int i = gap; i < arr.length; i++){
                int j = i;//用于分组扫描
                int temp = arr[j];//用于保存待插入的无序数

                while (j - gap >= 0 &&  arr[j-gap] > temp){
                    //大数后移
                   arr[j] = arr[j-gap];//以步长为单位进行后移
                    j -= gap;
                }
                //将待插入元素放到 j-gap 的后面
                arr[j] = temp;

            }

        }


    }
}

快速排序

/**
 * 快速排序
 * 采用:左右标兵扫描+递归分治,以空间换时间
 */
public class QuickSort {
    public static void main(String[] args) {

    }
    public static void quickSort(int[] arr,int left, int right){
        int l = left;
        int r= right;
        int pivot = arr[(left + right) / 2];//pivot 中轴值
        int temp = 0;//用作交换时的中间变量
        while (l < r){
            //左标兵从前往后找大数,右标兵从后往前找小数

            while (arr[l] < pivot){//大数法则
                l++;
            }
            while (arr[r] > pivot){//小数法则
                r--;
            }
            if (l > r){
                break;//在找数过程中,左右标兵碰面了,表示找数失败
            }
            //找数成功,交换左右标兵的值
            temp = arr[l];
            arr[l] = arr[r];
            arr[r] = temp;

            //注意一个bug,当数组中存在两个相等的pivot时,要避免死循环
            //比较交换完的元素是否有等于pivot,防止两个相等的pivot进入死循环
            if (arr[l] == pivot){
                r--;//交换完的元素可以跳过
            }
            if (arr[r] == pivot){
                l++;
            }
        }
        //如果一趟下来,l==r,必须l++,r--,将数组左右区分开
        if (l == r){
            l++;
            r--;
        }

        //向左递归
        quickSort(arr,left,r);
        //向右递归
        quickSort(arr,l,right);

    }
}

归并排序

/**
 * 归并排序:采取分而治之的思想
 * 采用:分割数组成小块区域,再整合小区域思想
 * 采用:递归分治 + temp临时中间数组 ,以空间换时间
 */
public class MergetSort {
    public static void main(String[] args) {
        int[] arr =  { 8, 4, 5, 7, 1, 3, 6, 2 };
        int[] temp = new int[arr.length];
        mergeSort(arr,0,arr.length-1,temp);
        System.out.println(Arrays.toString(arr));

    }


    /**
     * 分而治之思想,使用递归去分割数组,然后再合并
     * @param arr
     * @param left
     * @param right
     * @param temp
     */
    public 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);
            //合并
            merge(arr,left,mid,right,temp);

        }

    }


    /**
     * 合并算法
     * @param arr 排序的原始数组
     * @param left 左边有序序列的初始索引
     * @param mid 中间索引
     * @param right 右边索引
     * @param temp 做中转的数组
     */
    public static void merge(int[] arr,int left,int mid,int right,int[] temp){
        int i = left;
        int j = mid + 1;
        int t = 0;//用于对temp数组的遍历

        //1.
        //先把左右两边(有序)的数据按照规则填充到temp数组
        //直到左右两边的有序序列,有一边处理完毕为止
        while (i <= mid && j <= right){
            if (arr[i] <= arr[j]){
                temp[t] = arr[i];
                t++;
                i++;
            }else{
                temp[t] = arr[j];
                t++;
                j++;
            }
        }

        //2.//把有剩余数据的一边的数据依次全部填充到temp
        while (i <= mid){
            temp[t] = arr[i];
            t++;
            i++;
        }
        while (j <= right){
            temp[t] = arr[j];
            t++;
            j++;
        }

        //3.
        //将temp数组的元素拷贝到arr
        //注意,并不是每次都拷贝所有
        //第一次合并 tempLeft = 0 , right = 1 //  tempLeft = 2  right = 3 // tL=0 ri=3
        t = 0;
        int tempindex = left;
        while (tempindex <= right){
            arr[tempindex] = temp[t];
            t++;
            tempindex++;
        }

    }
}

桶排序

/**
 * 基数排序(桶排序)
 * 以0~9的基数创建二维数组,将数字以个十百千位放入桶中,这样从个位开始排起一直到最高位
 * 采用:桶二维数组 + 最大位数几位就会排几次 ,以空间换时间
 * (以下算法不支持小数、负数。若数据量过大,该算法会出现OOM)
 */
public class RadixSort {
    public static void main(String[] args) {
        int arr[] = { 53, 3, 542, 748, 14, 214,10};
        radixSory(arr);
        System.out.println(Arrays.toString(arr));

    }


    /**
     * 获取数组中,最大数的位数
     */
    public static int maxDigit(int[] arr){
        int max=arr[0];
        for (int i = 1; i < arr.length;i++){
            if (arr[i] > max){
                max = arr[i];
            }
        }
        String maxStr = max + "";
        return maxStr.length();

    }

    /**
     * 基数排序
     * @param arr
     */
    public static void radixSory(int[] arr){

        //创建一个桶二维数组,每一行代表一个桶,总共有10个桶
        int[][] bucket = new int[10][arr.length];
        //创建桶标志数组,标识该桶有多少个有效值
        int[] bucketElementCounts = new int[10];

        //获取最大有几位数
        int maxDigit = maxDigit(arr);
        double chu = (double) maxDigit;
        chu = Math.pow(10,chu-1);//三位数,截取百位时要除以100,四位数则除以1000


        for (int round = 1; round <= chu; round *= 10) {
            //截取位数并放入对应桶
            for (int j = 0; j < arr.length; j++) {
                int digit = arr[j] / round % 10;
                //将截取的位数放到对应下标的桶中
                int BucketColumn = bucketElementCounts[digit];//得到对应桶中已经放入多少个元素
                bucket[digit][BucketColumn] = arr[j];//放入
                bucketElementCounts[digit]++;

            }

            //将桶中的元素再顺序放回arr数组
            int index = 0;
            for (int m = 0; m < bucket.length; m++) {

                if (bucketElementCounts[m] != 0) {//如果改行有数据
                    //遍历该行
                    for (int n = 0; n < bucketElementCounts[m]; n++) {
                        arr[index++] = bucket[m][n];
                    }

                }
                //取出改行数据后,将改行数据清零
                bucketElementCounts[m] = 0;//将计数器置零

            }

        }

    }

}

堆排序

https://www.cnblogs.com/chengxiao/p/6129630.html

猜你喜欢

转载自blog.csdn.net/qq_41864648/article/details/107610241