美文网首页
【算法常用模板】总结(更新中)

【算法常用模板】总结(更新中)

作者: jenye_ | 来源:发表于2019-12-13 00:24 被阅读0次
  • 搜索类
  • 图类
  • 排序类
  • 并查集
  • 数学类
  • 位运算

Part1 搜索类

  • bfs 求迷宫问题最短路径(未验证)

#include<iostream>
#include<queue>
using namespace std;
//用于遍历的结构 (可以添加题目所要求的信息)
typedef struct Node{
    int x,y; 
    int step;
}NODE;

const int NUM = 100;  //地图最大范围,根据要求具体修改 
int M,N;
int m[NUM][NUM];      // 地图数组 
int vis[NUM][NUM]; 
bool check(NODE& node){
    int x = node.x;
    int y = node.y;
    //三种不可访问情况 
    if(x < 1 || y < 1 || x > M || y > N ) return 0; //地图边界判断(一定要最先判断) 
    if(vis[x][y]) return 0;                      //是否被访问过判断
    if(m[x][y] == '*') return 0;                 //是否是不可访问的节点判断(具体题目不同 假设为*) 
    //可访问 
    return 1; 
}

//判断是否是所求的节点 
bool checkRight(NODE& node){
    if(m[node.x][node.y] == '1') return 1; //假设1为目标
    return 0; 
}

int mov[4][2]={{0,1},{0,-1},
              {1,0},{-1,0}}; //用于移动的数组,这里是四个方向(具体问题具体分析) 
NODE bfs(NODE startNode){
    //初始化 
    queue<NODE> Q;
    vis[startNode.x][startNode.y] = 1;
    Q.push(startNode);
    //正式开始遍历 
    while(!Q.empty()){
        NODE nowNode = Q.front();       //获取判断节点
        if(checkRight(nowNode)) return nowNode; //达到目标节点,获取目标节点 
        //进行四个方向遍历(具体问题可能会不同)
        for(int i = 0; i < 4; i++){
            NODE nextNode;
            //下一个位置信息 
            nextNode.step = nowNode.step + 1;
            nextNode.x = nowNode.x + mov[i][0];
            nextNode.y = nowNode.y + mov[i][1];
            if(check(nextNode)){ //判断是否可访问; 
                vis[nextNode.x][nextNode.y] = 1; //标记为已访问 
                Q.push(nextNode); 
            } 
        }
             
        
    }
    
}

int main(){
    cin >> M >> N;
    for(int i = 1; i <= M; i++)
        for(int j = 1; j <= N; j++)
            cin >> m[i][j];
    //初始节点(根据题目具体要求位置)
    NODE sNode;
    sNode.step = 0;
    sNode.x = 1; 
    sNode.y = 1; 
    NODE targetNode = bfs(sNode);
    cout << targetNode.step << endl; //输出题目要的节点信息 
}

  • dfs

求总的路径数目


Part2 图类

  • 最小生成树 (Prim)

#include<iostream>
using namespace std;
const int INF = 0x3fffffff;
int vis[N];
void prim(int c[][],int u) {
    int i,j;
    vis[u] = 1; 
    for(i = 1; i <= N; i++) {
        closet[i] = c[u][i];    
    }
    for(i = 0; i < N; i++){
        int t = u;
        int min = INF;
        int j;
        for(j = 1; j <= N; j++){
            if(!vis[u] && lowcost[j] < min){
                min = closet[j];
                t = j;
            }
        }
        if (t == u) break;
        for(j = 1; j <= N; j++){
            if(!vis[j] && lowcost[j]>c[t][j]){
                lowcost[j] = c[t][j];
            }
        }
    } 
}
  • 单元最短路 (DJ)

const int  MAXINT = 32767;
const int MAXNUM = 10;
int dist[MAXNUM];
int prev[MAXNUM];

int A[MAXUNM][MAXNUM];

