java中常见的几种排序

常见的几种排序整理

冒泡排序

思想:对比当前值的下一个值,如果大就交换位置

代码:

java 复制代码
/**
 * 冒泡排序
 */
public class bubbleSort {
    public static void main(String[] args) {
        int[] array = {1, 5, 3, 2, 4};
        bubbleSort(array);
        System.out.println(Arrays.toString(array));
    }

    public static void bubbleSort(int[] array) {
        for (int i = 0; i < array.length; i++) {
            for (int j = i + 1; j < array.length; j++) {
                if (array[i] > array[j]) {
                    int temp = array[j];
                    array[j] = array[i];
                    array[i] = temp;
                }
            }
        }
    }
}

选择排序

思想:选择当前数组中最小的一个值放在起始位置,再从剩下的数组值中选择第二小的值放在前面值的后面,直到选完。

代码:

java 复制代码
/**
 * 选择排序
 */
public class SelectSort {
    public static void main(String[] args) {
        int[] array = {1, 5, 3, 2, 4};
        selectSort(array);
        System.out.println(Arrays.toString(array));
    }

    public static void selectSort(int[] array) {
        for (int i = 0; i < array.length; i++) {
            int minIndex = i;
            for (int j = i + 1; j < array.length; j++) {
                if (array[minIndex] > array[j]) {
                    minIndex = j;
                }
            }
            int temp = array[minIndex];
            array[minIndex] = array[i];
            array[i] = temp;
        }
    }
}

插入排序

思想:

  1. 首先从第一个元素开始,该元素被认为是有序的;
  2. 取出下一个元素,在已经排序的元素序列中从后往前进行扫描;
  3. 如果该已排好序的元素大于新元素,则将该元素移到下一位置;
  4. 重复步骤3一直往前进行扫描比较,直到找到已排序的元素小于或者等于新元素的位置;
  5. 将新元素插入到该位置后;
  6. 重复步骤2~5。

代码:

java 复制代码
public class InsertSort {
    public static void main(String[] args) {
        int[] array = {1, 5, 3, 2, 4};
        insertSort(array);
        System.out.println(Arrays.toString(array));
    }

    public static void insertSort(int[] a) {
        for (int i = 1; i < a.length; i++) {
            int j = i - 1;
            int current = a[i];
            while (a[j] > current && j > 0) {
                a[j + 1] = a[j];
                j--;
            }
            a[j + 1] = current;
        }
    }
}

希尔排序

思想:更加高效的排序,是插入排序的升级版,总的来说就是先分组做插入排序,最后当gap为1时,再对整个数组进行一次插入排序,这时候数组基本有序,所以最后一次插入排序耗时很低。

代码:

java 复制代码
public class ShellSort {
    public static void main(String[] args) {
        int[] array = {1, 5, 3, 2, 4};
        shellSort(array);
        System.out.println(Arrays.toString(array));
    }

    public static void shellSort(int[] a) {
        int len = a.length;
        int temp;
        int j;
        for (int gap = len / 2; gap >= 1; gap = gap / 2) {
            for (int i = gap; i < len; i++) {
                temp = a[i];
                j = i - gap;
                while (j > 0 && a[j] > temp) {
                    a[j + gap] = a[j];
                    j -= gap;
                }
                a[j + gap] = temp;
            }
        }
    }
}

快速排序

思想: 选择一个基准元素,通常选择第一个元素或者最后一个元素,通过一趟扫描,将待排序列分成两部分,一部分比基准元素小,一部分大于等于基准元素,此时基准元素在其排好序后的正确位置,然后再用同样的方法递归地排序划分的两部分。

java 复制代码
public class QuickSort {
    public static void main(String[] args) {
        int[] arr = {10, 7, 8, 9, 1, 5};
        quickSort(arr, 0, arr.length - 1);
        System.out.println(Arrays.toString(arr));
    }

    public static void quickSort(int[] arr, int low, int high) {
        if (low < high) {
            // pi 是分区索引,arr[p] 现在已经到位
            int pi = partition(arr, low, high);

            // 分别对 pi 左边和右边的子数组进行递归排序
            quickSort(arr, low, pi - 1);
            quickSort(arr, pi + 1, high);
        }
    }

    // 这个函数将数组分为两部分,并返回分区索引
    public static int partition(int[] arr, int low, int high) {
        int pivot = arr[high]; // 选择最右边的元素作为主元
        int i = (low - 1); // 指向最小元素的指针

        for (int j = low; j <= high - 1; j++) {
            // 如果当前元素小于或等于主元
            if (arr[j] <= pivot) {
                i++;
                // 交换 arr[i] 和 arr[j]
                int temp = arr[i];
                arr[i] = arr[j];
                arr[j] = temp;
            }
        }

        // 交换 arr[i+1] 和 arr[high] (或主元)
        int temp = arr[i + 1];
        arr[i + 1] = arr[high];
        arr[high] = temp;

        return i + 1;
    }
}

归并排序

思想:采用分治法,从中间拆分为2个子组,然后递归拆分子组直到每个子组数量为1,不断的将相邻两个子组合并并且排序直到只剩一个组

