十大排序 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 中国大陆许可协议进行许可。

posted @   护发师兄  阅读(19)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起