算法笔记-经典模板

BFS模板

void BFS(int s){
    queue q;
    q.push(s);
    while(!q.empty()){
        取出队首元素front;
        访问队首元素front;
        将队首元素出队;
        将front的下一层结点中未曾入队的结点全部入队,并设置已入队
    }
}

DFS模板

递归

priority_queue的cmp函数模板:

struct fruit{
    string name;
    int price;
}

struct cmp{
    bool operator () (fruit f1,fruit f2){
        return f1.price > f2.price;
    }
}

int main(){
    priority_queue,cmp> q;
    return 0;
}

中序序列和先序序列、后序序列、层序序列配合重建二叉树的模板:

//记住create函数模板,不管中序和谁配合,模板如下
//postL是后序序列的左端点
//postR是后序序列的右端点
//inL是中序序列的左端点
//inR是中序序列的右端点
//postOrder是后序序列
//inOrder是中序序列
node* create(int postL,int postR,int inL,int inR){    
    if(postL>postR){
        return NULL;
    }
    int in = postOrder[postR];
    node* root = new node;
    root->data = in;
    int k;
    for(k=inL;k<=inR;k++){
        if(inOrder[k]==in){
            break;
        }
    }

    int numLeft = k-inL;//这一步一定要有

    root->lChild = create(postL,postL+numLeft-1,inL,inL+numLeft-1);
    root->rChild = create(postL+numLeft,postR-1,inL+numLeft+1,inR);
    return root;
}

并查集寻找根节点的模板:

//递归写法
int findFather(int n){
    if(n==father[n]){
        return n;
    }
    else{
        //小括号和中括号要分开
        return findFather(father[n]);
    }
}

并查集合并集合的模板:

void unionS(int a,int b){
    int fA = findFather(a);
    int fB = findFather(b);
    if(fA != fB){
        father[fA] = fB;
    }
    return;
}

迪杰斯特拉算法+新增点权+求最短路径条数:

void Dij()
{
    //以下三行是初始化工作:
    //起点到起点的距离是0;
    //起点到起点的最短路径有1条;
    //起点到起点累计可以获得的最大资源=该起点本身拥有的资源
    d[now]  = 0;
    shortestNum[now] =1;
    maxRescue[now] = cityRescue[now];
    
    //整个for循环中没有用到i的地方,i只用来计数
    for(int i=0; i d[u]+roadLen)
                {
                    d[number] = d[u]+roadLen;
                    shortestNum[number] = shortestNum[u];
                    //如果最短路径变了,那么累计获得的最大资源要无条件改变
                    maxRescue[number] = maxRescue[u]+cityRescue[number];
                }
                else if(d[number]==d[u]+roadLen)
                {
                    shortestNum[number] += shortestNum[u];
                    //如果最短路径没变,那么累计获得的最大资源要有条件改变
                    if(maxRescue[u]+cityRescue[number]>maxRescue[number]){
                        maxRescue[number] = maxRescue[u]+cityRescue[number];
                    }
                }
            }
        }
    }

}

弗罗伊德算法模板

