版权声明:欢迎大家转载,指正。 https://blog.csdn.net/yin__ren/article/details/83210823
一、 插入排序
1. 特点:
- 易于实现
- 适合小规模输入(<50)
- 对近似排序好的输入效果好
2. 时间复杂度:
3. 伪代码
InsertionSort(A, n) {
for i = 2 to n {
key = A[i]
j = i - 1
while (j > 0) and (A[j] > key) {
A[j+1] = A[j]
j = j - 1
}
A[j+1] = key
}
}
4. java 实现
public static void insertSort(int[] arr) {
for (int i = 1; i < arr.length; i++) {
int tmp = arr[i];
int j;
for (j = i - 1; j >= 0 && tmp < arr[j]; j--) {
arr[j + 1] = arr[j];
}
arr[j + 1] = tmp;
}
}
二、归并排序
1. 特点
- 分割
- 递归处理
- 线性时间合并
2. 时间复杂度
3. 伪代码
MERGE(A,p,q,r){//p,q,r 是数组下标,p<=q<=r
n1 ← q – p + r
n2 ← r – q
let L and R 为左右临时数组
for i = 1..n1
do L[i] ← A[p + i – 1]
for j = 1..n2
do R[j] ← A[q + j]
//A:(结束标志)
L[n1 + 1] ← ∞
R[n2 + 1] ← ∞
i ← 1
j ← 1
for k = p to r
do if L[i] ≤ R[j]
then A[k] ← L[i]
i ← i + 1
else A[k] ← R[j]
j ← j + 1
}
MergeSort(A, p, r){
if p < r
//Split the input into 2 pieces of approximately equal size
q ← (p + r) / 2
//Recursively sort the two halves
MergeSort(A, p, q)
MergeSort(A, q + 1, r)
//Merge the two sorted subsequences
Merge(A, p, q, r)
}
4. java 实现
/**
* 分治
*
* @param arr
* @param left
* @param right
* @param tmp
*/
private static void sort(int[] arr, int left, int right, int[] tmp) {
if (left < right) {
int mid = (left + right) / 2;
sort(arr, left, mid, tmp);//左归并
sort(arr, mid + 1, right, tmp);//右归并
merge(arr, left, mid, right, tmp);
}
}
/**
* 归并核心算法
*
* @param arr
* @param left
* @param mid
* @param right
* @param tmp
*/
private static void merge(int[] arr, int left, int mid, int right, int[] tmp) {
int i = left;//左序列
int j = mid + 1;//右序列
int t = 0;//tmp
while (i <= mid && j <= right) {//归并
if (arr[i] <= arr[j]) {
tmp[t++] = arr[i++];
} else {
tmp[t++] = arr[j++];
}
}
while (i <= mid) {//将左边剩余元素填入
tmp[t++] = arr[i++];
}
while (j <= right) {//将右边剩余元素填入
tmp[t++] = arr[j++];
}
t = 0;
while (left <= right) {//将 tmp 中的元素拷贝如原数组中
arr[left++] = tmp[t++];
}
}
三、计数排序
1. 特点:
- 小范围整数的排序
- 稳定的:相等的输入元素的位置先后顺序在排列后输出中的先后顺序不变
2. 时间复杂度
3. 伪代码
//A 输入数组,B 存放排序的输出,C 提供临时储存空间
COUNTING-SORT(A, B, n, k){//假设n个输入元素为0-k之间的整数
let C[0..k] be a new array
for i ← 0 to k
do C[ i ] ← 0
//计算 C[i]包含等于i的元素的个数
for j ← 1 to n
do C[A[ j ]] ← C[A[ j ]] + 1
//计算 C[i] 包含小于或等于i的元素的个数
for i ← 1 to k
do C[ i ] ← C[ i ] + C[i -1]
for j ← n downto 1
B[C[A[ j ]]] ← A[ j ]
C[A[ j ]] ← C[A[ j ]] - 1
}
4. java 代码实现
public static void countSort(int[] input) {
int max = Integer.MIN_VALUE;
for (int i = 0; i < input.length; i++) {
max = Math.max(max, input[i]) + 1;
}
int[] output = new int[input.length];
int[] tmp = new int[max];
for (int i = 0; i < tmp.length; i++) {
tmp[i] = 0;
}
for (int j = 0; j < input.length; j++) {
tmp[input[j]]++;
}
int t = 0;
for (int k = 0; k < tmp.length; k++) {
while (tmp[k] > 0) {
output[t++] = k;
tmp[k]--;
}
}
for (int i = 0; i < input.length; i++) {
input[i] = output[i];
}
}
四、基数排序
1. 特点
- 扩大了可排序的整数范围
2. 时间复杂度
3. 伪代码
RADIX-SORT(A,d){
for i = 1 to d
use a table sort to sort array A on digit i
}
4. Java 代码实现
public static void radixSort(int[] arr) {
//防止越界
int max = Integer.MIN_VALUE;
for (int i = 0; i < arr.length; i++) {//计算最大值
max = Math.max(max, arr[i]);
}
final int bucketNum = 10;
List<ArrayList<Integer>> bucket = new ArrayList<>(bucketNum);
for (int i = 0; i < bucketNum; i++) {
bucket.add(new ArrayList<Integer>());
}
for (int i = 0; i < Math.log10(max) + 1; i++) {
int digest = (int) (1 * Math.pow(10, i));
for (int j = 0; j < arr.length; j++) {
int tmp = (arr[j] / digest) % 10;
bucket.get(tmp).add(arr[j]);
}
int t = 0;
for (int j = 0; j < bucketNum; j++) {
for (int k = 0; k < bucket.get(j).size(); k++) {
arr[t++] = bucket.get(j).get(k);
}
bucket.get(j).clear();
}
}
}
五、桶排序
1. 特点
- 将[0, 1) n等分,称为空桶
- 将n个输入分派到这些空桶之中
- 每个桶内排序
- 按顺序遍历每个桶中的元素
2. 时间复杂度
3. 伪代码
BUCKET-SORT(A){
n = A.length
let B[0..n-1] be a new array
for i ← 1 to n
insert A[i] into list B[nA[i]] (注意下标)
for i ← 0 to n - 1
sort list B[i] with insertion sort (桶内插入排序)
concatenate lists B[0], B[1], . . . , B[n -1]together in order
return the concatenated lists
}
4. java 代码实现
public static void bucketSort(int[] arr) {
//防止越界
int max = Integer.MIN_VALUE;
int min = Integer.MAX_VALUE;
for (int i = 0; i < arr.length; i++) {//计算最大值与最小值
max = Math.max(max, arr[i]);
min = Math.min(min, arr[i]);
}
//桶数
int bucketNum = (max - min) / arr.length + 1;
List<ArrayList<Integer>> bucket = new ArrayList<>(bucketNum);
for (int i = 0; i < bucketNum; i++) {//初始化每个桶
bucket.add(new ArrayList<Integer>());
}
for (int i = 0; i < arr.length; i++) {//将元素放入指定的桶中
int num = (arr[i] - min) / arr.length;
bucket.get(num).add(arr[i]);
}
int t = 0;
for (int i = 0; i < bucketNum; i++) {//对每个桶进行排序
Collections.sort(bucket.get(i));
for (int k = 0; k < bucket.get(i).size(); k++) {//将桶中排好序的元素放入原数组中
arr[t++] = bucket.get(i).get(k);
}
}
}
六、快速排序
1. 特点
- 平均性非常好
- 能进行原址排序
2. 时间复杂度
3. 伪代码
QUICKSORT(A,p,r){
if p < r
q = PARTITION(A,p,r)
QUICKSORT(A,p,q-1)
QUICKSORT(A,q+1,r)
}
PARTITION(A,p,r){
x = A[r]
i = p - 1
for j = p to r - 1
if A[j] <= x
i = i + 1
exchange A[i] with A[j]
exchange A[i + 1] with A[r]
return i + 1
}
4. Java 代码实现
private static void quickSort(int[] arr, int left, int right) {
if (left > right) {
return;
}
int index = arr[left], tmp;
int i = left, j = right;
while (i != j) {
while (arr[j] >= index && i < j) {
j--;
}
while (arr[i] <= index && i < j) {
i++;
}
if (i < j) {
tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
}
arr[left] = arr[i];
arr[i] = index;
quickSort(arr, left, i - 1);
quickSort(arr, i + 1, right);
}
七、随机快速排序
1. 特点
- 随机性
- 对数组划分比较均衡
2. 时间复杂度
3. 伪代码
RANDOMMIZED-QUICKSORT(A,p,r){
if p < r
q = RANDOMMIZED-PARTITION(A,p,r)
RANDOMMIZED-QUICKSORT(A,p,q - 1)
RANDOMMIZED-QUICKSORT(A,q + 1,r)
}
RANDOMMIZED-PARTITION(A,p,r){
i = RANDOM(p,r)
exchange A[r] with A[i]
return PARTITION(A,p,r)
}
4. Java 代码实现
private static void randomQuickSort(int[] arr, int left, int right) {
if (left > right) {
return;
}
Random random = new Random();
int random_index = (int) (Math.random() * (right - left + 1)) + left;
int swap = arr[random_index];
arr[random_index] = arr[left];
arr[left] = swap;
int index = arr[left], tmp;
int i = left, j = right;
while (i != j) {
while (arr[j] >= index && i < j) {
j--;
}
while (arr[i] <= index && i < j) {
i++;
}
if (i < j) {
tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
}
arr[left] = arr[i];
arr[i] = index;
randomQuickSort(arr, left, i - 1);
randomQuickSort(arr, i + 1, right);
}
八、堆排序
1. 实现最大堆
1. 伪代码
MAX-HEAPIFY(A,i)
l = LEFT(i)
r = RIGHT(i)
if l <= A.heap-size and A[l] > A[i]
largest = l
else largest = i
if r <= A.heap-size and A[r] > A[largest]
largest = r
if largest != i
exchange A[i] and A[largest]
MAX-HEAPIFY(A,largest)
2. 时间复杂度
3. java 代码实现
//使第 i 个节点满足最大堆规则
public static int[] maxHeap(int[] arr, int i) {
int large = i;
if (2 * i < arr.length && arr[2 * i] > arr[i]) {
large = 2 * i;
}
if (2 * i + 1 < arr.length) {
if (arr[2 * i + 1] > arr[i] && arr[2 * i + 1] > arr[2 * i]) {
large = 2 * i + 1;
}
}
if (large != i) {
HeapSort.swap(arr, i, large);
maxHeap(arr, large);
}
return arr;
}
private static void swap(int[] arr, int a, int b) {
int tmp = arr[a];
arr[a] = arr[b];
arr[b] = tmp;
}
//对数组进行扩容,使其以 1 为起始下标
private static int[] increaseArr(int[] arr) {
int[] result = new int[arr.length + 1];
for (int i = 1; i < result.length; i++) {
result[i] = arr[i - 1];
}
return result;
}
public static void main(String[] args) {
int[] arr = {16, 4, 10, 14, 7, 9, 3, 2, 8, 1};
arr = HeapSort.increaseArr(arr);
arr = HeapSort.maxHeap(arr, 2);
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
非递归代码:
public static int[] maxHeap2(int[] arr,int i){
while (2 * i < arr.length){
int j = 2 * i;
if (j + 1 < arr.length && arr[j + 1] > arr[j]){
j += 1;
}
if (arr[i] >= arr[j]){
break;
}
HeapSort.swap(arr,i,j);
i = j;
}
return arr;
}
2. 建最大堆
1. 伪代码
BUILD-MAX-HEAP(A)
A.heap-size = A.length
for i = A.length / 2 downto 1
MAX-HEAPIFY(A,i)
2. 时间复杂度
3. java 代码实现
public static int[] buildMaxHeap(int[] arr) {
arr = HeapSort.increaseArr(arr);
for (int i = arr.length / 2; i >= 1; i--) {
HeapSort.maxHeap(arr, i);
}
return arr;
}
public static void main(String[] args) {
int[] arr = {16, 4, 10, 14, 7, 9, 3, 2, 8, 1};
arr = HeapSort.buildMaxHeap(arr);
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
3. 堆排序
1. 伪代码
HEAPSORT(A)
BUILD-MAX-HEAP(A)
for i = A.length downto 2
exchange A[1] with A[i]
A.heap-size = A.heap-size - 1
MAX-HEAPIFY(A,1)
2. 时间复杂度
3. java 代码实现
public static int[] heapSort(int[] arr) {
int[] result = new int[arr.length];
arr = HeapSort.buildMaxHeap(arr);
for (int i = arr.length - 1; i >= 1; i--) {
HeapSort.swap(arr, 1, i);
result[i - 1] = arr[i];
arr = HeapSort.decreaseArr(arr);
arr = HeapSort.maxHeap(arr,1);
}
return result;
}
public static void main(String[] args) {
int[] arr = {16, 4, 10, 14, 7, 9, 3, 2, 8, 1};
arr = HeapSort.heapSort(arr);
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}