冒泡、插入、选择、归并、快速、希尔、堆、基数排序总结

  1. 冒泡排序
  2. 插入排序
  3. 选择排序
  4. 归并排序
  5. 快速排序
  6. 希尔排序
  7. 堆排序
  8. 基数排序

在这里插入图片描述

冒泡排序

对于给定的 n 个数据,每次选择相邻的两个数据进行比较,将数值较大的数据放在后面。

  • 第一次比较:将数值的最大的数据排在最后面;
  • 第二次比较:将数值次大的数据排在倒数第二;
  • 经过 n 次比较后:最小值将排在第一位。
    在这里插入图片描述
private static void bubbleSort(int[] arr){
    for(int i=0;i<arr.length;i++){   //遍历所有数据,比较n次。
        for(int j=0;j<arr.length-i-1;j++) { // 相邻数据两两比较;
            if(arr[j+1]<arr[j]){
                int tmp = arr[j];
                arr[j] =arr[j+1];
                arr[j+1] = tmp;
            }
        }
    }
}

插入排序

设有一个有序的初始序列,然后从原记录中取出一个数据,依次与初始有序序列中的数据进行比较,最后将数据插入到指定的位置。

  • 从原数组中取出第一个位置的数据,作为初始有序序列;
  • 从原数据中的第二个位置开始依次取出一条数据,与初始有序序列中的数据进行比较,并将数据插入到初始有序序列中的指定位置;
    在这里插入图片描述
private static void insertSort(int[] arr) {
    int insertVal = 0;
    int insertIndex = 0;

    for (int i = 1; i < arr.length; i++) { // 从原数组的第二个数据开始依次取出一个数据;
       
        insertVal = arr[i]; // 取出来的数据
        insertIndex = i - 1; // 记录索引位置,取出数据的当前位置的前一个位置索引。其实记录着初始有序序列的长度

        // 遍历初始数据,将取出来的数据与初始数组依次比,由于初始数据是有序的
        // 因此将初始数组中的大于取出来的数据值的数据往后移动一位。
        while (insertIndex >= 0 && insertVal < arr[insertIndex]) {
            arr[insertIndex + 1] = arr[insertIndex];
            insertIndex--;
        }
        // 将取出来的数据插入到初始数值中。
        if (insertIndex + 1 != i) {
            arr[insertIndex + 1] = insertVal;
        }
    }
}

选择排序

依次从数组中取出一个数据,然后依次与其索引之后的数据进行比较,如果不满足要求,即进行交换。

  • 取出索引为 0 的数据,与之后的数据一一进行比较,将最小的数据放在当前索引 0 的位置;
  • 取出所因为 1 的数据,与之后的数据一一进行比较,然后将次小的数据放在当前索引 1 的位置;
  • 依次取出比较,最终得到一个有序数组。
    在这里插入图片描述
private static void selectSort(int[] arr){
    for(int i=0;i<arr.length;i++){
        int minInde = i; // 获取当前索引位置
        int min = arr[minInde];  // 获取当前索引位置的数据
        
        for(int j= i;j<arr.length;j++){ // 分别与索引之后的数据进行比较
            if(arr[j] < min){ // 两两比较找出最小值
                min = arr[j];
                minInde = j;  // 找出两两比较后较小值的索引位置
            }
        }
        // 交换
        arr[minInde] = arr[i]; 
        arr[i]= min;
    }
}

归并排序

利用递归与分而治之的思路将数组切分成一系列很小很小的半子表,当半子表完成排序后再合并在一定,最终形成一个有序的数组。

  • 将数组进行拆分成很短的序列数组;
  • 然后依次比较合并;
    在这里插入图片描述
private static void mergeSort(int[] arr, int left, int right, int[] tmp) {
    if (left < right) {
        int mid = (left + right) / 2;
        mergeSort(arr, left, mid, tmp); // 上半子表拆分,不能再拆执行 merge
        mergeSort(arr, mid + 1, right, tmp); // 下半子表拆分,不能再拆执行 merge
        merge(arr, left, mid, right, tmp); 
    }
}

