快速排序
void quick_sort(int arr[],int l, int r){
if(l >= r) return;
int i = l-1, j=r+1, x = arr[l+r >> 1];
while(i < j){
do i++; while(arr[i]<x);
do j--; while(arr[j]>x);
if(i<j) swap(arr[i],arr[j]);
}
quick_sort(arr,l,j);
quick_sort(arr,j+1,r);
}
快速选择
vector<int> arr;
int quick_sort(int l,int r,int k){
if(l>=r)//只剩一个元素,可以理解为快速排序结束,arr是一个有序数组
return arr[k];//k一定在该区间内 直接返回该元素
int x = arr[l], i = l - 1, j = r + 1;//取最左元素为基准
while(i<j){
do i++; while(arr[i]<x);//指针i右移,左边找到一个大于基准的便跳出循环
do j--; while(arr[j]>x);//指针j左移,右边找到一个小于基准的便跳出循环
if(i<j) swap(arr[i],arr[j]);//让左边都是小于基准的,右边都是大于基准的
}
if(k <= j)//第k个数在左半部分
return quick_sort(l,j,k);//去左边区间找
else
return quick_sort(j+1,r,k);//去右边区间找
}
归并排序
void merge_sort(vector<int>& arr,int l,int r){
if(l>=r) return;
int mid = l+r>>1;
merge_sort(arr,l,mid);
merge_sort(arr,mid+1,r);
int k = 0, i = l, j = mid + 1;
while(i<=mid && j<=r){
//因为先递归,所以最小区间是两个数进行对比,所以更大的区间内,左右两个区间是分别有序的
//所以这里直接顺序比较就可以了,不用担心左边区间会出现arr[i+1]<arr[i]的情况
if(arr[i] < arr[j])
temp[k++] = arr[i++];//把小的放到前面,如果左边的数更小选择左边
else
temp[k++] = arr[j++];
}
//上面的while循环结束后可能 i 还没达到 mid 或者 j 没达到r,但肯定有一个已经达到了
//那么剩余的数一定都是在左区间或者右区间更大的数
while(i <= mid)
temp[k++] = arr[i++];
while(j <= r)
temp[k++] = arr[j++];
for(i = l,k = 0;i <= r;i++, k++)//temp数组的长度只是部分数组l到r
arr[i] = temp[k];//把temp的k个元素赋给arr
}
解决逆序对数量问题,即
if arr[i]<arr[j]:res += mid - i + 1
二分
//查找左边界 SearchLeft 简写SL
int SL(int l, int r)
{
while (l < r)
{
int mid = l + r >> 1;
if (check(mid)) r = mid;
else l = mid + 1;
}
return l;
}
//查找右边界 SearchRight 简写SR
int SR(int l, int r)
{
while (l < r)
{
int mid = l + r + 1 >> 1; //需要+1 防止死循环
if (check(mid)) l = mid;
else r = mid - 1;
}
return r;
}
离散化
vector<int> alls;//待离散化的值
sort(alls.begin(), alls.end());
alls.erase(unique(alls.begin(),alls.end()), alls.end());
int find(int x){//找到第一个大于等于x的位置
int l = 0;
int r = alls.size()-1;
int mid = l+r>>1;
while(l<r){
if(alls[mid] >= x)
r = mid;
else
l = mid + 1;
}
return r+1;//映射到1,2...n 不+1则是0..n
}
区间合并
void merge(vector<PII>&segs)
{
vector<PII> res;
sort(segs.begin(),segs.end());
int l = -2e9,r = -2e9;
for(auto item:segs)
if(r < item.first)
{
if(l != -2e9) res.push_back({l,r});
l = item.first;
r = item.second;
}
else r = max(r,item.second);
if(l != -2e9) res.push_back({l,r});
segs = res;
}
单链表
int e[N],ne[N];//当前节点值和当前节点指向的下一个节点的指针
int head,idx;//头节点指针和当前节点指针
void init(){
head = -1;//空链表时头指针指向末尾,末尾指针用-1表示
idx = 1;//初始化从下标1开始
}
void add_to_head(int x){//将值x插入头节点
e[idx] = x;//当前指针插入一个值x
ne[idx] = head;//当前指针的下一个节点指向原本的头节点
head = idx;//头节点更新为当前指针
idx++;//当前指针向前移动
}
void add(int k,int x){//在第k个节点后插入一个节点
e[idx] = x;
ne[idx] = ne[k];//当前指针的下一个节点指向k的指向的节点
ne[k] = idx;//k指向的节点更新为插入的节点
idx++;//当前指针向前移动
}
void del(int k){//删除第k个节点指向的节点,即k后面的一个节点
ne[k] = ne[ne[k]];
}
栈
if(op == "push"){
int num;
cin>>num;
a[++top] = num;
}
if(op == "pop"){
top--;
}
if(op == "query"){
cout<<a[top]<<endl;
}
if(op == "empty"){
cout<<(top == -1?"YES":"NO")<<endl;
}
STL栈
vector<int> stack;
int m,x;
string op;
cin >> m;
while (m--) {
cin >> op;
if (op == "push") {
cin >> x;
stack.push_back(x);
}
else if (op == "pop") {
stack.pop_back();
}
else if (op == "empty") {
if (stack.size() == 0) {
cout << "YES" << endl;
}
else {
cout << "NO" << endl;
}
}
else if (op == "query") {
cout << stack.back() << endl;
}
}
队列
int head = 0;
int tail = -1;
while(m--){
string op;
cin>>op;
if(op == "push"){
int x;
cin>>x;
a[++tail] = x;
}
if(op == "pop"){
head++;
}
if(op == "empty"){
cout<<(head>tail?"YES":"NO")<<endl;
}
if(op == "query"){
cout<<a[head]<<endl;
}
}
单调队列
#include<deque>
deque<int> q;
for(int i = 1;i<=n;i++){
cin>>a[i];
//求最大值
while(!q.empty() && a[i] > q.back()){//插入的值比队尾的值更大
q.pop_back();//弹出队尾
}
q.push_back(a[i]);//入队
if(i-k>=1 && q.front() == a[i-k]){//a[i-k]是上一个窗口的元素,如果还在队列内作为队头则要删去
q.pop_front();//弹出队头
}
if(i >= k){//当窗口大小达到k时,以后每次移动,队头元素都是要求的元素
cout<<q.front()<<" ";
}
}
并查集
int Find(int x){//寻找祖宗节点+路径压缩
if(x != pre[x])
pre[x] = Find(pre[x]);//把父结点设置为父结点的父结点,直到父结点已经是根结点
return pre[x];
}
void Union(int i,int j){//将i和j并入一个集合
pre[Find(i)] = Find(j);//把i的父结点的父结点设置为j的父结点
}
DFS
void dfs(int u){
if(u > n){
for(int i = 1;i<=n;i++)
cout<<path[i]<<" ";
cout<<endl;
return;
}
for(int i = 1;i<=n;i++){
if(!st[i]){
path[u] = i;
st[i] = 1;
dfs(u + 1);
st[i] = 0;
}
}
}
邻接表
// 对于每个点k,开一个单链表,存储k所有可以走到的点。h[k]存储这个单链表的头结点
int h[N], e[N], ne[N], idx;
// 添加一条边a->b
void add(int a, int b)
{
e[idx] = b, ne[idx] = h[a], h[a] = idx ++ ;
}
// 初始化
idx = 0;
memset(h, -1, sizeof h);
DFS遍历图
int dfs(int u)
{
st[u] = true; // st[u] 表示点u已经被遍历过
for (int i = h[u]; i != -1; i = ne[i])
{
int j = e[i];
if (!st[j]) dfs(j);
}
}
BFS遍历图
queue<int> q;
st[1] = true; // 表示1号点已经被遍历过
q.push(1);
while (q.size())
{
int t = q.front();
q.pop();
for (int i = h[t]; i != -1; i = ne[i])
{
int j = e[i];
if (!st[j])
{
st[j] = true; // 表示点j已经被遍历过
q.push(j);
}
}
}
朴素Dijkstra
时间复杂是 O ( n 2 + m ) O(n2+m) O(n2+m), n n n表示点数, m m m表示边数文章来源:https://www.toymoban.com/news/detail-541267.html
int g[N][N]; // 存储每条边
int dist[N]; // 存储1号点到每个点的最短距离
bool st[N]; // 存储每个点的最短路是否已经确定
// 求1号点到n号点的最短路,如果不存在则返回-1
int dijkstra()
{
memset(dist, 0x3f, sizeof dist);
dist[1] = 0;
for (int i = 0; i < n - 1; i ++ )
{
int t = -1; // 在还未确定最短路的点中,寻找距离最小的点
for (int j = 1; j <= n; j ++ )
if (!st[j] && (t == -1 || dist[t] > dist[j]))
t = j;
// 用t更新其他点的距离
for (int j = 1; j <= n; j ++ )
dist[j] = min(dist[j], dist[t] + g[t][j]);
st[t] = true;
}
if (dist[n] == 0x3f3f3f3f) return -1;
return dist[n];
}
堆优化Dijkstra
时间复杂度 O ( m l o g n ) O(mlogn) O(mlogn), n n n表示点数, m m m表示边数文章来源地址https://www.toymoban.com/news/detail-541267.html
typedef pair<int, int> PII;
int n; // 点的数量
int h[N], w[N], e[N], ne[N], idx; // 邻接表存储所有边
int dist[N]; // 存储所有点到1号点的距离
bool st[N]; // 存储每个点的最短距离是否已确定
// 求1号点到n号点的最短距离,如果不存在,则返回-1
int dijkstra()
{
memset(dist, 0x3f, sizeof dist);
dist[1] = 0;
priority_queue<PII, vector<PII>, greater<PII>> heap;
heap.push({0, 1}); // first存储距离,second存储节点编号
while (heap.size())
{
auto t = heap.top();
heap.pop();
int ver = t.second, distance = t.first;
if (st[ver]) continue;
st[ver] = true;
for (int i = h[ver]; i != -1; i = ne[i])
{
int j = e[i];
if (dist[j] > distance + w[i])
{
dist[j] = distance + w[i];
heap.push({dist[j], j});
}
}
}
if (dist[n] == 0x3f3f3f3f) return -1;
return dist[n];
}
文件读写
C读写
#include<stdio.h>
int n,m;
FILE* inputFile = fopen("filepath","r");
FILE* outputFile = fopen("filepath","w");
while(fscanf(inputFile,"%d%d",&n,&m) != EOF){
fprintf(outputFile,"%d %d\n",n,m);
fclose(inputFile);
fclose(outputFile);
}
C++读写
#include<fstream>
ifstream inputFile("inputpath");
ofstream outputFile("outputpath");
int n,m,a[100];
inputFile>>n>>m;
for(int i = 0;i<n;i++){
int x,y;
inputFile>>x>>y;
a[i] = x+y;
}
for(int i = 0;i<n;i++){
outputFile<<a[i];
}
string line;
while(getline(inputFile,line)){
outputFile<<line<<endl;
}
快速幂
int quick_mi(ll a,ll b,ll p){
ll res = 1;
while(b){
if(b&1) res = res*a%p;
b = b>>2;
a = a*a%p;
}
return res;
}
进制转换
ll getNum(char c){
if(c >='0' && c<='9')
return c - '0';
if(c >='A' && c<='Z')
return c - 'A' + 10;
if(c >= 'a' && c<='z')
return c - 'a' + 10;
}
void m2n(string x,int m,int n){
reverse(x.begin(),x.end());
ll num = 0;
/*m进制转10进制*/
for(int i = 0;i<x.size();i++)
if(i > 0) num += getNum(x[i])*pow(m,i);
else num += getNum(x[i]);
/*10进制转n进制*/
while(num){
ll t = num%n;
num /= n;
if(t>=0 && t<=9) ans.push_back(t+'0');
else ans.push_back(t - 10 + 'a');
}
for(int i = ans.size()-1; i>=0 ;i--)
cout<<ans[i];
}
日期计算
public:
bool isLeapYear(int year) {
return year%400 == 0 || year%4==0 && year%100!=0;
}
int daysBetweenDates(string date1,string date2){
if (date1.compare(date2) > 0) return daysBetweenDates(date2, date1);
int month_len[13] = {0,31,28,31,30,31,30,31,31,30,31,30,31};
int year1,year2,month1,month2,day1,day2;
int ans = 0;
stringstream ss(date1);
ss >> year1;ss.ignore();ss >> month1;ss.ignore();ss >> day1;
stringstream ss2(date2);
ss2 >> year2;ss2.ignore();ss2 >> month2;ss2.ignore();ss2 >> day2;
//计算年份
for(int year = year1;year < year2;year++)
ans += 365 + isLeapYear(year);
//计算月份和天数
for(int m = 1;m < month1;m++)
day1 += month_len[m] + (isLeapYear(year1) && m==2);
for(int m = 1;m < month2;m++)
day2 += month_len[m] + (isLeapYear(year2) && m==2);
return ans + day2 - day1;
}
到了这里,关于算法基础模板 快排、快选、归并、二分、离散化、区间合并、链表、图搜索、最短路等的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!