十大排序 Java实现
直接上代码
import java.util.ArrayList; import java.util.Collections; public class MySort { public static void main(String[] args) { MySort mySort = new MySort(); int[] arr = new int[]{5, 6, 1, 2, 3, 4, 11, 12, 32, 55, 122, 21}; // mySort.bubbleSort(arr); // mySort.selectionSort(arr); // mySort.insertionSort(arr); // mySort.shellSort(arr); // mySort.quickSort(arr); // mySort.mergeSort(arr); // mySort.heapSort(arr); // mySort.countSort(arr); // mySort.bucketSort(arr); // mySort.radixSort(arr); // System.out.println(Arrays.toString(arr)); // Arrays.sort(arr); // System.out.println(mySort.binarySearch(arr, 11, 0, arr.length - 1) == Arrays.binarySearch(arr, 11)); } /** * 交换数组中的元素 * * @param nums 数组 * @param i 交换的第一个数字 * @param j 交换的第二个数字 */ public void swap(int[] nums, int i, int j) { int temp = nums[i]; nums[i] = nums[j]; nums[j] = temp; } /** * 冒泡排序 * <p> * 比较相邻的元素。如果第一个比第二个大,就交换他们两个。 * <p> * 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数。 * <p> * 针对所有的元素重复以上的步骤,除了最后一个。 * <p> * 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。 * * @param nums 排序数组 */ public void bubbleSort(int[] nums) { for (int i = 0; i < nums.length - 1; i++) { //这里有一个优化的点是,每冒泡一次,最大的数就会排到后面去,那么最后面的数就不用比较,必定是有序的 for (int j = 0; j < nums.length - i - 1; j++) { if (nums[j] > nums[j + 1]) { swap(nums, j, j + 1); } } } } /** * 选择排序 * <p> * 首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置。 * <p> * 再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。 * <p> * 重复第二步,直到所有元素均排序完毕。 * * @param nums 排序数组 */ public void selectionSort(int[] nums) { for (int i = 0; i < nums.length; i++) { int minIndex = i; for (int j = i + 1; j < nums.length; j++) { if (nums[minIndex] > nums[j]) { minIndex = j; } } swap(nums, i, minIndex); } } /** * 插入排序 * <p> * **不断地向前比较/交换,插入到合适的位置** * <p> * 将第一待排序序列第一个元素看做一个有序序列,把第二个元素到最后一个元素当成是未排序序列。 * <p> * 从头到尾依次扫描未排序序列,将扫描到的每个元素插入有序序列的适当位置。(如果待插入的元素与有序序列中的某个元素相等,则将待插入元素插入到相等元素的后面。) * * @param nums 排序数组 */ public void insertionSort(int[] nums) { for (int i = 1; i < nums.length; i++) { int index = i; int num = nums[index]; while (index > 0 && num < nums[index - 1]) { nums[index] = nums[index - 1]; index--; } nums[index] = num; } } /** * 希尔排序 * <p> * 选择一个增量序列 t1,t2,……,tk,其中 ti > tj, tk = 1; * <p> * 按增量序列个数 k,对序列进行 k 趟排序; * <p> * 每趟排序,根据对应的增量 ti,将待排序列分割成若干长度为 m 的子序列,分别对各子表进行直接插入排序。仅增量因子为 1 时,整个序列作为一个表来处理,表长度即为整个序列的长度。 * * @param nums 排序数组 */ public void shellSort(int[] nums) { int len = nums.length; for (int step = len / 2; step >= 1; step /= 2) { for (int i = step; i < len; i++) { int num = nums[i]; int j = i - step; while (j >= 0 && nums[j] > num) { nums[j + step] = nums[j]; j -= step; } nums[j + step] = num; } } } /** * 归并排序 * <p> * 申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列; * <p> * 设定两个指针,最初位置分别为两个已经排序序列的起始位置; * <p> * 比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置; * <p> * 重复步骤 3 直到某一指针达到序列尾; * <p> * 将另一序列剩下的所有元素直接复制到合并序列尾。 * * @param nums 排序数组 */ public void mergeSort(int[] nums) { myMergeSort(nums, new int[nums.length], 0, nums.length - 1); } /** * 归并排序 * * @param nums 排序数组 * @param temp 临时数组,临时存放变量 * @param left 左边界,闭区间 * @param right 有边界,闭区间 */ public void myMergeSort(int[] nums, int[] temp, int left, int right) { if (left >= right) { return; } int mid = (left + right) / 2; myMergeSort(nums, temp, left, mid); myMergeSort(nums, temp, mid + 1, right); int index = 0; int l = left; int r = mid + 1; while (l <= mid && r <= right) { if (nums[l] <= nums[r]) { temp[index++] = nums[l++]; } else { temp[index++] = nums[r++]; } } while (l <= mid) { temp[index++] = nums[l++]; } while (r <= right) { temp[index++] = nums[r++]; } for (int i = left, j = 0; i <= right; i++, j++) { nums[i] = temp[j]; } } /** * 快速排序 * <p> * 从数列中挑出一个元素,称为 "基准"(pivot); * <p> * 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作; * <p> * 递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序; * * @param nums 排序数组 */ public void quickSort(int[] nums) { myQuickSort(nums, 0, nums.length - 1); } /** * 快速排序 * * @param nums 排序数组 * @param left 排序左边界 * @param right 排序右边界 */ public void myQuickSort(int[] nums, int left, int right) { if (left >= right) { return; } int l = left; int r = right; while (l < r) { while (l < r && nums[left] <= nums[r]) { r--; } while (l < r && nums[left] >= nums[l]) { l++; } swap(nums, l, r); } swap(nums, l, left); myQuickSort(nums, left, l - 1); myQuickSort(nums, l + 1, right); } /** * 堆排序 * <p> * 堆排序的思想就是先将待排序的序列建成大根堆,使得每个父节点的元素大于等于它的子节点。 * <p> * 此时整个序列最大值即为堆顶元素,我们将其与末尾元素交换,使末尾元素为最大值。 * <p> * 然后再调整堆顶元素使得剩下的 n-1 个元素仍为大根堆,再重复执行以上操作我们即能得到一个有序的序列。 * * @param nums 排序数组 */ public void heapSort(int[] nums) { int len = nums.length - 1; buildMaxHeap(nums, len); for (int i = len; i >= 1; i--) { swap(nums, 0, len); maxHeapify(nums, 0, --len); } } /* 初始化堆 */ public void buildMaxHeap(int[] nums, int len) { //数组倒数第二层,向上堆化 for (int i = len / 2; i >= 0; i--) { maxHeapify(nums, i, len); } } public void maxHeapify(int[] nums, int i, int len) { //当子节点小于数组长度时进行排序 if (i >= len) { return; } int lson = i * 2 + 1; int rson = i * 2 + 2; int large; //左右父节点中取最大 if (lson <= len && nums[lson] > nums[i]) { large = lson; } else { large = i; } if (rson <= len && nums[rson] > nums[large]) { large = rson; } if (large != i) { swap(nums, i, large); maxHeapify(nums, large, len); } } /** * 计数排序 * <p> * 找出待排序的数组中最大和最小的元素 * <p> * 统计数组中每个值为i的元素出现的次数,存入数组C的第i项 * <p> * 对所有的计数累加(从C中的第一个元素开始,每一项和前一项相加) * <p> * 反向填充目标数组:将每个元素i放在新数组的第C(i)项,每放一个元素就将C(i)减去1 * * @param nums 排序数组 */ public void countSort(int[] nums) { int min = 0; int max = 0; for (int num : nums) { min = Math.min(min, num); max = Math.max(max, num); } int[] arr = new int[max - min + 1]; for (int num : nums) { arr[num - min]++; } int index = 0; for (int i = 0; i < arr.length; i++) { while (arr[i] > 0) { nums[index++] = i + min; arr[i]--; } } } /** * 桶排序 * <p> * 计数排序的升级版,基数排序的桶的间隔为1,这里桶的间隔扩大,适用于给数据分间隔、大数据区间查找 * * @param nums 排序数组 */ public void bucketSort(int[] nums) { int min = 0; int max = 0; for (int num : nums) { min = Math.min(min, num); max = Math.max(max, num); } //默认5个桶 int BUCKET_SIZE = 5; int BUCKET_GAP = max / BUCKET_SIZE + 1; ArrayList<Integer>[] lists = new ArrayList[BUCKET_SIZE]; for (int num : nums) { int bucketIndex = num / BUCKET_GAP; if (lists[bucketIndex] == null) { lists[bucketIndex] = new ArrayList<>(); } lists[bucketIndex].add(num); } int index = 0; for (ArrayList<Integer> list : lists) { if (list != null) { Collections.sort(list); for (Integer integer : list) { nums[index++] = integer; } } } } /** * 基数排序 * <p> * **从个位数一直排到最高位** * <p> * 将所有待比较数值(正整数)统一为同样的数位长度,数位较短的数前面补零。 * <p> * 然后,从最低位开始,依次进行一次排序。 * <p> * 这样从最低位排序一直到最高位排序完成以后, 数列就变成一个有序序列。 * * @param nums 排序数组 */ public void radixSort(int[] nums) { int k = 0; int n = 1; int m = 1; //控制键值排序依据在哪一位 int max = 0; for (int num : nums) { max = Math.max(max, num); } int d = 1; while (max > 0) { max /= 10; if (max > 0) { d++; } } int[][] temp = new int[10][nums.length]; //数组的第一维表示可能的余数0-9 int[] order = new int[10]; //数组order[i]用来表示该位是i的数的个数 while (m <= d) { for (int num : nums) { int lsd = ((num / n) % 10); temp[lsd][order[lsd]] = num; order[lsd]++; } for (int i = 0; i < 10; i++) { if (order[i] != 0) for (int j = 0; j < order[i]; j++) { nums[k] = temp[i][j]; k++; } order[i] = 0; } n *= 10; k = 0; m++; } } /** * 二分查找 * * @param nums 排序后的数组 * @param target 目标值 * @return 找到目标值就返回数组,否则返回-1 */ public int binarySearch(int[] nums, int target, int left, int right) { while (left <= right) { int mid = left + (right - left) / 2; if (nums[mid] == target) { return mid; } else if (nums[mid] > target) { right = mid - 1; } else { left = mid + 1; } } return -1; } }
本文作者:护发师兄
本文链接:https://www.cnblogs.com/jonil/p/17247598.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步