void Dijkstra(int v0)
{
    bool S[MAXNUM];                                  // 判断是否已存入该点到S集合中
      int n=MAXNUM;
    for(int i=1; i<=n; ++i)
    {
        dist[i] = A[v0][i];
        S[i] = false;                                // 初始都未用过该点
        if(dist[i] == MAXINT)    
              prev[i] = -1;
        else 
              prev[i] = v0;
     }
     dist[v0] = 0;
     S[v0] = true;   
    for(int i=2; i<=n; i++)
    {
         int mindist = MAXINT;
         int u = v0;                               // 找出当前未使用的点j的dist[j]最小值
         for(int j=1; j<=n; ++j)
            if((!S[j]) && dist[j]<mindist)
            {
                  u = j;                             // u保存当前邻接点中距离最小的点的号码 
                  mindist = dist[j];
            }
         S[u] = true; 
         for(int j=1; j<=n; j++)
             if((!S[j]) && A[u][j]<MAXINT)
             {
                 if(dist[u] + A[u][j] < dist[j])     //在通过新加入的u点路径找到离v0点更短的路径  
                 {
                     dist[j] = dist[u] + A[u][j];    //更新dist 
                     prev[j] = u;                    //记录前驱顶点 
                  }
              }
     }
}
  • 多源最短路 (Floyd)

typedef struct          
{        
    char vertex[VertexNum];                                //顶点表         
    int edges[VertexNum][VertexNum];                       //邻接矩阵,可看做边表         
    int n,e;                                               //图中当前的顶点数和边数         
}MGraph; 
void Floyd(MGraph g)
{
   int A[MAXV][MAXV];
   int path[MAXV][MAXV];
   int i,j,k,n=g.n;
   for(i=0;i<n;i++)
      for(j=0;j<n;j++)
      {   
             A[i][j]=g.edges[i][j];
            path[i][j]=-1;
       }
   for(k=0;k<n;k++)
   { 
        for(i=0;i<n;i++)
           for(j=0;j<n;j++)
               if(A[i][j]>(A[i][k]+A[k][j]))
               {                     A[i][j]=A[i][k]+A[k][j];
                     path[i][j]=k;
                } 
     } }

Part3 排序类

  • 数组排序 sort

可对任意类型的数组排序。可以自定义排序规则

#include<algorithm>        //头文件
sort(数组名,数组名+数组长度) //自定义排序
sort(数组名,数组名+数组长度,cmp比较规则) //自定义排序
//自定义排序规则 
bool cmp(Node& a , Node& b){
    if(a.x == b.x) return a.y < b.y;
    return a.x < b.x;   
}
  • cmp排序函数的自定义方法:
    return true 就是a在b前
    return false 就是b在a前
  • 默认排序例子(小到大)
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 5;
int main(){
    int arr[N];
    for(int i = 0; i < 5; i++){
        cin >> arr[i]; 
    }
    sort(arr, arr + N);
    for(int i = 0; i < 5; i++){
        cout << arr[i] <<endl;
    }
    return 0;
}
  • 自定义排序例子
#include<iostream>
#include<algorithm>
using namespace std;

typedef struct NODE{
    int x,y;
}Node;

//自定义排序规则 
bool cmp(Node& a , Node& b){
    if(a.x == b.x) return a.y < b.y;
    return a.x < b.x;   
}
const int N = 5;
int main(){
    Node arr[N];
    for(int i = 0; i < 5; i++){
        cin >> arr[i].x >> arr[i].y;
    }
    sort(arr, arr + N, cmp); //自定义排序
    for(int i = 0; i < 5; i++){
        cout << arr[i].x << " " <<arr[i].y <<endl;
    }
    return 0;
}


  • 优先队列 priority_queue

用于动态排序的结构(需要不断的改变排序的元素)
如:哈夫曼树的构造

#include<queue>
priotrity_queue<ElemType> pq //默认定义 从大到小
priotrity_queue<ElemType, vector<ElemType>,cmp > pq 
//自定义排序规则 (有两种不用自己写的规则less<int>和greater<int> less和默认一样从大到小  greater从小到大)
struct cmp {
    bool operator() (Node& a , Node& b) {
        if (a.x == b.x) return a.y < b.y;
        return a.x < b.x;
    }
};
//基本方法
pq.push(node) //加入队列
pq.empty() //队列是否
pq.top() //获得队头元素(注意和queue的区别,queue是front)
pq.pop() //出队

注意:true false 对应的方向刚好与sort相反

  • 初步使用
