当前位置: 首页 > news >正文

冲刺蓝桥杯第四章标准模版库STL(上)

vector:

介绍:

vector 是 C++ 标准模板库(STL)中的一个非常重要的序列容器,它封装了动态数组的实现。vector 能够存储具有相同类型的元素序列,并且能够根据需要自动调整其大小。注意:在局部区域中(比如局部函数里面)开vector数组,是在堆空间里面开的。在局部区域开数组是在栈空间开的,而栈空间比较小,如果开了非常长的数组就会发生爆栈。故局部区域不可以开大长度数组,但是可以开大长度 vector 。
1、头文件:

#include <vector>

2、一维初始化:

vector<int> v; // 定义了一个名为v的一维数组,数组存储int类型数据
vector<double> v; // 定义了一个名为v的一维数组,数组存储double类型数据
vector<node> v; // 定义了一个名为v的一维数组,数组存储结构体类型数据,node是结构体类型

指定长度和初始值的初始化:

vector<int> v(n); // 定义一个长度为n的数组,初始值默认为0,下标范围[0, n - 1]
vector<int> v(n, 1); // v[0] 到 v[n - 1]所有的元素初始值均为1
//注意:指定数组长度之后(指定长度后的数组就相当于正常的数组了)

初始化中有多个元素:

vector<int> a{1, 2, 3, 4, 5}; // 数组a中有五个元素,数组长度就为5

拷贝初始化:

vector<int> a(n + 1, 0);
vector<int> b(a); // 两个数组中的类型必须相同,a和b都是长度为n+1,初始值都为0的数组
vector<int> c = a; // 也是拷贝初始化,c和a是完全一样的数组

3、二维初始化:
定义第一维固定长度为 5 ,第二维可变化的二维数组:

vector<int> v[5]; // 定义可变长二维数组
//注意:行不可变(只有5行), 而列可变,可以在指定行添加元素
//第一维固定长度为5,第二维长度可以改变

vector v[5] 可以这样理解:长度为5的v数组,数组中存储的是 vector 数据类型,而该类型就是数组形式,故 v 为二维数组。其中每个数组元素均为空,因为没有指定长度,所以第二维可变长。可以进行下述操作:

v[1].push_back(2);
v[2].push_back(3);

定义行列均可变的二维数组:

//初始化二维均可变长数组
vector<vector<int> > v; // 定义一个行和列均可变的二维数组,注意哦,>>之间要加上空

可以在 v 数组里面装多个数组:

vector<int> t1{1, 2, 3, 4};
vector<int> t2{2, 3, 4, 5};
v.push_back(t1);
v.push_back(t2);
v.push_back({3, 4, 5, 6}) // {3, 4, 5, 6}可以作为vector的初始化,相当于一个无名vector

行列长度均固定 n + 1 行 m + 1 列初始值为0:

vector<vector<int > a(n + 1, vector<int>(m + 1, 0));

常用函数:

#include<iostream>
#include<vector>
using namespace std;
vector<int>v;
int main(){v.push_back(1);//在尾部加一个元素  O(1)v.front();//返回第一个元素  O(1)v.back();//返回数组中的最后一个元素  O(1)v.pop_back();//删除最后一个元素  O(1)v.size();//返回元素的个数(unsigned类型)  O(1)v.clear();//清除元素个数  O(n) n为元素个数v.resize(n,v);//改变数组大小为n,n个空间数值赋为v,没有v时默认为零v.insert(it,x);//向任一迭代器it插入一个元素x  O(n)//例子:v.insert(v.begin(),1)将1插入到v[0]的位置v.erase(first,last);//删除[first,last)的所有元素  O(n)v.begin();//返回首元素的迭代器(类似于地址) O(1)v.end();//返回尾元素的下一个位置的迭代器  O(1)v.empty();//判断是否为空,为空返回真,反之返回假  O(1)
}

访问:

