CSP备考(自用)

vector补充

二维vector数组初始化

vector<vector<int>> matrix(M,vector<int>(N));//初始化一个 二维的matrix, 行M,列N,且值为0
vector<vector<int>>matrix(M);//M行,列数不固定

vector基础操作补充

vector<T> v(v1)//使用 v 中所有元素初始化 v1
vector<T> v(n, val)//v中包含了 n 个值为 val 的元素
vector<T> v(n)//v中包含了 n 个默认值初始化的元素
vector<T> v5{a, b, c...}//使用 a, b, c... 初始化 v5
vector<T> v //v 是一个元素类型为 T 的空 vector
v.back()//返回v中最后一个元素的引用
v.front()//返回v中第一个元素的引用
v1 = v2//用v2中的元素替换v1中的元素
v1 = {a,b,c……}//用元素{a,b,c……}替换v1中的元素
v1 == v2//当且仅当拥有相同数量且相同位置上值相同的元素时,v1 与 v2 相等
v1 != v2
<,<=,>,>=//以字典序进行比较

vector迭代器补充:

一个迭代器的范围由一对迭代器表示,分别为 begin 和 end。其中 begin 成员返回指向第一个元素的迭代器;end 成员返回容器最后一个元素的下一个位置(one past the end),也就是指向一个根本不存在的尾后位置,这样的迭代器没什么实际含义,仅是个标记而已,表示已经处理完了容器中的所有元素。所以 begin 和 end 表示的是一个左闭右开的区间 [ begin , end)

简单升序排序

头文件:

vector//头文件
algorithm//头文件   用来引入sort函数

函数格式:

sort(name.begin(),name.end());

name.begin()表示指向数组头的迭代器,name.end()表示指向数组尾下一个位置的迭代器,该式表示将叫name的vector元素按从小到大进行升序排序。

示例代码:

#include<iostream>
#include<cstdlib>
#include<algorithm>
#include<vector>
using namespace std;
int main(){
    int ans[6]={5,7,3,8,1,2};
    vector<int>num;
    cout<<"before sorted: ";
    for(int i=0;i<6;i++)
    {
        cout<<ans[i]<<" ";
        num.emplace_back(ans[i]);
    }
    cout<<endl;
    cout<<"after sorted: ";
    //按升序排序
    sort(num.begin(),num.end());
    for(int i=0;i<num.size();i++)
    {
        cout<<num[i]<<" ";
    }
    system("pause");
	return 0;
}

简单降序排序

sort(name.rbegin(),name.rend());

自定义函数排序

sort(res.begin(),res.end(),[&](const typename&a,const typename&b)->bool{
    return (输入你的排序标准);
});

示例代码:

#include<iostream>
#include<cstdlib>
#include<algorithm>
#include<vector>
#include<string>
#include<unordered_map>
using namespace std;
int main(){
    //我们将学生信息存入map中
    unordered_map<string,int>map;
    string name;
    int height;
    for(int i=0;i<7;i++)
    {
        cin>>name>>height;
        map[name]=height;
    }

    //将学生名字存入vector数组中
    vector<string>res;
    for(auto &[key,value]:map)
    {
        res.emplace_back(key);
    }

    //自定义排序,按身高降序,身高相同时则按名字升序排列
    sort(res.begin(),res.end(),[&](const string&a,const string&b)->bool{
        return map[a]==map[b]?a<b:map[a]>map[b];
    });

    //输出排列后的顺序
    cout<<endl;
    cout<<"after sorted: "<<endl;
    for(int i=0;i<res.size();i++)
    {
        cout<<res[i]<<"   "<<map[res[i]]<<endl;
    }
    system("pause");
	return 0;
}

消除相邻的重复元素

unique()

将输入序列相邻的重复项“消除”,返回一个指向不重复值范围末尾的迭代器,一般配合 sort() 使用

代码示例:

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
 
int main(void)
{
    vector<int> a{2, 0, 2, 2, 0, 3, 0, 9};
    sort(a.begin(), a.end());  // 先排序
    for(int i:a)   cout << i << " "; // 输出
    cout << endl;
    auto end_unique = unique(a.begin(), a.end());  //将输入序列相邻的重复项“消除”,返回一个指向不重复值范围末尾的迭代器
    a.erase(end_unique, a.end()); // 删除末尾元素
    for(int i:a)   cout << i << " "; // 输出
    return 0;
}
// 运行结果 //
0 0 0 2 2 2 3 9 
0 2 3 9

vector中找最值

最大值

auto it = max_element(v.begin, v,end())//返回最大值的迭代器

最小值

auto it = min_element(v.begin, v,end())//返回最小值的迭代器

相对位置大小

auto b = distance(x, y)//x、y 是迭代器类型,返回 x、y 之间的距离,可以用来获取最大/小值的索引

代码示例:

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
 
int main(void)
{
    vector<int> a({0,1,-2,3});
    auto b = distance(a.begin(), min_element(a.begin(), a.end()));
    cout << a[b] << endl;
    return 0;
}
// 输出 //
-2

string

头文件

#include<string>

实用string函数