#include<iostream>
#include<cstdio>
#include<queue>
#include<algorithm>
using namespace std;
const int N = 5;

int main(){

    priority_queue<int, vector<int>, greater<int> > pq; //整型从小到大
//  priority_queue<int, vector<int>, less<int> > pq; //整型从大到小 同priority_queue<int> pq; 
    int x;
    for(int i = 0; i < 5; i++){
        cin >> x;
        pq.push(x);
    }
    while(!pq.empty()){
        cout << pq.top()  <<endl;
        pq.pop();
    }
    return 0;
}
  • 自定义排序例子
#include<iostream>
#include<cstdio>
#include<queue>
#include<algorithm>
#define  Node ElemType
using namespace std;
const int N = 5;
typedef struct NODE{
    int x,y;
}Node;
//自定义排序规则
struct cmp {
    bool operator() (Node& a , Node& b) {
        if (a.x == b.x) return a.y < b.y;
        return a.x < b.x;
    }
};

int main(){
    Node arr[N];
    
    priority_queue<Node, vector<Node>, cmp> pq;

    for(int i = 0; i < 5; i++){
        cin >> arr[i].x >> arr[i].y;
        pq.push(arr[i]);
    }
    while(!pq.empty()){
        cout << pq.top().x << " " << pq.top().y <<endl;
        pq.pop();
    }
    return 0;
}

Part4 并查集

初始化数组为-1

find(int a); //找老大
union(int a, int b) // a集团加入b集团

不带路径压缩:

int find(int a){
    return boss[a]?find(a):a;
}
void union(int a, int b){
    int fa = find(a);
    int fb = find(b);
    boss[a] = b;
}

带路径压缩:

int find(int a){
    int bigBoss;
    int son = a;
    int temp;
    while(boss[a]) a = boss[a];
    bigBoss = a;  //找到大老板
    //把路径上的上司不是大老板的全部直属大老板
    while( son != bigBoss ){
         temp = boss[son];
         boss[son] = bigBoss;
         son = temp;
    }
    return bigBoss;
}
void union(int a, int b){
    int fa = find(a);
    int fb = find(b);
    boss[a] = b;
}

Part5 数学类

  • 最大公因数(辗转相除法)
int gcd(int a, int b){
  return b>0?gcd(b,a%b):a;
}
  • 最小公倍数
int gcd(int a, int b){
  return b>0?gcd(b,a%b):a;
}

int lcm(int a, int b){
  return a*b/gcd(a,b);
}

相关文章

  • 【算法常用模板】总结(更新中)

    搜索类 图类 排序类 并查集 数学类 位运算 Part1 搜索类 bfs 求迷宫问题最短路径(未验证) dfs 求...

  • Python/Numpy的一些高级用法(个人笔记)

    Python/numpy 常用与高级用法总结(实时更新)开始在商汤做算法研究员后,工作中要写大量python,但因...

  • 2018-01-28

    关于几种经典的非监督极化SAR分类算法的个人总结极化SAR一些常用知识总结(不断更新中)[精致Lee滤波的原创ma...

  • C++ 学习之(一):面试中的算法和准备过程

    面试中的算法和准备过程 从一道入门题说起 为什么要学习算法 如何准备面试算法 代码风格 了解算法面试的模板 常用工...

  • 常用算法模板

    动态规划(记忆化搜索) 给定一个包含非负整数的 m x n 网格,请找出一条从左上角到右下角的路径,使得路径上的数...

  • Paper Language

    本文总结了论文中的常用句式 持续更新中...

  • 总结几种常用的安全算法

    总结几种常用的安全算法

  • 常用排序算法

    常用的排序算法 在此总结一下常用排序算法的代码实现 #include using namespace std;t...

  • 计算机视觉 OpenCV Android | 基本特征检测 之

    模板匹配的 概述 以及 使用简介 模板匹配是最简单的模式识别算法之一,其在图像处理中经常用于从一副未知图像中,根据...

  • 模板模式

    概述 模板模式是在框架和实际编程当中常用到的编程方法。在书中看到模板模式的定义如下:定义一个操作中算法的骨架,而将...

网友评论

      本文标题:【算法常用模板】总结(更新中)

      本文链接:https://www.haomeiwen.com/subject/jgpxnctx.html