代码:

java 复制代码
public class mergeSortTest {
    public static void main(String[] args) {
        int[] array = {1, 5, 3, 2, 4};
        mergeSort(array);
        System.out.println(Arrays.toString(array));
    }

    public static void mergeSort(int[] array) {
        if (array == null || array.length == 1) {
            return;
        }
        mergeSort(array, 0, array.length - 1);
    }

    public static void mergeSort(int[] array, int left, int right) {
        if (left < right) {
            int mid = (left + right) / 2;
            // 对左半部分进行归并排序
            mergeSort(array, left, mid);
            // 对右半部分进行归并排序
            mergeSort(array, mid + 1, right);
            // 合并两个有序数组
            merge(array, left, mid, right);
        }
    }

    //合并左右两侧子数组
    public static void merge(int[] array, int left, int mid, int right) {
        //临时数组
        int[] temp = new int[right - left + 1];
        //左边指针
        int p1 = left;
        //右侧指针
        int p2 = mid + 1;
        //临时数组下标
        int tempIndex = 0;
        //此步就是合并左右两边,然后比大小,排序
        while (p1 <= mid && p2 <= right) {
            temp[tempIndex++] = array[p1] < array[p2] ? array[p1++] : array[p2++];
        }
        while (p1 <= mid) {
            temp[tempIndex++] = array[p1++];
        }
        while (p2 <= right) {
            temp[tempIndex++] = array[p2++];
        }
        //将临时数组的元素复制回原数组
        if (tempIndex >= 0) System.arraycopy(temp, 0, array, left, tempIndex);
    }
}

堆排序

思想:

堆排序是一种基于二叉堆(通常是大顶堆或小顶堆)的比较排序算法。其基本思想是将待排序的序列构造成一个大顶堆,此时,整个序列的最大值就是堆顶的根节点。将其与末尾元素进行交换,此时末尾就为最大值。然后将剩余n-1个序列重新构造成一个堆,这样会得到n个元素中的次大值。 如此反复执行,便能得到一个有序序列了。

代码:

java 复制代码
public class HeapSort {
    public static void main(String[] args) {
        int[] arr = {10, 7, 8, 9, 1, 5, 3, 5, 5, 2, 0, 6, 0, 9};
        sort(arr);
        System.out.println(Arrays.toString(arr));
    }

    public static void sort(int arr[]) {
        int n = arr.length;
        // 构建最大堆(从最后一个非叶子节点开始)
        for (int i = n / 2 - 1; i >= 0; i--) {
            heapify(arr, n, i);
        }
        // 一个一个从堆顶取出元素,将堆顶元素沉到数组末端
        for (int i = n - 1; i >= 0; i--) {
            int temp = arr[0];
            arr[0] = arr[i];
            arr[i] = temp;
            // 重新调整堆  
            heapify(arr, i, 0);
        }
    }

    // 调整堆

    /**
     * 调整堆
     * 关键解释:
     * 大顶堆:arr[i] >= arr[2i+1] && arr[i] >= arr[2i+2]
     * 小顶堆:arr[i] <= arr[2i+1] && arr[i] <= arr[2i+2]
     */
    static void heapify(int arr[], int n, int i) {
        int largest = i; // 初始化最大值为根  
        int left = 2 * i + 1; // 左 = 2*i + 1
        int right = 2 * i + 2; // 右 = 2*i + 2

        // 如果左子节点大于根  
        if (left < n && arr[left] > arr[largest])
            largest = left;

        // 如果右子节点大于目前已知的最大值  
        if (right < n && arr[right] > arr[largest])
            largest = right;

        // 如果最大值不是根  
        if (largest != i) {
            int swap = arr[i];
            arr[i] = arr[largest];
            arr[largest] = swap;

            // 递归调整受影响的子堆  
            heapify(arr, n, largest);
        }
    }
}
相关推荐
雷神乐乐10 分钟前
File.separator与File.separatorChar的区别
java·路径分隔符
小刘|15 分钟前
《Java 实现希尔排序:原理剖析与代码详解》
java·算法·排序算法
jjyangyou19 分钟前
物联网核心安全系列——物联网安全需求
物联网·算法·安全·嵌入式·产品经理·硬件·产品设计
逊嘘34 分钟前
【Java语言】抽象类与接口
java·开发语言·jvm
van叶~36 分钟前
算法妙妙屋-------1.递归的深邃回响:二叉树的奇妙剪枝
c++·算法
简简单单做算法37 分钟前
基于Retinex算法的图像去雾matlab仿真
算法·matlab·图像去雾·retinex
morris13141 分钟前
【SpringBoot】Xss的常见攻击方式与防御手段
java·spring boot·xss·csp
云卓SKYDROID1 小时前
除草机器人算法以及技术详解!
算法·机器人·科普·高科技·云卓科技·算法技术
七星静香1 小时前
laravel chunkById 分块查询 使用时的问题
java·前端·laravel
Jacob程序员1 小时前
java导出word文件(手绘)
java·开发语言·word