冒泡排序
for(int i = 0; i < nums.length - 1; i++){ // n个数,只需进行n-1轮循环比较
for(int j = 1; j < nums.length - i; j++){
if(nums[j] < nums[j - 1]){ // 如果前面的数>后面的数,交换两个数
swap(nums, j, j - 1);
}
}
}
选择排序
for(int i = 0; i < nums.length - 1; i++){ // n个数,只需进行n-1轮循环比较
int maxIndex = 0; // 找出从0~n-1-i之间最大的数的下标
for(int j = 0; j < nums.length - i; j++){
if(nums[maxIndex] < nums[j]){
maxIndex = j;
}
}
swap(nums, maxIndex, nums.length - 1 - i); // 交换
}
插入排序
for(int i = 1; i < nums.length; i++){ // 从 1开始,第i位之前是排好序的。
int tem = nums[i];
int j = i - 1;
while(j >= 0 && nums[j] > tem){ // 如果第i位小于前面的,找到临界位置,插入进去
nums[j + 1] = nums[j];
j--;
}
nums[j + 1] = tem;
}
快速排序
class Solution {
public int[] sortArray(int[] nums) {
sort(nums, 0, nums.length - 1);
return nums;
}
public void sort(int[] nums, int left, int right){
if(left >= right){
return;
}
int l = left;
int r = right;
int indexNum = nums[left];
while(l < r){
while(r > l && nums[r] >= indexNum){
r--;
}
nums[l] = nums[r];
while(r > l && nums[l] < indexNum){
l++;
}
nums[r] = nums[l];
}
nums[l] = indexNum;
sort(nums, left, l - 1);
sort(nums, l + 1, right);
}
}
堆排序
数组存储大根堆/小根堆;
升序使用大顶堆,降序采用小顶堆
下标为i的父节点,其子节点分别为【2 * i + 1】,【2 * i + 2】;
维护堆 以大根堆为例子,对于一个节点i,找出左右节点中最大的子节点,交换父节点与子节点,并递归判断子节点是否满足堆的性质。
void heapify(int nums[], int len, int index){
int largeIndex = index;
int leftIndex = index * 2 + 1;
int rightIndex = index * 2 + 2;
if(leftIndex < len && nums[largeIndex] < nums[leftIndex]){
largeIndex = leftIndex;
}
if(rightIndex < len && nums[largeIndex] < nums[rightIndex]){
largeIndex = rightIndex;
}
if(largeIndex != index){
swap(nums, largeIndex, index);
heapify(nums, len, largeIndex);
}
}
建堆 从最后一个有孩子的节点开始,调整堆。
最后一个有孩子的节点—{下标为i的父节点,其子节点分别为【2 * i + 1】,【2 * i + 2】;},那么对于第i个节点,其父节点的下标为【(i - 1) / 2】
void heapBuild(int[] nums, int len){
for(int i = (n - 2) / 2; i >= 0; i--){
heapify(nums, len, i);
}
}
堆排序
void sort(int[] nums){
heapBuild(nums, nums.length);
for(int i = n - 1; i > 0; i--){
swap(nums, i, 0);
heapify(nums, i, 0);
}
}
复杂度
| 排序法 | 平均时间 | 最差情形 | 稳定度 | 额外空间 | 备注 |
|---|---|---|---|---|---|
| 冒泡 | O((n^2) | O(n^2) | 稳定 | O(1) | n小时较好 |
| 选择 | O((n^2) | O((n^2) | 不稳定 | O(1) | n小时较好 |
| 插入 | O((n^2) | O((n^2) | 稳定 | O(1) | 大部分已排序时较好 |
| 快速 | O(nlogn) | O((n^2) | 不稳定 | O(nlogn) | n大时较好 |
| 归并 | O(nlogn) | O(nlogn) | 稳定 | O(1) | n大时较好 |
| 堆 | O(nlogn) | O(nlogn) | 不稳定 | O(1) | n大时较好 |