zoukankan      html  css  js  c++  java
  • 蓝桥杯总结-常用函数及算法

    <memory.h>或<string.h>

    void *memset(void *s, int ch, size_t n);

    #include <algorithm>

    sort(a,a+n)排序函数,从小到大,a为数组名字,n为元素个数

    sort(vector.begin(),vector.end())排序vector

    只要数据类型定义了小于操作符,即可用sort

    sort(a,a+n,compare)即可按照自定义顺序排列,compare为比较函数,返回值为bool

    lower_bound(a,a+n,x)二分查找,查找大于或等于x的第一个位置,只能查找vector<>数组,返回值为vector<>::iterator指针

        unique(vector1.begin(),vector1.end()),重排元素,使得所有值提前,返回值为重排后最后一个非重复值的后面的值的迭代器,即从返回值到vector1.end()是无意义的值,也是重复值的总数量

    reverse(vector1.begin(),vector1.end()),反转元素顺序

    next_permutation(p,p+n),求下一个全排列,枚举用

    #include <vector>   数组

    定义示例:vector<int> b(5);或者vector<int> a;

    赋值:b[0]=1;只有第一种定义可以这样赋值

    函数:

    int size(),获取大小

    void resize(int num),改变大小

    void push_back(int x),向尾部添加元素

    void pop_back(),删除最后一个元素

    void clear(),清空

    bool empty(),检查是否为空

    iterator insert(iterator x,y),向vector数组的x位置插入元素y,x可以为v.begin()+2

    iterator erase(iterator x),删除vector数组的x位置元素

    iterator begin(),返回头指针

    iterator end(),返回尾指针

    vector<>::iterator为一个可以指向其元素的指针

    #include <set>         集合,其中不含重复元素,且其中元素已从小到大排序,从1开始

    定义示例:set<int> a;

    函数:

    int size(),获取大小

    iterator find(x),若找到x,返回该键值迭代器的位置,否则,返回最后一个元素后面一个位置,即s.end()

    void clear(),清空

    bool empty(),检查是否为空

    iterator insert(y),向set集合插入元素y

    iterator erase(iterator x),删除set集合的值为x的元素,返回值为下一个位置的迭代器

    iterator begin(),返回头指针

    iterator end(),返回尾指针

    set<>::iterator为一个可以指向其元素的指针

    #include <map>       映射,索引

             定义示例:map<string,int> month_name;

    赋值:map[“July”]=7;

    函数:

    iterator find(y),寻找索引值为y的元素,返回指向其的指针

    iterator insert(map<string,int>(“July”,7)),向map映射插入元素(“July”,7)

    iterator erase(iterator x),删除map映射的迭代器x的元素

    map< string,int>::iterator l_it;;

       l_it=m.find(“July”);

       if(l_it==m.end())

            cout<<"we do not find July"<<endl;

       else  m.erase(l_it);  //delete July;

    iterator begin(),返回头指针

    iterator end(),返回尾指针

    map<>::iterator为一个可以指向其元素的指针

    #include <stack>

    定义示例:stack<int> s;

    void push(x),将值x压入栈

    void pop(),删除顶部元素

    top(),获得栈顶元素,但不删除

    bool empty(),检查是否为空

    int size(),获取大小

    #include <queue>

    定义示例:queue<int> q;

    void push(x),将值x入队

    void pop(),出队

    front(),获得队头元素,但不删除

    bool empty(),检查是否为空

    int size(),获取大小

    #include <string>

    string substr(int pos = 0,int n = npos) const;  //返回pos开始的n个字符组成的字符串

    void swap(string &s2);                                       //交换当前字符串与s2的值

    string &insert(int p0, const char *s);                //在p0位置插入字符串

    string &erase(int pos = 0, int n = npos);          //删除pos开始的n个字符,返回修改后的字符串

    int find(char c, int pos = 0) const;                     //从pos开始查找字符c在当前字符串的位置

    int find(const char *s,int pos = 0) const;         //从pos开始查找字符串s在当前串中的位置

    算法:

    快速排序:

    void quicksort(int *a,int l,int r){

             if(l>=r)

                      return;

             int temp=a[l];                                    //哨兵

             int i=l,j=r;

             while(i<j){

                      while(i<j){                                   //从右开始往左判断

                              if(a[j]>=temp){

                                       j--;

                              }

                              else{

                                       a[i++]=a[j];

                                       break;

                              }

                      }

                      while(i<j){                                   //从左开始往右判断

                              if(a[i]<=temp){

                                       i++;

                              }

                              else{

                                       a[j--]=a[i];

                                       break;

                              }

                      }

             }

             a[i]=temp;                                          //将哨兵放回中间位置

             quicksort(a,l,i-1);                               //左边排序

             quicksort(a,i+1,r);                             //右边排序

    }

    归并排序:

    void mergesort(int *a,int l,int r,int *b){

             if(l>=r)

                      return ;

             int mid=l+r;

             mid/=2;

             mergesort(a,l,mid,b);      //左边有序

             mergesort(a,mid+1,r,b);  //右边有序

            

             int k=l,i=l,j=mid+1;                    //注意k的初值

             while(i<=mid&&j<=r){              //将i-mid和j-r两组有序序列,归并在一个有序序列中

                      if(a[i]<=a[j])

                              b[k++]=a[i++];

                      else

                              b[k++]=a[j++];

             }

             while(i<=mid)                            //将i-mid剩余的数放在最后

                      b[k++]=a[i++];

             while(j<=r)                                 //将j-r剩余的数放在最后

                      b[k++]=a[j++];

             for(k=l;k<=r;k++)                       //将b数组中的数据拷贝到原数组中

                      a[k]=b[k];

    }

    并查集:

    #define N 100

    int father[N];

    void init() {

        for(int i=0; i<N; i++)

          father[i] = i;

    }

    // 合并两个元素所在的集合

    void union(int x,int y) {

        x = getfather(x);

        y = getfather(y);

        if(x!= y)

           father[x]=y;

    }

    // 判断两个元素是否属于同一个集合

    bool same(int x,int y) {

        return getfather(x)==getfather(y);

    }

    // 获取根结点

    int getfather(int x) {

        while(x != father[x])

          x = father[x];

        return x;

    }

    // 获取根结点,是上边函数的改进,压缩了路径长度

    int getfather(int x) {

        if(x != father[x])

          father[x] = getfather(father[x]); // 路径压缩修改的是father数组

        return father[x];

    }

    二分查找:

    int erfen(int *a,int l,int r,int v){        //a为待查找数组,l为下界下标,r为上界下标,v为目标值

             int mid;

             while(l<=r){

                      mid=l+r;

                      mid/=2;

                      if(a[mid]==v)   return mid;

                      else if(a[mid]>v)      r=mid-1;

                      else  l=mid+1;

             }      

             return -1;

    }

    01背包动态规划:

    int f[5000];

    int v[201],w[201];

    int main(int argc, char** argv) {

             int n=0,m,i,j,mx=0;

             cin>>n>>m;

             for(i=1;i<=n;i++){

                      cin>>w[i]>>v[i];

             }

             for(i=1;i<=n;i++){

                      for(j=m;j>=w[i];j--){

                              f[j]=max(f[j],f[j-w[i]]+v[i]);

                              mx=max(mx,f[j]);

                      }

             }

             cout<<mx;

             return 0;

    }

    LIS最长上升子序列

    int LIS(int *a,int n){

             int *dp=new int[n];         //存储以i为尾的最长上升子序列长度

             int mx=0,m,i,j;

             dp[0]=1;                            //初值,第一个字符为1

             for(i=1;i<n;i++){

                      m=0;

                      for(j=0;j<i;j++){        //对当前i之前的所有元素的最长上升子序列做判断

                              if(dp[j]>m&&a[j]<a[i]){

                                       m=dp[j];

                              }

                      }

                      dp[i]=m+1;               //最大m值再加上1

                      mx=max(mx,dp[i]); //同时判断所有最长上升子序列长度的最大值

             }

             return mx;

    }

    LCS最长公共子序列

    动态规划法:

    void LCS(string str1,string str2)

    {

             int x_len = str1.length();

             int y_len = str2.length();

            

             int arr[50][50] = {{0,0}};

            

             int i = 0;

             int j = 0;

             //动态规划二维矩阵

             for(i = 1; i <= x_len; i++)

             {

                      for(j = 1; j <= y_len; j++)

                      {

                              if(str1[i - 1] == str2[j - 1])

                              {

                                       arr[i][j] = arr[i - 1][j - 1] + 1;

                             }

                              else

                              {

                                       if(arr[i][j - 1] >= arr[i - 1][j])

                                       {

                                                arr[i][j] = arr[i][j - 1];

                                       }

                                       else

                                      {

                                                arr[i][j] = arr[i -1][j];

                                       }

                              }

                      }

             }

            

             //打印最长公共子序列

             stack<char> s;

            

             for(i = x_len, j = y_len; i >= 1 && j >= 1;)

             {

                      if(str1[i - 1] == str2[j - 1])

                      {

                              s.push(str1[i - 1]);

                              //cout<<str1[i - 1]<<" ";

                              i--;

                              j--;

                      }

                      else

                      {

                              //  if(arr[i][j -1] >= arr[i - 1][j])//打印两种情况

                              if(arr[i][j -1] > arr[i - 1][j])

                              {

                                       j--;

                              }

                              else

                              {

                                       i--;

                              }

                      }

             }

             while(!s.empty()){

                      cout<<s.top();

                      s.pop();

             }

             cout << endl;

    }

    递归法:(只能求数量)

    int LCS(char* x,char *y){

             if(strlen(x)==0)                  return 0;

             if(strlen(y)==0)         return 0;

            

             if(*x==*y)         return LCS(x+1,y+1)+1;

             return max(LCS(x,y+1),LCS(x+1,y));

    }

    Dijkstra最短路径算法

    #define MAX 9999999

    #define NUM 6

    int edge[NUM][NUM];                     //存储两点间距离

    int dist[NUM];                                   //存储到每个点的最短距离

    int mark[NUM];                                 //标记是否已选

    //n:多少个点  start:起始点   

    void Dijkstra(int n,int start){

             int i,j,k=start;

             int min;

             for(i=0;i<n;i++){

                      mark[i]=0;

                      dist[i]=edge[start][i];

             }

             mark[start]=1;

             dist[start]=0;

             for(i=0;i<n;i++){

                      min=MAX;

                      for(j=0;j<n;j++){

                              if(!mark[j]&&dist[j]<min){

                                       min=dist[j];

                                       k=j;

                              }

                      }

                      mark[k]=1;

                      for(j=0;j<n;j++){

                              if(!mark[j]&&dist[j]>dist[k]+edge[k][j]){

                                       dist[j]=dist[k]+edge[k][j];

                              }

                      }

             }

    }

    Floyd

    #define MAX 9999999

    #define NUM 6

    int edge[NUM][NUM];

    int temp[NUM][NUM];

    void Floyd(int a[NUM][NUM],int b[NUM][NUM]){

             int i,j,k;

             for(k=0;k<NUM;k++){

                      for(i=0;i<NUM;i++){

                              for(j=0;j<NUM;j++){

                                       if(k==0)

                                                b[i][j]=a[i][j];

                                       else{

                                                b[i][j]=min(b[i][j],b[i][k]+b[k][j]);

                                       }

                              }

                      }

             }      

    }

    最小生成树(prim)最好选择下边Krusal算法

    #define MAX  100000

    #define VNUM  6                       

    int edge[NUM][NUM];

    int lowcost[NUM];             //记录Vnew中每个点到V中邻接点的最短边

    int addvnew[NUM];               //标记某点是否加入Vnew

    int adjecent[NUM];            //记录最小生成树的边,从adjecent[i]到i

    void prim(int start){

             int i,j,k;

             int v,min;

             int sum=0;

             for(i=0;i<NUM;i++){

                      addvnew[i]=0;

                      adjecent[i]=start;

                      lowcost[i]=edge[start][i];

             }

             addvnew[start]=1;

             for(i=0;i<NUM-1;i++){

                      min=MAX;

                      v=-1;

                      for(j=0;j<NUM;j++){

                              if(!addvnew[j]&&min>lowcost[j]){

                                       min=lowcost[j];

                                       v=j;

                              }

                      }

                      if(v!=-1){

                              addvnew[v]=1;

                              sum+=lowcost[v];

                              for(j=0;j<NUM;j++){

                                       if(!addvnew[j]&&lowcost[j]>edge[v][j]){

                                                lowcost[j]=edge[v][j];

                                                adjecent[j]=v;

                                       }

                              }

                      }

             }

    }

    Kruskal

    #define N 100

    Int w[N],p[i],r[i];     //w为权值数组,p为并查集数组,r为边权值排序数组,里边存储的是边的w对应的标号

    Int cmp(const int I,const int j){ return w[i]<w[j]; }

    Int find(int x){ return p[x]==x?x:find(p[x]); }

    Int Kruskal(){

             Int ans=0;

             For(int i=0;i<n;i++) p[i]=I;

             For(int i=0;i<n;i++) r[i]=I;

             Sort(r,r+m,cmp);//给边升序排列

             For(int i=0;i<n;i++){

                      Int e=r[i]; int x=find(u[e]); int y=find(v[e]);

                      If(x!=y) { ans+=w[e]; p[x]=y; }

             }

             return ans;

    }

    测试数据

    for(int i=0;i<VNUM;i++){

                      for(int j=0;j<VNUM;j++){

                              edge[i][j]=MAX;

                      }

             }

             edge[1][2]=5;

             edge[2][1]=5;

             edge[3][2]=3;

             edge[2][3]=3;

             edge[1][3]=4;

             edge[3][1]=4;

             edge[1][6]=7;

             edge[6][1]=7;

             edge[2][5]=6;

             edge[5][2]=6;

             edge[3][4]=2;

             edge[4][3]=2;

             edge[4][6]=3;

             edge[6][3]=3;

             edge[4][5]=1;

             edge[5][4]=1;

             edge[5][6]=4;

             edge[6][5]=4;

    可重集的全排列(递归)

    void print_permutation(int n,int P[],int A[],int cur)        //P按顺序存储待排列数,A同样大小的临时空间数组

    {

             int i,j;

             if(cur==n){

                      for(i=0;i<n;i++) printf("%d ",A[i]);                    //可输出可统计

                      printf(" ");

             }

             else for(i=0;i<n;i++) if(!i||P[i]!=P[i-1]){

                      int c1=0,c2=0;

                      for(j=0;j<cur;j++) if(A[j]==P[i])c1++;

                      for(j=0;j<n;j++) if(P[i]==P[j])c2++;

                      if(c1<c2){

                              A[cur]=P[i];

                              print_permutation(n,P,A,cur+1);

                      }

             }

    }

    next_permutation(p,p+n),求下一个全排列

    二进制法求子集

    void print_submet(int n,int s){                 //打印一个子集

             for(int i=0;i<n;i++)                            

                      if(s&(1<<i)) printf("%d ",i);      //s=101时,代表子集{0,2}

             printf(" ");

    }

    int main() {

             int n=7;                                                //代表集合{0,1,2,3,4,5,6},二进制表示

             for(int i=0;i<(1<<n);i++)                    //枚举所有子集

                      print_submet(n,i);

             return 0;

    }

    快速求幂

    int pow3(int x,int n){

             if(n==0)                                       //任何数的0次幂都是1

                      return 1;

             else{                                            //把尾部的0全部去除

                      while((n&1)==0){

                              n>>=1;

                              x*=x;

                      }

             }

             int res=x;                                    //后边的都不明白

             n>>=1;

             while(n!=0){

                      x*=x;

                      if((n&1)!=0)

                              res*=x;

                      n>>=1;

             }

             return res;

    }

    辗转相除法求最大公约数:

    int gcd(int a,int b){

             int temp;

             while(a%b!=0){

                      temp=a;

                      a=b;

                      b=temp%b;

             }

             return b;

    }

    辗转相除法最大公倍数:

    int lcm(int a,int b){

             int a1=a,b1=b,temp;

             while(a%b!=0){

                      temp=a;

                      a=b;

                      b=temp%b;

             }

             return a1/b*b1;

    }

    有重复元素的全排列:
    例如:有k个元素,其中第i个元素有ni个,求全排列个数。

    X=n!/(n1!*n2!......nk!)

    可重复选择的组合:

    有N个不同元素,每个元素可以选多次,一共选k个元素,有多少种选法?

    C(n+k-1,k)

    分析详见P319

    杨辉三角:

    任意一行的所有元素

    C[0]=1;

    For(int i=1;i<=n;i++)         C[i]=C[i-1]*(n-i+1)/i

  • 相关阅读:
    Ubuntu 12.04 国内更新源列表 LINUX软件 偶偶贝塔のBlog
    乱码
    charset
    乱码
    使用 Python 进行线程编程
    Pyphantomjs makes python crash
    乱码
    PyQt v4 Python Bindings for Qt v4 | Документация
    Automated Discovery of Blog Feeds and Twitter, Facebook, LinkedIn Accounts Connected to Business Website « Data Big Bang Blog
    jeanphix/Ghost.py · GitHub
  • 原文地址:https://www.cnblogs.com/chengyu404/p/5600739.html
Copyright © 2011-2022 走看看