算法总结
参见 幺幺山的博客
选择排序
void selectSort(vector<int>& nums) {
int n = nums.size();
for (int i = 0; i < n - 1; ++i) {
int k = i;
for (int j = i + 1; j < n; ++j) {
if (nums[j] < nums[k]) {
k = j;
}
}
swap(nums[i], nums[k]);
}
}
冒泡排序
void bubbleSort(vector<int>& nums) {
int n = nums.size();
for (int i = n - 1; i > 0; --i) {
bool flag = false;
for (int j = 0; j < i; ++j) {
if (nums[j] > nums[j + 1]) {
swap(nums[j], nums[j + 1]);
flag = true;
}
}
if (!flag) return;
}
}
插入排序
void insertSort(vector<int>& nums) {
int n = nums.size();
for (int i = 1; i < n; ++i) {
for (int j = i; j > 0 && nums[j] < nums[j - 1]; --j) {
swap(nums[j], nums[j - 1]);
}
}
}
希尔排序
void shellSort(vector<int>& nums) {
int n = nums.size();
for (int h = n / 2; h >= 1; h /= 2) {
for (int i = h; i < n; ++i) {
for (int j = i; j >= h && nums[j] < nums[j - h]; j -= h) {
swap(nums[j], nums[j - h]);
}
}
}
}
归并排序
void sort(vector<int>& nums) {
mergeSort(nums, 0, nums.size() - 1);
}
void mergeSort(vector<int>& nums, int l, int r) {
if (l <= r) return;
int mid = l + (r - l) / 2;
mergeSort(nums, l, mid);
mergeSort(nums, mid + 1, r);
merge(nums, l, mid, r);
}
void merge(vector<int>& nums, int l, int mid, int r) {
vector<int> tmp(l - r + 1);
int i = l, j = mid + 1, k = 0;
while (i <= mid && j <= r) {
if (nums[i] <= nums[j]) tmp[k++] = nums[i++];
else tmp[k++] = nums[j++];
}
while (i <= mid) tmp[k++] = nums[i++];
while (j <= r) tmp[k++] = nums[j++];
for (k = 0, i = l; i <= r; ++i, ++k) {
nums[i] = tmp[k];
}
}
快速排序
void sort(vector<int>& nums) {
quickSort(nums, 0, nums.size() - 1);
}
void quickSort(vector<int>& nums, int low, int high) {
if (low >= high) return;
int pivot = partition(nums, low, high);
quickSort(nums, low, pivot - 1);
quickSort(nums, pivot + 1, high);
}
int partition(vector<int>& nums, int low, int high) {
int pivot = nums[low];
while (low < high) {
while (low < high && nums[high] >= pivot) --high;
nums[low] = nums[high];
while (low < high && nums[low] <= pivot) ++low;
nums[high] = nums[low];
}
nums[low] = pivot;
return low;
}
堆排序
概述
- 堆中某个节点的值总是大于等于其子节点的值,并且堆是一颗完全二叉树
- 位置 k 的节点的父节点位置为 k/2,而它的两个子节点的位置分别为 2k 和 2k+1;这里不使用数组索引为 0 的位置
插入元素
- 将新元素放到数组末尾,然后上浮到合适的位置
- 从位置k上浮的代码:
void swim(int k) {
while (k > 1 && nums[k] > nums[k / 2]) {
swap(nums[k], nums[k / 2]);
k /= 2;
}
}
删除最大元素
- 从数组顶端删除最大的元素,并将数组的最后一个元素放到顶端,并让这个元素下沉到合适的位置
- 从位置k下沉的代码:
void sink(int k) {
while (k * 2 < nums.size()) {
int j = k * 2;
if (j + 1 < nums.size() && nums[j] < nums[j + 1]) ++j;
swap(nums[k], nums[j]);
k = j;
}
}
堆排序
void heapSort(vector<int> nums) {
for (int i = (nums.size() - 1) / 2; i >= 1; --i) { // 处理非叶子节点
sink(i);
}
for (int i = nums.size() - 1; i > 1; --i) {
swap(nums[i], nums[1]);
sink(1);
}
}
桶排序
- 先把数据分到多个桶中,类似于哈希表拉链
- 对每个桶进行排序
- 扩展:基数排序 https://www.cnblogs.com/skywang12345/p/3603669.html