标签:计数排序 int ring 排序算法总结 src heapsort str 空间 The
大部分算法都是从无序区扩展到有序区
1.冒泡排序 O(N2),空间O(1)
每一轮从无序区冒泡出一个最大的数到有序区
2.选择排序O(N2),空间O(1)
每一轮从无序区选择一个最大的数到有序区
3.堆排序O(NlogN),空间O(1)
其实就是选择排序的改进,每次从堆中选择一个最大值;
堆:父节点的值 >= 所有子节点的值
建堆:
在一个数组中,下标为0的元素为根节点,i的子节点为2i+1和2i+2;
从右往左、从下往上的第一个非叶子节点开始,即arr.length/2-1,与它的子节点递归比较。
建完堆后,产生一个最大值,将它与最后一个节点swap,无序区就变成了N-1,这个时候只要将根节点递归比较,就能产生次大值,依次下去...
public class HeapSort {
public static void main(String[] args) {
int[] array = new int[] { 2, 1, 4, 3, 6, 5, 8, 7 };
// 接下来就是排序的主体逻辑
sort(array);
System.out.println(Arrays.toString(array));
}
public static void sort(int[] array) {
for (int i = array.length / 2 - 1; i >= 0; i--) {
adjustHeap(array, i, array.length);
}
for (int j = array.length - 1; j > 0; j--) {
adjustHeap(array, 0, j);
}
}
public static void adjustHeap(int[] array, int i, int length) {
int temp = array[i];
for (int k = 2 * i + 1; k < length; k = 2 * k + 1) {
if (k + 1 < length && array[k] < array[k + 1]) {
k++;
}
if (array[k] > temp) {
swap(array, i, k);
i = k;
} else {
break;
}
}
}
public static void swap(int[] arr, int a, int b) {
int temp = arr[a];
arr[a] = arr[b];
arr[b] = temp;
}
}
4.插入排序O(N2),空间O(1)
在数组大多数元素有序时有优势
从第2个元素开始,与前面的元素比较,若小于前面的,则swap,注意要向前比较一直到不用swap。
5.希尔排序O(?),空间O(1)
假定一个数k,如果说插入排序每次是与前面间隔1步的比较,那么希尔排序就是与前面间隔k步的比较
k每轮减1,一直到1,这样做其实利用插入排序的优势。
6.归并排序O(NlogN),空间O(N)
分治,O(N)合并
7.快速排序O(NlogN),空间O(logN)
主要难写的就是划分区域的部分
划分为左区域、右区域,先从右边扫,再从左边扫
(各扫到一个不满足条件的数后,交换,进行下一轮)
temp = a[left]; //temp中存的就是基准数
i = left;
j = right;
while(i != j) { //顺序很重要,要先从右边开始找
while(a[j] > temp && i < j)
j--;
while(a[i] <= temp && i < j)//再找左边的
i++;
if(i < j)//交换两个数在数组中的位置
{
t = a[i];
a[i] = a[j];
a[j] = t;
}
}
//最终将基准数归位
a[left] = a[i];
a[i] = temp;
为啥这个做法是正确的?
分情况讨论一下即可:
两边若都扫到一个不满足a[j] > temp/<= temp 条件的,则交换;
右边是一定会扫到,而左边没扫到,则可以停止了,最终将基准数归位。
8.桶排序O(N),空间O(M)
桶即hash的那个桶
计数排序
数字区间范围小的,比如年龄、身高
基数排序
以数字为0-9作为桶,从低位到高位排
标签:计数排序 int ring 排序算法总结 src heapsort str 空间 The
原文地址:https://www.cnblogs.com/lnu161403214/p/11183847.html