Java各种排序

快速排序

我们会以最左边的元素作为标准,

从高位取值和他比较,找到高位比他小的元素和low互换,如果比他大则坐标减一继续找

从低位取值找到比他大的元素,和high互换填补到high的位置,如果比他小则继续找

直到low = high循环结束,此时low或者high的坐标就是standard的坐标,返回之后继续递归

复制代码
public static int parition(int[] arr, int low, int high) {
    int standard = arr[low];
    while (high > low) {
        while (high > low && arr[high] >= standard) {
            high--;
        }
        arr[low] = arr[high];
        while (high > low && arr[low] <= standard) {
            low++;
        }
        arr[high] = arr[low];
    }
    arr[low] = standard;
    return low;
}
这里需要注意:必须要检查from要小于等于end
public static void quickSort(int[] arr, int from, int end) {
    if (arr.length <= 1 || from >= end) {
        return;
    }
    int partition = parition(arr, from, end);
    quickSort(arr, from, partition - 1);
    quickSort(arr, partition + 1, end);
}

归并排序

主体思想是先把数组分为不可分的整体每个整体看作一个数组,然后数组合并排序然后再合并最终变成一整个排序好的数组。但是直接这样可能不太好理解。

可以先用二分的方式把数组分成两个部分,然后再二分,直到不可分,然后merge

复制代码
public static void mergeSort(int[] arr) {
    if (arr.length < 2) {
        return;
    }
    dichotomy(arr, 0, arr.length - 1);
}
public static void dichotomy(int[] arr, int low, int high) {
    if (high <= low) {
        return;
    }
    int mid = low + (high - low) / 2;
    // 继续二分
    dichotomy(arr, low, mid);
    dichotomy(arr, mid + 1, high);
    merge(arr, low, mid, high);
}

当有任意一方到头了,则另一方全部灌入目标数组

复制代码
public static void merge(int[] arr, int low, int mid, int high) {
    int leftIndex = low;
    int rightIndex = mid + 1;
    int[] result = new int[high - low + 1];
    for(int i = 0; i < result.length; i++) {
        // 两边都还没到头则互相比较
        if (leftIndex <= mid && rightIndex <= high) {
            if (arr[leftIndex] <= arr[rightIndex]) {
                result[i] = arr[leftIndex];
                leftIndex++;
            } else {
                result[i] = arr[rightIndex];
                rightIndex++;
            }
        } else if (leftIndex <= mid) {
            // 右边到头了
            result[i] = arr[leftIndex];
            leftIndex++;
        } else {
            // 左边到头了
            result[i] = arr[rightIndex];
            rightIndex++;
        }
    }
// 目标数组归入原数组
    for(int i = 0; i < result.length;i++) {
        arr[i + low] = result[i];
    }
}

堆排序

通过大根堆的性质,把最大值放到堆顶,然后和数组最后一位互换,堆长度--

整个过程堆长度要始终传入。

数组元素i的左右堆元素分别为 2*i + 1,2*i+2

数组最大非叶子节点为(length - 2)/2

复制代码
public static void heapsort(int[] arr) {
    if (arr.length < 2) {
        return;
    }
    int heapLen = arr.length;
    for (int i = arr.length - 1; i > 0; i--) {
        findBiggestHeap(arr, heapLen);
        // 此时和大根堆的0位置互换
        swap(arr, 0, i);
        heapLen--;
    }
}
复制代码
public static void findBiggestHeap(int[] arr, int heapLen) {
    int notLeafNode = (heapLen - 2) / 2;
    int leftNode, rightMode;
    for(int i = notLeafNode; i >= 0;i--) {
        leftNode = i*2 + 1;
        rightMode = leftNode + 1;
        leftRightCompare(arr, leftNode, rightMode, heapLen, i);
    }
}
public static void downAdjust(int[] arr, int i, int heapLen) {
    int leftNode = i*2 + 1;
    int rightMode = leftNode + 1;
    leftRightCompare(arr, leftNode, rightMode, heapLen, i);
}
复制代码
public static void leftRightCompare(int[] arr, int leftNode, int rightMode, int heapLen, int i) {
    if (rightMode < heapLen) {
        // 有两个节点
        if (arr[leftNode] > arr[i] && arr[leftNode] >= arr[rightMode]) {
            // 左节点最大
            swap(arr, leftNode, i);
            // i节点下放之后还得处理
            downAdjust(arr, leftNode, heapLen);
        } else if (arr[rightMode] > arr[i] && arr[rightMode] > arr[leftNode]) {
            // 右节点最大
            swap(arr, rightMode, i);
            // i节点下放之后还得处理
            downAdjust(arr, rightMode, heapLen);
        }
    } else if (leftNode < heapLen) {
        // 仅有左边的节点
        if (arr[leftNode] > arr[i]) {
            swap(arr, leftNode, i);
            // i节点下放之后还得处理
            downAdjust(arr, leftNode, heapLen);
        }
    }
}