//声明一个字符串
 string s(str,stridx) //将字符串str内“始于位置stridx”的部分当作字符串的初值
 string s(str,stridx,strlen) //将字符串str内“始于stridx且长度顶多strlen”的部分作为字符串的初值
 string s(num,c) //生成一个字符串,包含num个c字符
 
 //字符串操作函数
 s.insert(pos,args)//在pos之前插入args指定的字符
 s.erase(pos,len)//删除从pos开始的len个字符,如果len省略,则删除pos开始的后面所有字符,返回一个指向s的引用
 s.assign(args)//将s中的字符替换为args指定的字符。返回一个指向s的引用
 s.append(args)//将args追加到s,返回一个指向s的引用,args必须是双引号字符串
 s.replace(range,args)//将s中范围为range内的字符替换为args指定的字符
 s.find(args)//查找s中args第一次出现的位置
 s.rfind(args)//查找s中args最后一次出现的位置
 to_string(vall)//将数值val转换为string并返回。fal可以是任何算术类型(int、浮点型等)
 stoi(s)/atoi(c)//字符串/字符 转换为整数并返回
 stof(s)/atof(s)//字符串/字符 转换为浮点数并返回
 s.substr(pos,n)//从索引pos开始,提取连续的n个字符,包括pos位置的字符
 reverse(s2.begin(),s2.end())//反转string定义的字符串s2(加头文件<algorithm>)

各个数据结构样例

图的邻接矩阵(Adjacency Matrix) 存储方式是用两个数组来表示图。一个一维数组存储图中顶点信息,一个二维数组(称为邻接矩阵)存储图中的边或弧的信息。
无向图和其邻接矩阵
image

  • 无向图的邻接矩阵一定是一个对称矩阵(即从矩阵的左上角到右下角的主对角线为轴,右上角的元与左下角相对应的元全都是相等的)。 因此,在实际存储邻接矩阵时只需存储上(或下)三角矩阵的元素。
  • 对于无向图,邻接矩阵一定是一个对称矩阵

有向图及其邻接矩阵
image

对于带权图,对应位置写上权重即可

#define MaxVertexNum 100	//顶点数目的最大值
typedef char VertexType;	//顶点的数据类型
typedef int EdgeType;	//带权图中边上权值的数据类型
typedef struct{
	VertexType Vex[MaxVertexNum];	//顶点表
	EdgeType Edge[MaxVertexNum][MaxVertexNum];	//邻接矩阵,边表
	int vexnum, arcnum;	//图的当前顶点数和弧树
}MGraph;

注意:
在简单应用中,可以直接用二维数组作为图的邻接矩阵

无向图及其邻接表
image
有向图及其邻接表
image

相应的存储结构定义

#define MAXVEX 100	//图中顶点数目的最大值
type char VertexType;	//顶点类型应由用户定义
typedef int EdgeType;	//边上的权值类型应由用户定义
/*边表结点*/
typedef struct EdgeNode{
	int adjvex;	//该弧所指向的顶点的下标或者位置
	EdgeType weight;	//权值,对于非网图可以不需要
	struct EdgeNode *next;	//指向下一个邻接点
}EdgeNode;

/*顶点表结点*/
typedef struct VertexNode{
	Vertex data;	//顶点域,存储顶点信息
	EdgeNode *firstedge	//边表头指针
}VertexNode, AdjList[MAXVEX];

/*邻接表*/
typedef struct{
	AdjList adjList;
	int numVertexes, numEdges;	//图中当前顶点数和边数
}

几个经典算法

Dijkstra算法

例图:
image

具体步骤:

image

递归示例

 public static int Factorial(int num)
    {
        if(num==1)
        {
            return num;
        }
        return num*Factorial(num-1);
    }

KMP算法

模式匹配:

当有两个字符串Str = "abdabcde;和 modStr = "abcd";时,如果要在Str中查找与modelStr相等的子串,则称Str为主串,modelStr为模式串。在查找过程中,从Str中的第一个字符进行比较,如果找到与modelStr相同的子串,函数返回modelStr字符串第一次出现的位置,否则返回-1。以上过程就称为模式匹配.

匹配过程:

image
image
KMP算法发现每个字符对应的该 k 值仅仅依赖于模式T本身,而与目标对象S无关
image
因此,next[j]可以预先计算

next[j]表示在第j位失配后,j应该挪到模式串的第几位

image

KMP代码实现

int KMP(const char* s, const char* p)
{
    int ret = -1;
    int sLen = strlen(s);
    int pLen = strlen(p);
    //创建模式字符串的部分匹配表
    int* pmt = makePMT(p);
    if((pmt != NULL) && (0 < sLen) && (pLen <= sLen))
    {
        //遍历目标字符串,
        for(int i = 0, j = 0; i < sLen; i++)
        {
            //如果已经有字符匹配,并且s[i]和p[j]不匹配
            while((j > 0) && (s[i] != p[j]))
            {
                //i位置前的pmt[j-1]个字符已经与模式字符串的前pmt[j-1]个字符匹配
                j = pmt[j-1];//j回溯到pmt[j-1]处的字符继续比较
            }
 
            //如果字符匹配,继续逐位比较
            if(s[i] == p[j])
            {
                j++;
            }
 
            //如果找到匹配的字符串
            if(j == pLen)
            {
                //目标字符串中匹配的模式字符串的起始位置索引
                ret = i + pLen - 1;
                break;
            }
        }
    }
 
    free(pmt);
    return ret;
}
posted @ 2023-09-17 00:25  中原白也  阅读(78)  评论(0)    收藏  举报