void Floyed()
{
    for(int k=0; k

普里姆算法模板

//G为图,一般设置成全局变量;数组d为顶点与集合S的最短距离
Prime(G,d[]){
    初始化;
    for(循环n次){
        u = 使d[u]最小的还未被访问的顶点的标号;
        记u已被访问;
        for(从u出发能到达的所有顶点v){
            if(v未被访问 && 以u为中介点使得v与集合S的最短距离d[v]更优){
                将G[u][v]赋值给v与集合S的最短距离d[v];
            }
        }
    }
}

求素数模板

//给定一个数,判断它是不是素数
#include 
#include 
#include 
using namespace std;

//核心代码
bool isPrime(int n){
    if(n<=1){
        return false;
    }
    int a = (int)sqrt(1.0*n);//向下取整
    for(int i=2; i<=a; i++){
        if(n%i==0){
            return false;
        }
    }
    return true;
}


int main()
{
    int n;
    scanf("%d",&n);
    bool is = isPrime(n);
    if(is){
        printf("Yes");
    }
    else{
        printf("No");
    }
    return 0;
}

求素数表模板(埃氏筛法)

//求1到n之间的所有素数,
#include 
#include 
using namespace std;
const int maxn = 1000;
bool is[maxn] = {false};
int prime[maxn];
int p=0;
int n;

//核心代码
void findPrime(){
    for(int i=2;i<=n;i++){
        if(!is[i]){
            prime[p] = i;
            p++;
            for(int j=i+i;j<=n;j = j+i){
                is[j] = true;
            }
        }
    }
}


int main()
{
    scanf("%d",&n);
    findPrime();
    for(int i=0; i

求解最大公约数的模板

//给定两个数n和m,求n和m的最大公约数a
#include 
#include 
using namespace std;


//核心代码;不必关心a和b的大小,默认a>b,就算ab
int gcd(int a,int b){
    if(b==0){
        return a;
    }
    else{
        return gcd(b,a%b);
    }
}


int main()
{
    int n;
    int m;
    scanf("%d%d",&n,&m);
    int a = gcd(n,m);
    printf("%d",a);
    return 0;
}

求解最小公倍数的模板

//给定两个数n和m,求n和m的最小公倍数b
#include 
#include 
using namespace std;

//核心代码
int gcd(int a,int b){
    if(b==0){
        return a;
    }
    else{
        return gcd(b,a%b);
    }
}


int main()
{
    int n;
    int m;
    scanf("%d%d",&n,&m);
    int a = gcd(n,m);
    int b = (n/a)*m;//先求最大公约数,然后再求最小公倍数
    printf("%d",b);
    return 0;
}

求斐波拉契数列模板(动态规划方法)

一个问题能用动态规划方法求解,需要满足以下两个条件:

  1. 存在重叠子问题。
  2. 存在最优子结构(全局问题的最优解可以由局部问题的最优解构成)
//n为45的时候,F(n)就已经有10位数了,超过45的时候,就超过int的极限了,而int是有符号数,符号位发生了改变
#include 
#include 
using namespace std;
const int maxn = 1000;
int dp[maxn];

//核心代码
int F(int n){
    if(n==0 || n==1){
        return 1;
    }
    //这一步让计算复杂度降低很多
    else if(dp[n]!=-1){
        return dp[n];
    }
    else{
        dp[n] = F(n-1)+F(n-2);
        return dp[n];
    }
}


int main()
{
    for(int i=0; i

sort函数

使用sort函数前,进行如下声明:

#include 
using namespace std;
sort(首元素地址(必填),尾元素地址的下一个地址(必填),比较函数(非必填))
#include 
#include 
#include 

using namespace std;
const double pi = acos(-1.0);
const double eps = 1e-8;
#define EQU(a,b) (fabs((a)-(b))eps)
#define LESS(a,b) (((a)-(b))<(-eps))
#define GREATER_EQU(a,b) (((a)-(b))>(-eps))
#define LESS_EQU(a,b)  (((a)-(b))<(eps))

struct node{
    int id;
    string name;
    double grade;
}tmp[3];

bool cmp2(node a,node b){
    if(EQU(a.grade,b.grade)){
        //成绩相同时按照字典序排列
        return a.name >b.name;
    }
    else{
        //成绩高的在前面
        return GREATER(a.grade,b.grade);
    }
}


bool cmp(double a,double b){
    return a>b;
}

int main() {
    double a[] = {1.2,4.3,-2.34,23.44};
    sort(a,a+3);
    for(int i=0; i<4; i++){
        printf("%lf\n",a[i]);
    }
    printf("---------------------------------\n");

    double b[] = {1.0,2.0,3.0,4.0};
    sort(b,b+4,cmp);
    for(int i=0; i<4; i++){
        printf("%lf\n",b[i]);
    }
    printf("---------------------------------\n");

    tmp[0].grade=12.33;
    tmp[0].id=1;
    tmp[0].name="Jack";

    tmp[1].grade=12.33;
    tmp[1].id=2;
    tmp[1].name="Rose";

    tmp[2].grade=13.33;
    tmp[2].id=3;
    tmp[2].name="Tom";
    sort(tmp,tmp+3,cmp2);
    for(int i=0; i<3; i++){
        printf("%d\t%s\t%.2f\n",tmp[i].id,tmp[i].name.c_str(),tmp[i].grade);
    }
    return 0;
}

算法笔记-经典模板_第1张图片

priority_queue中自定义优先级

#include 
#include 
using namespace std;

struct fruit{
    string name;
    int price;
    friend bool operator < (fruit f1,fruit f2){
        return f1.price>f2.price;
    }
}f1,f2,f3;

int main() {
    priority_queue q;
    f1.name = "taozi";
    f1.price = 3;
    f2.name = "lizi";
    f2.price = 4;
    f3.name = "pingguo";
    f3.price = 1;
    q.push(f1);
    q.push(f2);
    q.push(f3);
    cout<

算法笔记-经典模板_第2张图片

将string类型变量转化为int、long、float、double型变量

C语言转换形式:

std::string str;
int i = atoi(str.c_str());

C++转换形式(C++11):

std::string str;
int i = std::stoi(str);

同样, 可以使用 stol(long), stof(float), stod(double) 等.

参考文章

将int、long、float、double型变量转化为string类型变量

to_string( )函数方法是C++11新增的对数字转为字符串string类对象的新功能,主要函数接口如下:

std::to_string
  C++  Strings library std::basic_string  Defined in header 
std::string to_string( int value );
std::string to_string( long value );
std::string to_string( long long value );
std::string to_string( unsigned value );
std::string to_string( unsigned long value );
std::string to_string( unsigned long long value );
std::string to_string( float value );
std::string to_string( double value );
std::string to_string( long double value );

功能真的很强大而且也很方便。使用如下:

#include
#include
using namespace std;

string str = to_String(123405);

参考文章

将单个字符char转化为string

使用push_back()

char c = 'a';
string s1;
s1.push_back(c);

更多方法:

const char c = 'a';
//1.使用 string 的构造函数
string s(1,c);

//2.声明string 后将char push_back
string s1;
s1.push_back(c);

//3.使用stringstream
stringstream ss;
ss << c;
string str2 = ss.str();

//注意 使用to_string 方法会转化为char对应的ascii码,原因是 to_string 没有接受char型参数的函数原型,

//有一个参数类型为int的函数原型,所以传入char型字符,实际是先将char转化为int型的ascii码,然后再转变为

//string,以下输出结果为97

cout << to_string(c) << endl;

参考文章

将单个字符string转化为char

使用c_str()将string转化为char数组,这个数组其实只有一个元素,就是我们要的char元素

string f = "m";
const char *g1 = f.c_str();
printf("%s\n",g1);

数字字符和数字的互相转换

//对于1位数字而言,其整数形式和字符形式差一个'0'
#include 
#include 
using namespace std;

int main()
{
    //字符变数字
    char a='3';
    int b = a-'0';
    int c = b+2;
    printf("%d\n",c);
    
    //数字变字符
    int d = 6;
    char e = d+'0';
    printf("%c\n",e);
    return 0;
}

算法笔记-经典模板_第3张图片

小写字母和大写字母的互相转换

//小写字母比大写字母大32
#include 
#include 
using namespace std;

int main()
{
    char a = 'A';
    printf("%c\n",a+32);
    char b = 'g';
    printf("%c\n",b-32);
    return 0;
}

算法笔记-经典模板_第4张图片

将int型数组转换为int型整数

//用户指定输入a位数,然后输入a位数,形成int型数组,然后将int型数组转化为int型整数
#include 
#include 
using namespace std;
const int maxn = 1000;
int num[maxn];
int a;

int toInt(){
    int sum = 0;
    for(int i=0; i

将int型整数转换为int型数组

写下面这段代码时得到一个教训

全局变量和局部变量不能同名,否则会出现无法发现的错误

#include 
#include 
#include 
using namespace std;
const int maxn = 1000;
int n;
int num[maxn];
int k=0;

//核心代码
void toArray(){
    for(int i=0; i=pow(10,k)){
        k++;
    }
    toArray();
    for(int i=0; i

算法笔记-经典模板_第5张图片

sscanf和sprintf模板

作用是实现字符串数字的转换。

sscanfsprintf均在stdio.h头文件下。

scanf("%d",&n);
printf("%d",n);

可以写成下面的样子,screen代表屏幕:

scanf(screen,"%d",&n);//将屏幕上用户输入的字符串写到n里(自左向右)
printf(screen,"%d",n);//将n的内容以字符串的形式显示在屏幕上(自右向左)

把screen换成字符数组str,就是sscanf和sprintf的用法:

sscanf(str,"%d",&n);//将str中的内容写到n里(自左向右)
sprintf(str,"%d",n);//将n的内容以字符串的形式写到str上(自右向左)

典型应用如下:

#include 
#include 
using namespace std;
int main()
{
    char str[10] = "123";
    int a;
    sscanf(str,"%d",&a);//将字符串转化为数字
    printf("%d\n",a);
    int b = 124332;
    char stt[20];
    sprintf(stt,"%d",b);//将数字转化为字符串
    printf("%s\n",stt);
    return 0;
}

算法笔记-经典模板_第6张图片

高级应用如下:

先修知识1:

读入double型变量的语法:

double a;
scanf("%lf",&a);

输出double型变量的语法:

printf("%f",a);

或者

printf("%.2f",a);

先修知识2:

初始化字符数组的方法:

char str[100]= "123a";

//注释中为错误写法
//char str[100];
//str= "123a";

//注释中为错误写法
//char str[100];
//str[100]= "123a";

正式应用1:

#include 
#include 
using namespace std;

int main()
{
    int n;
    double db;
    char str[100] = "2048:3.14,hello";//初始化字符数组的方法
    char str2[100];
    sscanf(str,"%d:%lf,%s",&n,&db,str2);//读入double型变量的语法:
    printf("%d\n",n);
    printf("%.2f\n",db);
    printf("%s\n",str2);
    return 0;
}

算法笔记-经典模板_第7张图片

正式应用2:

#include 
#include 
using namespace std;

int main()
{
    int n=12;
    double db = 3.1415;
    char str[100];
    char str2[100] = "good";
    sprintf(str,"%d:%.2f,%s",n,db,str2);
    printf("%s",str);
    return 0;
}

图片.png

圆周率与浮点数比较

浮点数在计算机中的存储并不总是精确的,需要引入一个极小数eps对这种误差进行修正,eps一般取1e-8

#include 
#include 
#include 
using namespace std;

const double eps = 1e-8;
const double Pi = acos(-1.0);
//注意,Equ后面要跟小括号
#define Equ(a,b) ((fabs((a)-(b)))<(eps))
#define More(a,b) (((a)-(b))>(eps))
#define Less(a,b) (((a)-(b))<(eps))
#define MoreEqu(a,b) (((a)-(b))>(-eps))
#define LessEqu(a,b) (((a)-(b))<(eps))
int main()
{
    cout << "Hello world!" << endl;
    return 0;
}

算法笔记-经典模板_第8张图片

读入未知个数的string类型字符串

#include 
#include 
#include 
#include 
using namespace std;


int main()
{
    string str;
    vector now;
    //getline(cin,str)!=NULL和getline(cin,str)!=-1都是错的
    while(getline(cin,str)){
        now.push_back(str);
    }
    int len = now.size();
    for(int i=0; i

获得单链表从后往前第k位

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* getKthFromEnd(ListNode* head, int k) {
        int now[5002];
        int i=0;
        while(head->next != NULL){
            now[i] = head->val;
            i++;
            head = head->next;
        }

        i = i-2;
        ListNode* tmp;
        tmp = head;
        while(i>=0){
            ListNode* a = new ListNode(now[i]);
            tmp->next = a;
            tmp = a;
            i--;
        }
        return head;
    }
};

参考书目:《算法笔记》

你可能感兴趣的:(c++数据结构算法)