半插入排序

我的半插入排序习惯从第三位开始排序,即默认前两个位置已经有序

复制代码
public static void dInsertSort(int[] arr) {
    if (arr.length < 2) {
        return;
    }
    if(arr[0] > arr[1]) {
        swap(arr, 0, 1);
    }
    int mid, low, high, tmp;
    for(int i = 2; i < arr.length; i++) {
        if (arr[i] >= arr[i-1]) {
            continue;
        }
        low = 0;
        high = i;
        mid = low + (high - low)/2;
        while (high >= low) {
            if (arr[i] > arr[mid]) {
                low = mid + 1;
            } else {
                high = mid - 1;
            }
            mid = low + (high - low)/2;
        }
        // 当low比high要大的时候
        // 移动数组,1,4,5,3 => 1,4,4,5
        tmp = arr[i];
        moveArr(arr, low, i);
        // 1,4,4,5 -> 1,3,4,5
        arr[low] = tmp;
    }
}
复制代码
public static void moveArr(int[] arr, int low, int to) {
    for(int i = to; i > low; i--) {
        arr[i] = arr[i - 1];
    }
}

桶排序

希尔排序

复制代码
public static void shell(int[] arr) {
    int gap = arr.length >> 1;
    while (gap >= 1) {
        shell1(arr, gap);
        if(gap == 1) {
            break;
        }
        gap = gap >> 1;
    }
}
public static void shell1(int[] arr, int gap) {
    for(int i = 0; i < gap; i++) {
        isGap(arr, gap);
    }
}
public static void isGap(int[] arr, int gap) {
    for(int i = gap; i < arr.length; i += gap) {
        for(int j = i; j > 0; j -= gap) {
            if(arr[j - gap] > arr[j]) {
                swap(arr, j - gap, j);
            }
        }
    }
}
相关推荐
q***649718 分钟前
Spring BOOT 启动参数
java·spring boot·后端
不穿格子的程序员21 分钟前
从零开始写算法——二分-搜索二维矩阵
线性代数·算法·leetcode·矩阵·二分查找
百***784522 分钟前
Java实战:Spring Boot application.yml配置文件详解
java·网络·spring boot
你不是我我31 分钟前
【Java 开发日记】SQL 语句左连接右连接内连接如何使用,区别是什么?
java·javascript·数据库
七夜zippoe1 小时前
Java性能调优工具篇:JMH基准测试与Profiler(JProfiler/Async-Profiler)使用指南
java·开发语言·jprofiler·jmh·async-profiler
從南走到北1 小时前
JAVA国际版二手车交易二手车市场系统源码支持Android+IOS+H5+APP
android·java·ios
Kuo-Teng1 小时前
LeetCode 19: Remove Nth Node From End of List
java·数据结构·算法·leetcode·链表·职场和发展·list
北i1 小时前
TiDB 关联子查询去关联优化实战案例与原理深度解析
java·数据库·sql·tidb
Kuo-Teng1 小时前
LeetCode 21: Merge Two Sorted Lists
java·算法·leetcode·链表·职场和发展
我命由我123451 小时前
Java 开发 - 粘包处理器 - 基于消息头 + 消息体(魔数验证、长度验证)
java·网络·后端·网络协议·java-ee·intellij-idea·intellij idea