这是我参与「第三届青训营-后端场」笔记创作活动的的第3篇笔记。
快速排序
快速排序作为经典的排序算法,可以说人人都会。
其思想为,在待排序数组中取一个值X,随后将数组中比X小的数放在X左边,比X大的数放在X右边,这样就完成了一轮排序。随后对X左边和右边的所有数分别看作一个新数组,按照上述规则进行排序,重复这个过程,直到待排序数组大小为1时,这样就能得到一个有序数组。
快速排序算法的关键是选取X与如何将数组中比X小的数放在X左边,比X大的数放在X右边。
其中选取X可以随机的选取,这样可以保证其因为数据的原因对排序的算法的时间复杂度影响降低到最小。
划分的过程可以使用双指针交换。
/*
*@File Name :quickSort.cpp
*@Author :cc
*@Version :1.0.0
*@Date :2022/4/7 9:22
*@Description :
*@Function List :
*@History :
*/
#include "vector"
#include "algorithm"
#include "ctime"
using namespace std;
void quickSort(vector<int> &nums, int l, int r) {
if (l >= r) return;
int k = rand() % (r - l + 1) + l;
swap(nums[k], nums[l]);
int i = l, j = r;
while (i < j) {
while (i < j && nums[j] >= nums[l]) j--;
while (i < j && nums[i] <= nums[l]) i++;
if (i < j) swap(nums[i], nums[j]);
}
swap(nums[l], nums[i]);
quickSort(nums, l, i - 1);
quickSort(nums, i + 1, r);
}
vector<int> sortArray(vector<int> &nums) {
srand((unsigned) time(NULL));
quickSort(nums, 0, nums.size() - 1);
return nums;
}
堆排序
堆排序其实就是建立一个有序的二叉树,或者一个堆,根据规则不同堆的构成不同,我们以大顶堆为例子。
大顶堆中,堆顶的元素为整个堆的最大值,那么对于每一次,我们将堆顶元素取出来之后,需要调整堆,保证堆顶的元素仍然是最大值。
每次调整的规程其实就是将当前节点的值,与其儿子节点的值比较,如果当前节点的值比儿子节点值大,则不需要调整,或者就需要交换当前节点的值与儿子节点的值中较大的那个值,以此维护堆。
/*
*@File Name :heapSort.cpp
*@Author :cc
*@Version :1.0.0
*@Date :2022/4/7 9:28
*@Description :
*@Function List :
*@History :
*/
#include "vector"
#include "algorithm"
using namespace std;
void sift_down(vector<int> &nums, int start, int end) {
int p = start;
int ch = p * 2 + 1;
while (ch <= end) {
if (ch + 1 <= end && nums[ch + 1] > nums[ch]) ch++;
if (nums[p] >= nums[ch]) return;
swap(nums[p], nums[ch]);
p = ch;
ch = p * 2 + 1;
}
}
vector<int> sortArray(vector<int> &nums) {
int n = nums.size() - 1;
for (int i = (n - 1) / 2; i >= 0; --i)
sift_down(nums, i, n);
for (int i = n; i > 0; --i) {
swap(nums[0], nums[i]);
sift_down(nums, 0, i - 1);
}
return nums;
}