排序算法

本贴最后更新于 2334 天前,其中的信息可能已经事过境迁

1. 选择排序

import java.util.Arrays; /** * 选择排序:最基本的排序方法,从前往后的排序 * 从第一个位置开始,依次和剩余的数字进行比较 * 如果小则交换;大,则不做操作。 * 比较完毕,换此时数组的第二个位置,依次和3到结尾的数字进行比较 * ...... * 直到倒数第二个位置,和最后一个位置的数比较完毕,排序完成 */ public class SelectSort { public static void main(String[] args) { // int[] a = {1, 2, 4, 5, 7, 4, 5 ,3 ,9 ,0}; int[] a = {10, 20, 15, 0, 6, 7, 2, 1, 65, 55}; System.out.println(Arrays.toString(a)); // 调用选择排序 selectSort(a); System.out.println(Arrays.toString(a)); } private static void selectSort(int[] numbers) { int size = numbers.length; int tmp = 0; // 外层循环:含义:从第一个位置开始,以此和剩余未排序的位置比较 for (int i = 0; i < size -1; i++) { // 内层循环:含义:选择的位置之后未排序的数据 i + 1 for (int j = i + 1; j < size; j++) { // 如果后一个数比前一个数的数值小,则交换两者的位置 if (numbers[j] < numbers[i]) { tmp = numbers[i]; numbers[i] = numbers[j]; numbers[j] = tmp; } } } } }

2. 冒泡排序

import java.util.Arrays; /** * 冒泡排序:依次对相邻的两个值进行比较,从后往前的排序 */ public class BubbleSort { public static void main(String[] args) { // int[] a = {1, 2, 4, 5, 7, 4, 5 ,3 ,9 ,0}; int[] a = {10, 20, 15, 0, 6, 7, 2, 1, 65, 55}; System.out.println(Arrays.toString(a)); // 调用冒泡排序 bubbleSort(a); System.out.println(Arrays.toString(a)); } private static void bubbleSort(int[] numbers) { int size = numbers.length; int tmp; boolean changed; do { changed = false; size -= 1; for (int i = 0; i < size; i++) { if (numbers[i] > numbers[i + 1]) { tmp = numbers[i]; numbers[i] = numbers[i + 1]; numbers[i + 1] = tmp; changed = true; } } } while (changed); //如果上一次的循环没有排序,则表明已经排序完成,直接结束 } }

3. 快速排序

import java.util.Arrays; /** * 快速排序: * 1. 从序列中挑出一个元素,作为"基准"(pivot).(基准不是固定不动的,也会被交换) * 2. 把所有比基准值小的元素放在基准前面,所有比基准值大的元素放在基准的后面(相同的数可以到任一边),这个称为分区(partition)操作。 * 3. 对每个分区递归地进行步骤1~2,递归的结束条件是序列的大小是0或1,这时整体已经被排好序了。 */ public class QuickSort { public static void main(String[] args) { // int[] arr = new int[]{1, 4, 8, 2, 55, 3, 4, 8, 6, 4, 0, 11, 34, 90, 23, 54, 77, 9, 2, 9, 4, 10}; int[] arr = {10, 20, 15, 0, 6, 7, 2, 1, 65, 55}; System.out.println(Arrays.toString(arr)); qSort(arr, 0, arr.length - 1); System.out.println(Arrays.toString(arr)); } private static void qSort(int[] arr, int head, int tail) { // 结束条件,1.头和尾的哨兵相遇 // 2. 数组为空或者长度小于等于1 if (head >= tail || arr == null || arr.length <= 1) { return; } // 去中间的数值为基准值 int i = head, j = tail, pivot = arr[(head + tail) / 2]; // 只有当i <= j的时候,即头哨兵小于尾哨兵,才会循环 while (i <= j) { // 从左往右,找到第一个大于基准值的数值所在的位置 while (arr[i] < pivot) { ++i; } // 从右往左,找到第一个小于基准值的数值所在的位置 while (arr[j] > pivot) { --j; } // 如果左右哨兵的位置仍然是左右分布,没有重合或者交错,进行数据的交换 // 如果两个哨兵中间就间隔一个数,在if内,分别自增和自减,会导致i == j // 如果两个哨兵中间没有间隔,是相邻的,在if内,分别自增和自减,会导致 i > j if (i < j) { int t = arr[i]; arr[i] = arr[j]; arr[j] = t; ++i; --j; } else if (i == j) {// 如果左右哨兵遇到了,增大i的位置,为了下一步递归的使用 ++i; } } // 递归判断左侧 qSort(arr, head, j); // 递归判断右侧 qSort(arr, i, tail); } }

4. 归并排序

import java.util.Arrays; /** * 归并排序 * 归并排序算法主要依赖归并(Merge)操作。归并操作指的是将两个已经排序的序列合并成一个序列的操作 */ public class MergeSort { public static void main(String[] args) { // int[] a = {1, 2, 4, 5, 7, 4, 5 ,3 ,9 ,0}; // 偶数个 // int[] a = {10, 20, 15, 0, 6, 7, 2, 1, 65, 55}; // 奇数个 int[] a = {10, 20, 15, 6, 7, 2, 1, 65, 55}; System.out.println(Arrays.toString(a)); // 调用归并排序 递归的方法实现 mergeSort(a); System.out.println(Arrays.toString(a)); } private static void mergeSort(int[] arr) { int len = arr.length; int[] result = new int[len]; merge_sort_recursive(arr, result, 0, len - 1); } private static void merge_sort_recursive(int[] arr, int[] result, int start, int end) { // 当待递归的数据长度等于1的时候(也就是将数据切分为一个一个的个体),递归开始回溯,进行 归并 的操作 if (start >= end) return; // 每次都将数组拆分为两个,在进行下一级的递归 // 确定递归每部分的start和end int len = end - start, mid = (len >> 1) + start; int start1 = start, end1 = mid; int start2 = mid + 1, end2 = end; // 开始递归,直到待递归的长度等于1的时候(也就是将数据切分为一个一个的个体), merge_sort_recursive(arr, result, start1, end1); merge_sort_recursive(arr, result, start2, end2); // 归并 操作。这一步的操作在递归的作用下,实际上每一部分都是一个有序的数组,所以才可以下方简单的比较就可以 int k = start; // 给对应的result数组赋值 while (start1 <= end1 && start2 <= end2) result[k++] = arr[start1] < arr[start2] ? arr[start1++] : arr[start2++]; // 如果第一部分有剩余的 while (start1 <= end1) result[k++] = arr[start1++]; // 如果第二部分有剩余的 while (start2 <= end2) result[k++] = arr[start2++]; // 将排序后的值重新赋值给arr的同样的位置 for (k = start; k <= end; k++) arr[k] = result[k]; } }

5. 堆排序

import java.util.Arrays; /** * 堆排序: * 堆排序就是把 * 1) 数组堆化,并进行最大堆调整,结果就是堆的堆顶 是数组最大的那个值;并且子节点永远小于父节点 * 2) 将最大堆堆顶的最大数取出, * 3) 将剩余的堆继续调整为最大堆,再次将堆顶的最大数取出, * 4) 这个过程持续到剩余数只有一个时结束。在堆中定义以下几种操作: * 1. 最大堆调整(Max-Heapify):将堆的末端子节点作调整,使得子节点永远小于父节点 * 2. 创建最大堆(Build-Max-Heap):将堆所有数据重新排序,使其成为最大堆 * 3. 堆排序(Heap-Sort):移除位在第一个数据的根节点,并做最大堆调整的递归运算 */ public class HeapSort { public static void main(String[] args) { // int[] arr = new int[]{3,5,3,0,8,6,1,5,8,6,2,4,9,4,7,0,1,8,9,7,3,1,2,5,9,7,4,0,2,6}; int[] arr = {10, 20, 15, 0, 6, 7, 2, 1, 65, 55}; System.out.println(Arrays.toString(arr)); // 调用堆排序 heapSort(arr); System.out.println(Arrays.toString(arr)); } /** * 堆排序的主要入口方法,共两步。 * * @param arr */ private static void heapSort(int[] arr) { /* * 第一步:将数组堆化 * beginIndex = 第一个非叶子节点。 * 从第一个非叶子节点开始即可。无需从最后一个叶子节点开始。 * 叶子节点可以看作已符合堆要求的节点,根节点就是它自己且自己以下值为最大。 */ // len 最大下标值 int len = arr.length - 1; // 第一个非叶子节点的下标(计算方法是:第一个非叶子节点是最后一个叶子节点的父节点) int beginIndex = (len - 1) >> 1; for (int i = beginIndex; i >= 0; i--) { maxHeapify(arr, i, len); } /* * 第二步:对堆化数据排序 * 每次都是移出最顶层的根节点A[0],与最尾部节点位置调换,同时遍历长度 - 1。 * 然后从新整理被换到根节点的末尾元素,使其符合堆的特性。 * 直至未排序的堆长度为 0。 */ for (int i = len; i > 0; i--) { swap(arr, 0, i); maxHeapify(arr, 0, i - 1); } } private static void swap(int[] arr, int i, int j) { int temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } /** * 调整索引为 index 处的数据,使其符合堆的特性。 * * @param arr * @param index 需要堆化处理的数据的索引 * @param len 未排序的堆(数组)的长度 */ private static void maxHeapify(int[] arr, int index, int len) { int li = (index << 1) + 1; // 左子节点索引 int ri = li + 1; // 右子节点索引 int cMax = li; // 子节点值最大索引,默认左子节点。 if (li > len) return; // 左子节点索引超出计算范围,直接返回。 if (ri <= len && arr[ri] > arr[li]) // 先判断左右子节点,哪个较大。 cMax = ri; if (arr[cMax] > arr[index]) { swap(arr, cMax, index); // 如果父节点被子节点调换, maxHeapify(arr, cMax, len); // 则需要继续判断换下后的父节点是否符合堆的特性。 } } }
  • 数据结构
    87 引用 • 115 回帖 • 4 关注
  • 算法
    437 引用 • 254 回帖 • 24 关注
  • 笔记

    好记性不如烂笔头。

    310 引用 • 794 回帖

相关帖子

回帖

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...