private static void merge(int[] arr, int left, int mid, int right, int[] tmp) {
    int i = left;
    int j = mid + 1;
    int t = 0;

    while (i <= mid && j <= right) { 
        if (arr[i] <= arr[j]) {
            tmp[t] = arr[i];
            t += 1;
            i += 1;
        } else {
            tmp[t] = arr[j];
            t += 1;
            j += 1;
        }
    }

    while (i <= mid) {
        tmp[t] = arr[i];
        t += 1;
        i += 1;
    }

    while (j <= right) {
        tmp[t] = arr[j];
        t += 1;
        j += 1;
    }

    t = 0;
    int tmpIndex = left;

    while (tmpIndex <= right) {
        arr[tmpIndex] = tmp[t];
        t += 1;
        tmpIndex += 1;
    }
}

快速排序

通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小。然后再按此方法对这两部分数据分别进行快速排序。整个排序过程可以递归进行。以此达到整个数据数组的有序。
在这里插入图片描述

private static void quickSort(int[] arr, int left, int right) {
    int l = left;
    int r = right;
    int m = (left + right) /2;
    int pivot = arr[m];

    while(l < r){
        while(arr[l] < pivot){
            l++;
        }

        while(pivot < arr[r]){
            r--;
        }

        if(l >= r){
            break;
        }

        int tmp = arr[l];
        arr[l] = arr[r];
        arr[r] = tmp;

        if(arr[l] == pivot){
            r--;
        }

        if(arr[r] == pivot){
            l++;
        }
    }

    if(l == r){
        l++;
        r--;
    }

    if(left < r){
        quickSort(arr,left,r);
    }
    
    if(l <right){
        quickSort(arr,l,right);
    }
}

希尔排序

把记录按下标的一定增量分组,对每组使用直接插入排序算法排序。随着增量逐渐减少,每组包含的关键词越来越多,当增量减少至 1 时,整个文件恰好是有序的。
在这里插入图片描述在这里插入图片描述

private static void shellSort(int[] arr) {
    for (int gap = arr.length / 2; gap > 0; gap /= 2) {
        for (int j = gap; j < arr.length; j++) {
            for (int k = j - gap; k >= 0; k -= gap) {
                if (arr[k] > arr[k + gap]) {
                    int tmp = arr[k];
                    arr[k] = arr[k + gap];
                    arr[k + gap] = tmp;
                }
            }
        }
    }
}

堆排序

堆排序是一种选择排序,是一种不稳定排序。

  • 将待排数组构造成一个大顶堆
  • 此时整个序列的最大值就是堆顶的根节点
  • 将其与末尾元素交换,末尾就是最大值。
  • 对余下数据重复上述操作,最终得到一个有序数组。

堆排序动态演示

private static void heapSort(int[] arr) {

    // 将数组构建成大顶堆
    for (int i = arr.length /2 -1 ; i >= 0; i--) {
        adjustHeap(arr, i, arr.length);
    }

    // 始终将栈顶元素与栈顶元素进行交换,保证数组末尾始终是最大值
    for (int j = arr.length - 1; j > 0; j--) {
        int tmp = arr[j];
        arr[j] = arr[0];
        arr[0] = tmp;
        adjustHeap(arr, 0, j);
    }
}

// 构建大堆顶
private static void adjustHeap(int[] arr, int i, int length) {

    int tmp = arr[i];
    // 2*i+1 是左节点
    for (int k = i * 2 + 1; k < length; k = k * 2 + 1) {
        if (k + 1 < length && arr[k] < arr[k + 1]) {
            // k += 1 是右子节点
            k++;
        }
        // 子根节点与左右子树节点进行比较
        if (arr[k] > tmp) {
            arr[i] = arr[k];
            i = k;
        } else {
            break;
        }
    }
    arr[i] = tmp;
}

基数排序

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

基数排序动态演示

private static void radixSort(int[] arr){
    int max = arr[0];
    for(int i = 1; i< arr.length;i++){
        if(arr[i] > max){
            max = arr[i];
        }
    }

    int maxLength = (max+"").length();

    int[][] bucket = new int[10][arr.length];
    int [] bucketElementCounts = new int[10];


    for(int i=0,n =1;i<maxLength;i++,n*=10){
        for(int j = 0;j<arr.length;j++){
            int digitOfElement = arr[j]/n %10;
            bucket[digitOfElement][bucketElementCounts[digitOfElement]] = arr[j];
            bucketElementCounts[digitOfElement]++;
        }

        int index = 0;

        for(int k = 0;k<bucketElementCounts.length;k++){
            if(bucketElementCounts[k] != 0){
                for(int l =0;l<bucketElementCounts[k];l++) {
                    arr[index++] = bucket[k][l];
                }
            }
            bucketElementCounts[k] = 0;
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值