算法第四版- 2.1,2.2
排序基础篇
1.希尔排序
课本上的希尔排序
void ShellSort(vector<int> a)
{
int N = a.size();
int h = 1;
while (h < N / 3) h = 3 * h + 1;
while (h >= 1)
{
//将数组变成h有序
for (int i = h; i < N; i++)
{
//将a[i]插入到a[i-h],a[i-2*h],a[i-3*h]
for (int j = i; j >= h && a[j] < a[j - h]; j -= h)
{
swap(a[j], a[j - h]);
}
h = h / 3;
}
}
}
关于如何理解这段代码:
希尔排序-小灰的漫画算法
2.归并排序
这次不用书上的代码,用的左程云网课的代码
class Code01_MergeSort
{
public:
void mergeSort(int *arr, int size)
{
if (arr == nullptr || size < 2)
return;
process(arr, 0, size - 1);
}
void merge(int* arr, int L, int M, int R)
{
int* help = new int[R - L + 1];
int i = 0;
int p1 = L;
int p2 = M + 1;
while (p1 <= M && p2 <= R)
{
help[i++] = arr[p1] <= arr[p2] ? arr[p1++] : arr[p2++];
}
while (p1 <= M)
help[i++] = arr[p1++];
while (p2 <= R)
help[i++] = arr[p2++];
for (int i = 0; i < R - L + 1; i++)
arr[L + i] = help[i];
delete[]help;
}
void process(int* arr, int L, int R)
{
if (L == R) return;
int mid = L + (R - L) >> 2;
process(arr, L, mid);
process(arr, mid + 1, R);
merge(arr, L, mid, R);
}
};
杂记
1)选择排序+插入排序
2)基数排序
基数排序-漫画
然后,放一下左神的代码
#include <iostream>
#include <vector>
using namespace std;
void radixSort(int* arr,int size)
{
if (arr == nullptr || size < 2)
return;
radixSort(arr, 0, size - 1, maxbits(arr, size));
}
int maxbits(int* arr,int size)
{
int max1 = 0;
for (int i = 0; i < size; i++)
max1 = max(max1, arr[i]);
int res = 0;
while (max1 != 0)
{
res++;
max1 /= 10;
}
return res;
//最大值的位数
}
int getDigit(int x, int d)
{
return ((x / ((int)pow(10, d - 1))) % 10);
}
void radixSort(int* arr, int L, int R, int digit)
{
const int radix = 10;
int i = 0, j = 0;
vector<int> bucket(R - L + 1);
for (int d = 1; d <= digit; d++)//有多少位就进出多少次
{
//10个空间
//count[i], 当前位(d位)是(0~i)的数字有多少个
vector<int> count(radix);
for (i = L; i <= R; i++)
{
j = getDigit(arr[i], d); //把arr[i]在d位的数字取出来
count[j]++;
}
for (i = 1; i < radix; i++)
{
count[i] = count[i] + count[i - 1];
}
for (i = R; i >= L; i--)
{
j = getDigit(arr[i], d);
bucket[count[j] - 1] = arr[i];
count[j]--;
}
for (i = L, j = 0; i <= R; i++, j++)
{
arr[i] = bucket[j];
}
}
}
3)多变量排序方法
在做算法4习题2.1.21的时候,发现了并不是只有简单的一维的排序,还可能有多种状态。
在这举一些compare如何写,以及lambda表达式的写法。
我们来看一下LC第1337题
1337.矩阵中战斗力最弱的几行
sort的第三个参数
二维数组直接排序,这个方便的程度超出我想象了。
vector可以直接排序,本质是一个指针,排序方法从第一个元素到最后一个元素依次比较,不相等返回结果{1,1,0}>{1,0,0}
1.首先是lambda表达式版本的
class Solution {
public:
vector<int> kWeakestRows(vector<vector<int>>& mat, int k) {
int n=mat.size();
int m=mat[0].size();
vector<int> ans;
for(int i=0;i<n;i++) ans.push_back(i);
sort(ans.begin(),ans.end(),[&](const int& a,const int & b){return mat[a]==mat[b]?a<b:mat[a]<mat[b];});
vector<int> r(ans.begin(),ans.begin()+k);
return r;
}
};
2.其实我想要的是类似于哈希表,有first,second这种版本的
注意一下pair的使用
class Solution {
public:
vector<int> kWeakestRows(vector<vector<int>>& mat, int k) {
int n = mat.size();
vector<pair<int, int>> power;
for (int i = 0; i < n; ++i) {
int sum = accumulate(mat[i].begin(), mat[i].end(), 0);
power.emplace_back(sum, i);
}
sort(power.begin(), power.end());
vector<int> ans;
for (int i = 0; i < k; ++i) {
ans.push_back(power[i].second);
}
return ans;
}
};
3.其实我想要再补充一下的是结构体类型的cmp函数咋写,类似于下面这样吧,还补充了一下严格弱序:
严格弱序
4)插入排序的哨兵
哨兵最早是在王道视频里看到的。所以这次的代码参考咸鱼学长的
普通的插入排序如下:
void InsertSort(int A[], int n)
{
int i, j, temp;
for (i = 1; i < n; i++)
{
if (A[i] < A[i - 1])
{
temp = A[i];
for (j = i - 1; j >= 0 && A[j] > temp; --j)
A[j + 1] = A[j];
A[j + 1] = temp;
}
}
}
带哨兵的如下:
哨兵的好处就是不用再判断j>=0了
因为当j=0的时候,A[0]<A[j]不满足,自动就跳出了for循环。
备注:
例题2.2.11是对归并排序的改进,但是懒得再去看java代码了。
对于排序这边没什么兴趣,毕竟可以直接调sort函数