记录下十大排序算法的内核及改进。
不稳定排序:快选择谢尔顿。(快速、选择、希尔、堆)
算法分类:
![](https://i-blog.csdnimg.cn/blog_migrate/a95560d84495d63f6366fcf5e67bb963.png)
时间复杂度:
![](https://i-blog.csdnimg.cn/blog_migrate/c3e07b2206c42c97e51e55b893f3450a.png)
图片转自:https://www.cnblogs.com/onepixel/articles/7674659.html
快排的空间复杂度为O(log2n)
十大排序算法
一、比较排序
1. 交换排序
(一)冒泡排序
for(int i = 0; i < len - 1; i++)
{
for(int j = 0; j < len - i - 1; j++)
{
if(arr[j] > arr[j + 1]) swap(arr[j], arr[j + 1]);
}
}
(二)快速排序
简单版,但如果最左边的元素是最大值或最小值就会是最坏时间复杂度。
//一开始left = 0, right = len - 1;
void quickSort(int q[], int left, int right)
{
if (left >= right) return;
int l = left - 1, r = right + 1, temp = q[left + right >> 1];
while (l < r)
{
while (q[++l] < temp);
while (q[--r] > temp);
if (l < r) swap(q[l], q[r]);
}
quickSort(q, left, r), quickSort(q, r + 1, right);
}
改进
//三值取中法
```cpp
int main()//测试
{
vector<int> arr = {5, 3, 6, 7, 2, 1};
quickSort(arr, 0, arr.size() - 1);
for(int i = 0; i < arr.size(); i++)
cout<<arr[i]<<" ";
return 0;
}
第k大数 lc215
https://leetcode.cn/problems/kth-largest-element-in-an-array/
class Solution {
public int findKthLargest(int[] nums, int k) {
int n = nums.length;
return qS(0, n - 1, nums, n - k);
}
public int qS(int left, int right, int[] nums, int k) {
if (left >= right)
return nums[k];
int l = left - 1, r = right + 1, tmp = nums[(left + right) / 2];
while (l < r) {
while (nums[++l] < tmp);
while (nums[--r] > tmp);
if (l < r) {
int a = nums[l];
nums[l] = nums[r];
nums[r] = a;
}
}
if (r >= k)
return qS(left, r, nums, k);
return qS(r + 1, right, nums, k);
}
}
class Solution:
def findKthLargest(self, nums: List[int], k: int) -> int:
def quickSort(left, right, k):
# 终止
if left >= right:
return nums[k]
l, r = left - 1, right + 1
mid = (left + right) // 2
x = nums[mid]
while l < r:
r -= 1
while nums[r] > x:
r -= 1
l += 1
while nums[l] < x:
l += 1
if l < r:
nums[l], nums[r] = nums[r], nums[l]
if r >= k:
return quickSort(left, r, k)
return quickSort(r + 1, right, k)
n = len(nums)
return quickSort(0, n - 1, n - k)
2. 插入排序
(一)插入排序
第一种:
int j, k;
for (int i = 1; i < len; i++)
{
j = i - 1;
k = arr[i];
while (j > -1 && k < arr[j] )
{
arr[j + 1] = arr[j];//比k大就往后移
j--;
}
arr[j + 1] = k;//把k填进去
}
第二种:
for(int i = 0; i < len; i++)
{
for(int j = i; j > 0; j--)
{
if(arr[j - 1] > arr[j]) swap(arr[j - 1], arr[j]);
}
}
(二)希尔排序
当d = 1时,最后一次排序可以视为插入排序。
int i, j, d, temp, n = arr.size();
d = n / 2;//设置增量
while (d > 0)//边界条件
{
for (i = d; i < n; i++)//对所有组采用直接插入排序
{
temp = arr[i];//对相隔d个为止一组采用直接插入排序
j = i - d;
while (j > -1 && temp < arr[j])
{
arr[j + d] = arr[j];
j = j - d;
}
arr[j + d] = temp;
}
d = d / 2;//减小增量
}
参考:https://www.jianshu.com/p/502153724b91
3. 选择排序
(一)简单选择排序
for(int i = 0; i < len - 1; i++)
{
for(int j = i + 1; j < len; j++)
{
if(arr[i] > arr[j]) swap(arr[i], arr[j]);
}
}
(二)堆排序
void heapAdjust(vector<int>& arr, int k, int end)
{
for(int i = 2 * k + 1; i <= end; i = i * 2 + 1)
{
if (i < end && arr[i] < arr[i + 1]) i++;
if (arr[k] > arr[i]) break;
else
{
swap(arr[k], arr[i]);
k = i;
}
}
}
void heapSort(vector<int> &arr, int len)
{
int i;
for (i = len / 2 - 1; i >= 0; i--) heapAdjust(arr, i, len - 1);
for (i = len - 1; i > 0; i--)
{
swap(arr[0], arr[i]);
heapAdjust(arr, 0, i - 1);
}
}
4. 归并排序
(一)二路归并排序
觉得太复杂的话应先从mergeSort函数看起,然后再看merge函数。
void merge(int left, int mid, int right, vector<int> &arr)
{
if(left >= right) return;
int n = right - left + 1;
int *temp = new int[n];//建立临时数组
int l = left, r = mid + 1, index = 0;
while(l <= mid && r <= right)
temp[index++] = arr[l] <= arr[r] ? arr[l++] : arr[r++];
while(l <= mid)
temp[index++] = arr[l++];
while(r <= right)
temp[index++] = arr[r++];
for(int i = 0; i < n; i++)//返回排序好的数组
{
arr[left + i] = temp[i];
}
delete []temp;
}
void mergeSort(int left, int right, vector<int> &arr)
{
if(left > right)//判断是否为合法输入
{
cout<<"非法输入,请检查输入的参数!"<<endl;
return;
}
else if(left == right) return;
int mid = (left + right) / 2;//找中点
mergeSort(left, mid, arr);//开始分组递归
mergeSort(mid + 1, right, arr);
merge(left, mid, right, arr);//排序
}
int main()//测试
{
vector<int> arr = {5, 3, 6, 7, 2, 1};
mergeSort(0, arr.size() - 1, arr);
for(int i = 0; i < arr.size(); i++)
cout<<arr[i]<<" ";
return 0;
}