作为一个数学系的coding菜鸟,还是得多多练习coding,花了一个多小时又手撸了一遍排序,这次把代码补全关了,果然有点不习惯~
排序算法算是基础中的基础,必须得多练。稍微讲一下要点吧。
冒泡排序:每一趟将相邻元素比较,将大的元素往后挪。每一趟可以把最大的元素放到未排序数组的末尾。可以实现成稳定的排序。时间复杂度为N-1+N-2+N-3+...+1 = N(N-1)/2 = O(N^2)。空间复杂度为O(1)
选择排序:每一趟从未排序的元素中选出最大的,与未排序数组的末尾交换。不稳定的排序。时间复杂度为O(N^2),空间复杂度为O(1)
插入排序:原始的插入排序是将新的元素插入到已经排序好的数组中去,找到排序好的数组中第一个大于当前元素的位置,然后依次交换过去。可以实现为稳定的排序,时间复杂度为O(N^2),若数组已经有序,则为O(N),与待排序数组的数据状况有关。
二分插入排序:原理与插入排序一样,只不过在查找排序好的数组中第一个大于当前元素的位置时用了二分查找,相比于顺序查找效率较高。同样为稳定的排序。
希尔排序:同样也是插入排序。因为插入排序的时间复杂度与待排序数组的数据状况有关,这个时间复杂度主要是在交换元素上。而希尔排序的核心思想就是慢慢使得整个待排序数组有序,这样每一次插入排序的交换元素耗时就会变小。通过设置一个gap,对每个相邻gap的元素进行直接插入排序。如果听不懂,你就这么想,当gap为1的时候就是直接插入排序。gap为2就是对1,3,5,7,9。。。。。位置的元素进行直接插入排序。注意希尔排序是不稳定的,其时间复杂度为O(n^1.3)~O(n^2)
归并排序:利用了分治的想法。关键在于如何Merge,具体不说了,网上有很多的图解,写的都很好。时间复杂度O(NlogN),空间复杂度O(N),可以实现成稳定的排序。
快速排序:同样利用了分治的思想,关键在于Partition函数。时间复杂度为O(NlogN),最坏情况下为O(N^2)在基本排好序的情况下就很差,如果每次分区越均匀则速度越快。所以通常采用随机快排,随机选取分割点。是不稳定的排序。
堆排序:不稳定,时间复杂度为O(NlogN)
桶排序计数排序:
桶排序基数排序:
工程中的综合排序:
对数器:
下次再来填坑了~
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
int[] arr = { 1, 11, 5, 10, 9, 4, 6, 4, 2, 0 };
// BubbleSort(arr);
// InsertionSort(arr);
// BinaryInsertionSort(arr);
// ShellSort(arr);
// SelectionSort(arr);
// MergeSort(arr);
// QuickSort(arr);
// HeapSort(arr);
// BucketSort(arr);
RadixSort(arr);
for (int i : arr) {
System.out.print(i + " ");
}
System.out.println();
int testTime = 500000;
int maxSize = 100;
int maxValue = 100;
boolean succeed = true;
for (int i = 0; i < testTime; i++) {
int[] arr1 = generateRandomArray(maxSize, maxValue);
int[] arr2 = copyArray(arr1);
// BubbleSort(arr1);
// InsertionSort(arr1);
// BinaryInsertionSort(arr1);
// ShellSort(arr1);
// SelectionSort(arr1);
// MergeSort(arr1);
// QuickSort(arr1);
// HeapSort(arr1);
// BucketSort(arr1);
RadixSort(arr1);
comparator(arr2);
if (!isEqual(arr1, arr2)) {
succeed = false;
break;
}
}
System.out.println(succeed ? "Nice!" : "Fucking fucked!");
}
public static void BubbleSort(int[] arr) {
if (arr == null || arr.length < 2) {
return;
}
for (int i = 0; i < arr.length - 1; i++) {
for (int j = 0; j < arr.length - 1 - i; j++) {
if (arr[j + 1] < arr[j]) {
swap(arr, j, j + 1);
}
}
}
}
public static void InsertionSort(int[] arr) {
if (arr == null || arr.length < 2) {
return;
}
for (int i = 1; i < arr.length; i++) {
for (int j = i - 1; j >= 0; j--) {
if (arr[j + 1] < arr[j])
swap(arr, j, j + 1);
}
}
}
public static void BinaryInsertionSort(int[] arr) {
if (arr == null || arr.length < 2)
return;
for (int i = 1; i < arr.length; i++) {
int index = BinarySearch(arr, 0, i - 1, arr[i]);
for (int j = i - 1; j >= index; j--)
swap(arr, j, j + 1);
}
}
public static int BinarySearch(int[] arr, int l, int r, int target) {
int mid = 0;
while (l <= r) {
mid = l + ((r - l) >> 1);
if (arr[mid] <= target)
l = mid + 1;
else
r = mid - 1;
}
return l;
}
public static void ShellSort(int[] arr) {
if (arr == null || arr.length < 2)
return;
int gap = arr.length;
while (gap > 1) {
gap = gap / 3 + 1;
for (int i = gap; i < arr.length; i += gap) {
for (int j = i - gap; j >= 0; j--) {
if (arr[j + gap] < arr[j])
swap(arr, j, j + gap);
}
}
}
}
public static void SelectionSort(int[] arr) {
if (arr == null || arr.length < 2)
return;
for (int i = 0; i < arr.length - 1; i++) {
int index = 0;
for (int j = 1; j < arr.length - i; j++) {
if (arr[j] > arr[index])
index = j;
}
swap(arr, index, arr.length - 1 - i);
}
}
public static void MergeSort(int[] arr) {
if (arr == null || arr.length < 2)
return;
MergeSort(arr, 0, arr.length - 1);
}
public static void MergeSort(int[] arr, int l, int r) {
if (l < r) {
int mid = l + ((r - l) >> 1);
MergeSort(arr, l, mid);
MergeSort(arr, mid + 1, r);
Merge(arr, l, mid, r);
}
}
public static void Merge(int[] arr, int l, int mid, int r) {
int p1 = l;
int p2 = mid + 1;
int[] help = new int[r - l + 1];
int i = 0;
while (p1 <= mid && p2 <= r) {
if (arr[p1] <= arr[p2])
help[i++] = arr[p1++];
else
help[i++] = arr[p2++];
}
while (p1 <= mid)
help[i++] = arr[p1++];
while (p2 <= r)
help[i++] = arr[p2++];
for (int j = 0; j < help.length; j++)
arr[l + j] = help[j];
}
public static void QuickSort(int[] arr) {
if (arr == null || arr.length < 2)
return;
QuickSort(arr, 0, arr.length - 1);
}
public static void QuickSort(int[] arr, int l, int r) {
if (l < r) {
int[] p = Partition(arr, l, r);
QuickSort(arr, l, p[0]);
QuickSort(arr, p[1], r);
}
}
public static int[] Partition(int[] arr, int l, int r) {
swap(arr, r, l + (int) (Math.random() * (r - l + 1)));
int val = arr[r]; // split standard.
int p1 = l - 1;
int p2 = r;
while (l < p2) {
if (arr[l] < val)
swap(arr, l++, ++p1);
else if (arr[l] > val)
swap(arr, l, --p2);
else
l++;
}
swap(arr, p2++, r);
return new int[] { p1, p2 };
}
public static void HeapSort(int[] arr) {
if (arr == null || arr.length < 2)
return;
for (int i = 1; i < arr.length; i++)
HeapInsert(arr, i);
int size = arr.length;
while (size > 1) {
swap(arr, 0, --size);
Heapify(arr, 0, size);
}
}
public static void HeapInsert(int[] arr, int index) {
while (index > 0) {
if (arr[index] > arr[(index - 1) >> 1]) {
swap(arr, index, (index - 1) >> 1);
index = (index - 1) >> 1;
} else
return;
}
}
public static void Heapify(int[] arr, int index, int size) {
while ((index << 1) + 1 < size) {
int leftchild = (index << 1) + 1;
int childlargest = leftchild + 1 < size && arr[leftchild + 1] > arr[leftchild] ? leftchild + 1 : leftchild;
int largest = arr[index] >= arr[childlargest] ? index : childlargest;
if (largest == index)
return;
swap(arr, index, largest);
index = largest;
}
}
public static void BucketSort(int[] arr) {
if (arr == null || arr.length < 2)
return;
int min = Integer.MAX_VALUE;
int max = Integer.MIN_VALUE;
for (int i = 0; i < arr.length; i++) {
min = arr[i] < min ? arr[i] : min;
max = arr[i] > max ? arr[i] : max;
}
// 针对负数
int[] buckets = new int[max - min + 1];
for (int i = 0; i < arr.length; i++)
arr[i] -= min;
for (int i = 0; i < buckets.length; i++)
buckets[i] = 0;
for (int i = 0; i < arr.length; i++)
buckets[arr[i]]++;
int j = 0;
for (int i = 0; i < buckets.length; i++)
while (buckets[i] != 0) {
arr[j++] = i;
buckets[i]--;
}
for (int i = 0; i < arr.length; i++)
arr[i] += min;
}
public static void RadixSort(int[] arr) {
if (arr == null || arr.length < 2)
return;
final int radix = 10;
RadixSort(arr, radix);
}
public static void RadixSort(int[] arr, int radix) {
int maxbit = getmaxbit(arr, radix);
int[] count = new int[radix];
int[] buckets = new int[arr.length];
for (int bit = 1; bit <= maxbit; bit++) {
for (int i = 0; i < count.length; i++)
count[i] = 0;
for (int i = 0; i < arr.length; i++) {
int digit = getdigit(arr[i], bit, radix);
count[digit]++;
}
for (int i = 1; i < count.length; i++)
count[i] += count[i - 1];
for (int i = arr.length - 1; i >= 0; i--) {
int digit = getdigit(arr[i], bit, radix);
buckets[--count[digit]] = arr[i];
}
for (int i = 0; i < buckets.length; i++)
arr[i] = buckets[i];
}
}
public static int getmaxbit(int[] arr, int radix) {
int max = Integer.MIN_VALUE;
for (int i = 0; i < arr.length; i++)
max = arr[i] > max ? arr[i] : max;
int bit = 0;
while (max != 0) {
bit++;
max /= radix;
}
return bit;
}
public static int getdigit(int val, int bit, int radix) {
return (int) ((val / (int) Math.pow(radix, bit - 1)) % radix);
}
public static void swap(int[] arr, int i, int j) {
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
// for test
public static void comparator(int[] arr) {
Arrays.sort(arr);
}
// for test
public static int[] generateRandomArray(int maxSize, int maxValue) {
int[] arr = new int[(int) ((maxSize + 1) * Math.random())];
for (int i = 0; i < arr.length; i++) {
// arr[i] = (int) ((maxValue + 1) * Math.random()) - (int) (maxValue *
// Math.random());
arr[i] = (int) ((maxValue + 1) * Math.random());
}
return arr;
}
// for test
public static int[] copyArray(int[] arr) {
if (arr == null) {
return null;
}
int[] res = new int[arr.length];
for (int i = 0; i < arr.length; i++) {
res[i] = arr[i];
}
return res;
}
// for test
public static boolean isEqual(int[] arr1, int[] arr2) {
if ((arr1 == null && arr2 != null) || (arr1 != null && arr2 == null)) {
return false;
}
if (arr1 == null && arr2 == null) {
return true;
}
if (arr1.length != arr2.length) {
return false;
}
for (int i = 0; i < arr1.length; i++) {
if (arr1[i] != arr2[i]) {
return false;
}
}
return true;
}
// for test
public static void printArray(int[] arr) {
if (arr == null) {
return;
}
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
System.out.println();
}
}