共三种方法:
1、下标法:直接和普通数组一样进行访问即可。
注意:一维数组的下标是从 0 到 v.size()-1 ,访问之外的数会出现越界错误

#include<iostream>
#include<vector>
using namespace std;
vector<int>v;
int main(){int n,t;cin>>n;for(int i=0;i<n;i++){cin>>t;v.push_back(t);}for(int i=0;i<n;i++){cout<<v[i];}return 0;
}

2、迭代器法 :类似指针,迭代器就是充当指针的作用。

vector<int> vi{1, 2, 3, 4, 5};
//迭代器访问
vector<int>::iterator it;
//相当于声明了一个迭代器类型的变量it,通俗来说就是声明了一个指针变量

方法一:

#include<iostream>
#include<vector>
using namespace std;
vector<int>v;
int main(){int n,t;cin>>n;for(int i=0;i<n;i++){cin>>t;v.push_back(t);}vector<int>::iterator it=v.begin();for(int i=0;i<n;i++){cout<<*(it+i);}return 0;
}

方法二:

#include<iostream>
#include<vector>
using namespace std;
vector<int>v;
int main(){int n,t;cin>>n;for(int i=0;i<n;i++){cin>>t;v.push_back(t);}vector<int>::iterator it;for(it=v.begin();it!=v.end();it++){//注意不能用小于只能使用不等于cout<<*it;}return 0;
}

方法三:

#include<iostream>
#include<vector>
using namespace std;
vector<int>v;
int main(){int n,t;cin>>n;for(int i=0;i<n;i++){cin>>t;v.push_back(t);}auto it=v.begin();while(it!=v.end()){cout<<*it;it++;}return 0;
}

3、智能指针:使用auto :比较简便,但是只能访问数组的所有元素(特别注意0位置元素也会访问到)如果要指定的内容进行遍历,需要另选方法。
auto 能够自动识别并获取类型。

#include<iostream>
#include<vector>
using namespace std;
int main(){int n;cin>>n;vector<int>v(n);//使用auto必须要有输入数量//输入for(auto &x:v){cin>>x;}//输出for(auto val:v){cout<<val;}return 0;
}

vector 注意:
vi[i] 和 *(vi.begin() + i) 等价,与指针类似。
vector 和 string 的 STL 容器支持 *(it + i) 的元素访问。

stack

介绍

栈是STL中实现的一个先进后出,后进先出的容器。
1、头文件

#include<stack>

2、初始化

stack<int> s;
stack<string> s;
stack<node> s; // node是结构体类型

常用函数

#include<iostream>
#include<stack>
using namespace std;
stack<int>s;
int main(){s.push(n);//将元素n入栈  O(1)s.pop();//移除栈顶元素  O(1)s.top();//取出栈顶元素  O(1)s.empty();//检测栈内是否为空,空为真,非空为假  O(1)s.size();//返回栈内的元素个数  O(1)
}

遍历

1、栈只能对栈顶元素进行操作,如果想要进行遍历,只能将栈中元素一个个取出来存在数组中

#include<iostream>
#include<stack>
using namespace std;
stack<int>s;
int main(){int n;cin>>n;for(int i=0;i<n;i++){int x;cin>>x;s.push(x);}while(!s.empty()){int tp=s.top();s.pop();cout<<tp;}
}

2、数组模拟栈进行遍历:通过一个数组对栈进行模拟,一个存放下标的变量 top 模拟指向栈顶的指针。
一般来说单调栈和单调队列写法均可使用额外变量 tt 或 hh 来进行模拟。
特点: 比 STL 的 stack 速度更快,遍历元素方便

int s[100]; // 栈 从左至右为栈底到栈顶
int tt = -1; // tt 代表栈顶指针,初始栈内无元素,tt为-1
for(int i = 0; i = 5; i++) {//入栈s[++tt] = i;
}
//出栈
int top_element = s[tt--];
//入栈操作示意
//0 1 2 3 4 5
//          tt
//出栈后示意
//0 1 2 3 4
//        tt 

queue

介绍:

队列是一种先进先出的数据结构。
1、头文件:

#include<queue>

2、初始化:

queue<int> q;

常用函数:

#include<iostream>
#include<queue>
using namespace std;
queue<int>q;
int main(){q.push(n);//将n元素入队  O(1)q.front();//返回队首元素  O(1)q.back();//返回队尾元素  O(1)q.pop();//删除第一个元素(出队)  O(1)q.size();//返回队列中元素的个数,返回值类型unsigned int  O(1)q.empty();//判断队列是否为空,队列为空返回true,为非空返回false  O(1)
}

对列模拟

使用 q[] 数组模拟队列
hh 表示队首元素的下标,初始值为 0
tt 表示队尾元素的下标,初始值为 -1 ,表示刚开始队列为空

#include<iostream>
using namespace std;
const int N = 1e5 + 5;
int q[N];
int main(){int hh = 0,tt = -1;//入队q[++tt] = 1;q[++tt] = 2;//将所有元素出队while(hh = tt) {int t = q[hh++];printf("%d ",t);}return 0;
}

deque

介绍

首尾都可插入和删除的队列为双端队列,在两端都可以进行操作。
1、头文件

#include<deque>

2、初始化

deque<int> dq;

常用函数

#include<iostream>
#include<deque>
using namespace std;
deque<int>dq;
int main(){dp.push_back(n);//把元素n插入到队尾  O(1)dp.push_front(n);//把元素n插入到队首  O(1)dp.back();//返回队尾元素  O(1)dp.front();//返回队首元素  O(1)dp.pop_back();//删除队尾元素  O(1)dp.pop_front();//删除队首元素  O(1)dp.erase(iterator it);//删除双端队列中的某一个元素dp.erase(iterator first,iterator last);//删除双端队列中[first,last)中的元素dp.empty();//判断双端队列是否为空  O(1)dp.size();//返回双端队列的元素数量  O(1)dp.clear();//清空双端队列
}

注意点

deque可以进行排序(双端队列排序一般不用,使用其他STL依然可实现相同功能)

//从小到大
sort(dq.begin(), dq.end())
//从大到小排序
sort(dq.begin(), dq.end(), greater<int>()); // deque里面的类型需要是int型
sort(dq.begin(), dq.end(), greater());//c++高版本才可以用

priority_queue

介绍:

优先队列是一种特殊的队列,其中每个元素都被赋予一个优先级。在优先队列中,元素的出队顺序不是基于它们的入队顺序,而是基于它们的优先级。优先级最高的元素会最先被移除。优先队列分为最大优先队列和最小优先队列,前者总是移除当前优先级最高的元素(即最大的元素),后者总是移除当前优先级最低的元素(即最小的元素)。
优先队列的实现通常基于堆数据结构,特别是二叉堆。堆是一个近似完全二叉树的结构,并同时满足堆属性:即子节点的键值或索引总是小于(或大于)它的父节点。通过堆的性质,优先队列可以在对数时间复杂度内完成插入和删除最大(或最小)元素的操作。
1、头文件

#include<queue>

2、初始化

priority_queue<int> q;

常用函数:

#include<iostream>
#include<queue>
using namespace std;
priority_queue<int>q;
int main(){q.top();//访问队首元素  O(1)q.push(n);//将n入队  O(logn)q.pop();//堆顶(队首)元素出队  O(logn)q.size();//队列元素个数  O(1)q.empty();//判断是否为空,空为真,非空为假  O(1)//注意:优先队列没有clear()//优先队列只能通过 top() 访问队首元素(优先级最高的元素)
}

设置优先级

1、基本数据类型的优先级

priority_queue<int> q; // 默认大根堆, 即每次取出的元素是队列中的最大值
priority_queue<int, vector<int>, greater<int> > q; // 小根堆, 每次取出的元素是队列中的最小值

参数解释:
第一个参数:
就是优先队列中存储的数据类型
第二个参数:
vector 是用来承载底层数据结构堆的容器,若优先队列中存放的是 double 型数据,就要填 vector< double >总之存的是什么类型的数据,就相应的填写对应类型。同时也要改动第三个参数里面的对应类型。
第三个参数:
less 表示数字大的优先级大,堆顶为最大的数字
greater 表示数字小的优先级大,堆顶为最小的数字
int代表的是数据类型,也要填优先队列中存储的数据类型
基础数据类型优先级设置的写法:
<1>、基础写法:

priority_queue<int> q1; // 默认大根堆, 即每次取出的元素是队列中的最大值
priority_queue<int, vector<int>, less<int> > q2; // 大根堆, 每次取出的元素是队列中的最大值,同第一行
priority_queue<int, vector<int>, greater<int> > q3; // 小根堆, 每次取出的元素是队列中的最小值

<2>、自定义排序:

struct cmp1 {bool operator()(int x, int y) {return x > y;}
};
struct cmp2 {bool operator()(const int x, const int y) {return x < y;}
};
priority_queue<int, vector<int>, cmp1> q1; // 小根堆
priority_queue<int, vector<int>, cmp2> q2; // 大根堆

2、高级数据类型(结构体)优先级:即优先队列中存储结构体类型,必须要设置优先级,即结构体的比较运算(因为优先队列的堆中要比较大小,才能将对应最大或者
最小元素移到堆顶)。
优先级设置可以定义在结构体内进行小于号重载,也可以定义在结构体外。

//要排序的结构体(存储在优先队列里面的)
struct Point {int x, y;
};

<1>、自定义全局比较规则

//定义的比较结构体
//注意:cmp是个结构体
struct cmp { // 自定义堆的排序规则bool operator()(const Point& a,const Point& b) {return a.x < b.x;}
};
//初始化定义
priority_queue<Point, vector<Point>, cmp> q; // x大的在堆顶

<2>、直接在结构体里面写:因为是在结构体内部自定义的规则,一旦需要比较结构体,自动调用结构体内部重载运算符规则。
结构体内部有两种方式:
方式一 :

struct node {int x, y;friend bool operator < (Point a, Point b) { // 为两个结构体参数,结构体调用一定要写上friendreturn a.x < b.x; // 按x从小到大排,x大的在堆顶}
};

方式二 :(推荐)

struct node {int x, y;bool operator < (const Point &a) const { // 直接传入一个参数,不必要写friendreturn x < a.x; // 按x升序排列,x大的在堆顶}
};

优先队列的定义:

priority_queue<Point> q;

注意: 优先队列自定义排序规则和 sort() 函数定义 cmp 函数很相似,但是最后返回的情况是相反的。即相同的符号,最后定义的排列顺序是完全相反的。
所以只需要记住 sort 的排序规则和优先队列的排序规则是相反的就可以了。
3、存储特殊类型的优先级
存储pair类型:
排序规则:
默认先对 pair 的 first 进行降序排序,然后再对 second 降序排序
对 first 先排序,大的排在前面,如果 first 元素相同,再对 second 元素排序,保持大的在前面。

#include<iostream>
#include<queue>
using namespace std;
int main() {priority_queue<pair<int, int> >q;q.push({7, 8});q.push({7, 9});q.push(make_pair(8, 7));while(!q.empty()) {cout << q.top().first << " " << q.top().second;q.pop();}return 0;
}
//结果:
//8 7
//7 9
//7 8

map

介绍

映射类似于函数的对应关系,每个 key 对应一个 value ,而 map 是每个键对应一个值。
1、头文件

#include<map>

2、初始化

map<string, string> mp;
map<string, int> mp;
map<int, node> mp; // node是结构体类型

map特性:map会按照键的顺序从小到大自动排序,键的类型必须可以比较大小

常用函数

#include<iostream>
#include<map>
using namespace std;
map<int ,int>mp;
int main() {mp.find(key);//返回健为key的映射的迭代器  O(logN)//注意:用find函数来定位数据出现的位置,它返回一个迭代器。当数据存在时,返回数据所在位置的迭代器,当数据不存在时,返回mp.end()mp.erase(it);//删除迭代器对应的键和值  O(1)mp.erase(key);//根据映射的键删除键和值  O(logN)mp.erase(first,last);//删除[first,last)区间的迭代器对应的键和值  O(last-first)mp.size();//返回映射的对数  O(1)mp.clear();//清空map中的所有元素  O(n)mp.insert();//插入元素,插入时要构造键值对mp.empty();//判断map是否为空,为空返回true,为假返回falsemp.begin();//返回指向map第一个元素的迭代器(地址)mp.end();//返回指向map最后一个元素的下一个地址mp.rbegin();//返回指向map最后一个元素的迭代器(地址)mp.rend();//返回指向元素map第一个元素的前一个地址(逆向迭代器)mp.count(key);//查看元素是否存在,因为map中的键值是唯一的,存在返回true,不存在返回falsemp.lower_bound();//返回一个迭代器,指向键值>=key的第一个元素mp.upper_bound();//返回一个迭代器,指向键值>key的第一个元素
}

注意点:
查找元素是否存在时,可以使用① mp.find() ② mp.count() ③ mp[key]但是第三种情况,如果不存在对应的 key 时,会自动创建一个键值对(产生一个额外的键值对空间)所以为了不增加额外的空间负担,最好使用前两种方法。

迭代器进行正反向遍历:

1、mp.begin() 和 mp.end() 用于正向遍历map

#include<iostream>
#include<map>
using namespace std;
map<int ,int>mp;
int main() {int n;cin>>n;for(int i=1;i<=n;i++){int x,y;cin>>x>>y;mp[x]=y;}auto it=mp.begin();while(it!=mp.end()){cout<<it->first<<" "<<it->second<<endl;it++;}
}

2、mp.rbegin() 和 mp.rend()用于逆向遍历map

#include<iostream>
#include<map>
using namespace std;
map<int ,int>mp;
int main() {int n;cin>>n;for(int i=1;i<=n;i++){int x,y;cin>>x>>y;mp[x]=y;}auto it=mp.rbegin();while(it!=mp.rend()){cout<<it->first<<" "<<it->second<<endl;it++;}
}

二分查找:

map的二分查找以第一个元素(即键为准),对键进行二分查找返回值为map迭代器类型

#include<iostream>
#include<map>
using namespace std;
map<int ,int>mp{{1,2},{2,2},{3,2},{6,2},{8,2}};//有序
int main() {//判断的是key返回的也是key的值map<int ,int>::iterator it1=mp.lower_bound(2);//左边界cout<<it1->first;//2map<int ,int>::iterator it2=mp.upper_bound(6);//右边界cout<<it2->first;//8return 0;
}

添加元素:

先声明:

map<string ,string>mp;

方法一:

mp["abcd"]="abcd";

方法二:

mp.insert(make_pair("abcd","abcd"));

方法三:

mp.insert(pair<string ,string>("abcd","abcd"));

方法四:

mp.insert({"abcd","abcd"});

访问元素

1、下标访问:

#include<iostream>
#include<map>
using namespace std;
map<string ,string>mp;
int main() {mp["abcd"]="efg";cout<<mp["abcd"];
}

2、遍历访问:
方法一:迭代器访问

#include<iostream>
#include<map>
using namespace std;
map<string ,string>mp;
int main() {mp["abcd"]="efg";map<string ,string>::iterator it;for(it=mp.begin();it!=mp.end();it++){cout<<it->first<<" "<<it->second;//it是结构体指针访问要用  ->  访问cout<<(*it).first<<" "<<(*it).second;//*it是结构体变量访问要用  .  访问}
}

方法二:智能指针

#include<iostream>
#include<map>
using namespace std;
map<string ,string>mp;
int main() {mp["abcd"]="efg";map<string ,string>::iterator it;for(auto i:mp){cout<<i.first<<" "<<i.second;}
}

方法三:对指定单个元素访问

#include<iostream>
#include<map>
using namespace std;
map<string ,string>mp;
int main() {mp["abcd"]="efg";map<string ,string>::iterator it=mp.find("abcd");//key的值cout<<it->first<<" "<<it->second;
}

方法四:c++17特性

#include<iostream>
#include<map>
using namespace std;
map<string ,string>mp;
int main() {mp["abcd"]="efg";for(auto [x,y]:mp){cout<<x<<" "<<y;}
}

map与unordered_map的比较

头文件:

#include <unordered_map>

1、内部实现原理
map:内部用红黑树实现,具有自动排序(按键从小到大)功能。
unordered_map:内部用哈希表实现,内部元素无序杂乱。
2、效率比较
map:
优点:内部用红黑树实现,内部元素具有有序性,查询删除等操作复杂度为O(logN)
缺点:占用空间,红黑树里每个节点需要保存父子节点和红黑性质等信息,空间占用较大。
unordered_map:
优点:内部用哈希表实现,查找速度非常快(适用于大量的查询操作)。
缺点:建立哈希表比较耗时。
两者方法函数基本一样,差别不大。
注意:
随着内部元素越来越多,两种容器的插入删除查询操作的时间都会逐渐变大,效率逐渐变低。
使用 [] 查找元素时,如果元素不存在,两种容器都是创建一个空的元素;如果存在,会正常索引对应的值。所以如果查询过多的不存在的元素值,容器内部会创建大量的空的键值对,后续查询创建删除效率会大大降低。
查询容器内部元素的最优方法是:先判断存在与否,再索引对应值(适用于这两种容器)

#include<iostream>
#include<map>
using namespace std;
map<string ,string>mp;
int main() {mp["abcd"]="efg";string s="abcd";//key的值if(mp.count(s)){cout<<mp[s];}
}

multimap

键可以重复,即一个键对应多个值。
1、头文件:

#include<map>

2、初始化:
方法一:

multimap<string, int> mymultimap{{"penny",1},{"leonard",2},{"sheldon",3}};

方法二:

//借助pair类模板的构造函数生成各个pair类型的键值对
multimap<string,int> mymultimap{pair<string,int>{"penny",1},pair<string,int>{"leonard",2},pair<string,int>{"sheldon",3}
};
//调用make_pair()函数,生成键值对元素;然后创建并初始化multimap容器
multimap<string,int> mymultimap{make_pair("penny", 1),make_pair("leonard",2),make_pair("sheldon",3)
};

方法三:
拷贝(复制)构造函数,也可以初始化新的multimap容器。

//创建一个会返回临时multimap对象的函数
multimap<string,int> tmpmultimap(){multimap<string,int> tempmultimap{{"penny",1},{"leonard",2}};return tempmultimap;
}
//在main函数中调用multimap类模板的移动构造函数创建newmultimap容器
multimap<string,int> newmultimap(tmpmultimap());

方法四:
multimap类模板还支持从已有的multimap容器中,选取某块区域内的所有键值对,用作初始化新multimap容器时使用。

#include<iostream>
#include<map>
#include<string>
using namespace std;
int main(){//创建并初始化multimap容器multimap<string,int> mymultimap{{"penny",1},{"leonard",2},{"sheldon",3},{"howard",4}};multimap<string,int> newmultimap(++mymultimap.begin(),mymultimap.end());      for(auto iter = newmultimap.begin(); iter != newmultimap.end(); iter++){cout<<iter->first<<" "<<iter->second<<endl;}return 0;
}

和map容器相比,multimap未提供at()成员方法,也没有重载[ ] 运算符。map容器中通过指定键获取指定键值对的方式,将不再适用于multimap容器。multimap容器提供的成员方法,map容器都有提供,并且它们的用法是相同的。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • App推广新姿势:Xinstall地推码,一键直达用户心!
  • 嵌入式高频面试题——第一章 进程与线程(上)
  • Redis Stream 助力:打造实时用户行为日志处理平台
  • 分类预测|基于麻雀优化核极限学习机的数据分类预测Matlab程序SSA-KELM 多特征输入多类别输出 含基础KELM
  • BlinqIO:业界首个生成式 AI 测试平台
  • OpenCV绘图函数(5)绘制标记函数drawMarker()的使用
  • 【Cadence24】如何给PCB板露铜处理
  • pycharm修改文件大小限制
  • Docker网络模型深度解析
  • Java方法的引用
  • Linux —— 驱动——platform平台总线
  • 浅析 Linux 进程地址空间
  • C# 使用 StackExchange nuget 包进行 Redis操作
  • AI 大模型时代,对前端工程师有哪些机遇和挑战?
  • 网络安全售前入门04——审计类产品了解
  • Android开发 - 掌握ConstraintLayout(四)创建基本约束
  • Android路由框架AnnoRouter:使用Java接口来定义路由跳转
  • linux学习笔记
  • vue-loader 源码解析系列之 selector
  • 编写高质量JavaScript代码之并发
  • 基于Vue2全家桶的移动端AppDEMO实现
  • 前端_面试
  • 手机端车牌号码键盘的vue组件
  • 智能网联汽车信息安全
  • TPG领衔财团投资轻奢珠宝品牌APM Monaco
  • 带你开发类似Pokemon Go的AR游戏
  • ​油烟净化器电源安全,保障健康餐饮生活
  • # linux 中使用 visudo 命令,怎么保存退出?
  • # 学号 2017-2018-20172309 《程序设计与数据结构》实验三报告
  • (1)(1.13) SiK无线电高级配置(六)
  • (php伪随机数生成)[GWCTF 2019]枯燥的抽奖
  • (带教程)商业版SEO关键词按天计费系统:关键词排名优化、代理服务、手机自适应及搭建教程
  • (附源码)php投票系统 毕业设计 121500
  • (免费领源码)python#django#mysql公交线路查询系统85021- 计算机毕业设计项目选题推荐
  • (南京观海微电子)——COF介绍
  • (实战)静默dbca安装创建数据库 --参数说明+举例
  • (四)js前端开发中设计模式之工厂方法模式
  • (转载)Linux 多线程条件变量同步
  • .NET delegate 委托 、 Event 事件
  • .Net 基于.Net8开发的一个Asp.Net Core Webapi小型易用框架
  • .NET 使用 ILMerge 合并多个程序集,避免引入额外的依赖
  • .NET 中使用 TaskCompletionSource 作为线程同步互斥或异步操作的事件
  • .NET/C# 在 64 位进程中读取 32 位进程重定向后的注册表
  • .net分布式压力测试工具(Beetle.DT)
  • .NET命名规范和开发约定
  • .NET与java的MVC模式(2):struts2核心工作流程与原理
  • .NET中统一的存储过程调用方法(收藏)
  • []C/C++读取串口接收到的数据程序
  • [4.9福建四校联考]
  • [AIGC] CompletableFuture的重要方法有哪些?
  • [ARM]ldr 和 adr 伪指令的区别
  • [C#]C# OpenVINO部署yolov8图像分类模型
  • [C#]winform制作圆形进度条好用的圆环圆形进度条控件和使用方法
  • [C++数据结构](31)哈夫曼树,哈夫曼编码与解码
  • [DEBUG] spring boot-如何处理链接中的空格等特殊字符