类型一、选择排序
(1)冒泡排序:
a.每趟排序,最大沉底;
b.排列元素个数逐渐(从尾)减一,因为每趟排序,最后一位已确定;
c.每次冒泡序列:0 ~ i-1
TimeCost:O(N^2)
SpaceCost:O(N)
代码:
void BubbleSort(int[] nums){
int i,j;
for(i=nums.length; i>0; i--){
for(j=0; j<i; j++){
if(nums[j] > nums[j+1])
swap(nums[j], nums[j+1]);
}
}
}
(2)快速排序(划分排序、基准位排序)
a. 思想:基准位排序,每趟划分找出基准位,基准位左边小于它,基准位右边大于它;
b. 递归操作
递归原子操作:分别划分基准位左边序列(left,k-1) 和基准位右边序列(k+1,right);
递归判定条件:最小划分为单个元素,基准位为单个元素,此时left == right,所以判定条件为left < right;
c. 复杂度分析
Time Complexity:共(logN)趟划分,每趟划分耗时(O(N)),共耗时O(NlogN),所以O(NlogN);
Space Complexity:递归栈深度为N, 所以O(N);
代码:
/*启动函数*/
void StartQuickSort(int[] nums){
QuickSort(nums, 0, nums.length);
}
/*快排函数*/
void QuickSort(int[] nums, int left, int right){
int k = 0;
if(left < right){
k = Partition(nums, left, right);
QuickSort(nums, left, k-1);
QuickSort(nums, k+1, right);
}
}
/*划分函数, 返回基准元素*/
int Partition(int[] nums, int left, int right){
int pivot = left;
while(left < right){
while(nums[left] < nums[k]) left++;
while(nums[right] > nums[k]) right++;
if(left < right)
swap(nums[left], nums[right]);
}
swap(nums[pivot], nums[right]);
return right;
}
类型二、选择排序
(3) 简单选择排序:
a.每趟从已知序列中找出最小值,与首元素交换;
b.排列元素个数逐渐(从头)减一,因为每趟排序,首位已确定;
c.每次选择序列:i ~ len;
TimeCost:O(N^2)
SpaceCost:O(N)
代码:
void SelectSort(int[] nums){
int i,j,min;
for(i = 0; i<nums.length; i++){
for(j = i, j<nums.length;j++){
min = nums[j];
if(nums[j] < min)
min = nums[j]
}
swap(num[i], min);
}
}
(4)堆排序:
利用小顶堆,每次输出堆顶值(最小值);
TimeCost:O(NlogN)
SpaceCost:O(N)
类型三、插入排序
(5)直接插入排序:
a. 以首元素为有序序列,后面元素依次插入有序序列;
b. 每次插入序列:0 ~ i;
TimeCost:O(N^2)
SpaceCost:O(N)
代码:
void InsertSort(int[] nums){
int i,j;
for(i = 1; i<nums.length; i++){
for(j = 0; j<i; j++){
if(nums[j] > nums[j+1])
swap(nums[j], nums[j+1]);
}
}
}
(6)希尔排序
类型四、合并排序
(7)合并排序
a. 思想:
先分裂,再合并;
合并两个有序序列,最小的有序序列为单个;
b. 递归操作
递归原子操作:合并(left, mid)和(mid+1, right)两个有序序列
递归判定条件:取决于原子操作,单个有序序列只有一个元素,left和right相等,即可返回,所以判定条件为 left < right;
c. 复杂度分析
Time Complexity:O(NlogN)
Space Complexity:O(N)
代码:
int[] sort(int[] nums, int low, int high) {
int mid = (low + high) / 2;
if (low < high) {
// 左边分裂
sort(nums, low, mid);
// 右边分裂
sort(nums, mid + 1, high);
// 左右归并
merge(nums, low, mid, high);
}
return nums;
}
void merge(int[] nums, int low, int mid, int high) {
int[] temp = new int[high - low + 1];
int i = low; // 左指针
int j = mid + 1; // 右指针
int k = 0;
// 把较小的数先移到新数组中
while (i <= mid && j <= high) {
if (nums[i] < nums[j]) {
temp[k++] = nums[i++];
} else {
temp[k++] = nums[j++];
}
}
// 把左边剩余的数移入数组
while (i <= mid) {
temp[k++] = nums[i++];
}
// 把右边边剩余的数移入数组
while (j <= high) {
temp[k++] = nums[j++];
}
// 把新数组中的数,覆盖部分nums数组
for (int k2 = 0; k2 < temp.length; k2++) {
nums[k2 + low] = temp[k2];
}
}
类型五、基数排序(桶排序)
(8)基数排序