【C++】500行代码全解STL_string_vector_remove和erase实现逻辑_deque_queue_list_pair_set_multiset_map_multimap

//STL六大类:
//容器: 各种数据结构(Vvector,list,deque,set,map等等)
//算法: 常用算法,如sort,find,copy,for_each.
//迭代器: 容器和算法间的联系纽带
//仿函数: 行为类似仿函数,可作为算法的某种策略。
//适配器(配接器: 修饰容器和或者仿函数迭代器接口的东西
//空间配置器: 负责空间的配置和管理。

*一、string类型

1-1声明和赋值

void string_01()
{
	string s1;  //声明
	//下面为赋值方式
	getline(cin, s1);
	cout << s1 << endl;
	char s2[] = "kakamolaiwe";
	string s3(s2);
	cout << s3 << endl;
	const char *c = "nishishuis所示";
	string s4(c);
	cout << s4 << endl;
	string s5(5, 'g');
	cout << s5 << endl;
	//用 [ ] 调用和赋值
	cout<<s5[2]<<endl
	

	

1-2string中的功能函数

void string_02()
{
	//赋值函数
	string s0 = "kkskskshjs";
	char c[] = "这是一个char型数组";
	const char *c2 = "这是一个char*型";
	string s1;
	s1 = s0;
	cout << s1 << endl;
	string s2;
	s2 = 2;
	cout << s2 << endl;
	s2 = c2;
	cout << s2 << endl;
	s2.assign(s0);
	cout << s2 << endl;
	s2.assign(c);
	cout << s2 << endl;
	s2.assign(c2);
	cout << s2 << endl;
	s2.assign(c2, 3);
	cout << s2 << endl;
	s2.assign(34, 'f');
	cout << s2 << endl;
	s2.assign("hello", 3);
	cout << s2 << endl;


}

1-3 string字符串拼接

//string字符串拼接
void string_04()
{
	string s = "卡卡";
	const char *c = "molaiwei";
	char c2[] = { 's','i' };
	char c3[] = "shuaige";
	s += c;
	cout << s << endl;
	s += c2;
	cout << s << endl;
	s += c3;
	cout << s << endl;
	string s1;
	s1.append(s);
	s1.append(c, 3, 6);
	s1.append(c2, 1);
	s1.append(c3);
	s1.append(5, 'f');
	s1.append("lox");
	cout << s1 << endl;
	//从左查找然后输出位置,0开始
	int pos = s1.find('m');
	//从右开始查找字符,输出位置。
	int pos2 = s1.rfind("卡卡");
	//0-3替换为kaka
	//s1.replace(0, 3, "kaka");
	cout << pos << pos2 << endl;
	cout << s1 << endl;
	//字符串比较(逐位比较ascii码值)
	int bo = s1.compare(s);
	cout << bo << endl;
	//读取和写入如字符串中单独位置元素
	cout << s1.at(4) << "  " << s1[5] << endl;
	s1 = "kakamolaiwei";
	//插入和删除
	s1.insert(3, "ka");
	cout << "s1" << s1 << endl;
	//0后面3个全删除了
	s1.erase(0, 3);
	cout << s1 << endl;
	//取子串,位置2后面取4个。
	string sub = s1.substr(2, 4);
	cout << sub << endl;
}

**

二、vector容器

**

2-1 被调用函数外部实现

//遍历int型Vector对象函数

void printVector(vector<int> &p)
{    //利用迭代器访问
	for (vector<int>::iterator it = p.begin(); it != p.end(); it += 1)
	{

		cout << *it << '\t';
	}
	cout << endl;
}

//遍历string型Vector对象

void printStrVec(vector<string>&p)
{
	for (vector<string>::const_iterator it = p.begin(); it != p.end(); it++)
	{
		cout << *it << " ";
	}
	cout << endl;
}

//将两个int型vector对象拼接

void  pushback1(vector<int>&v1, vector<int>&v2)
{
	for (vector<int>::iterator it = v2.begin(); it != v2.end(); it++)
	{
		v1.push_back(*it);
		cout << *it << endl;
	}
}

2-2 vector使用主函数

void test05()
{
	vector<int>v;
	for (int i = 5; i < 16; i++)
	{
		v.push_back(i);
	}
	printVector(v);
	//调用的直接是对象本身,区别于迭代器
	for_each(v.begin(), v.end(), printPTR);
	vector<int>v2;
	for (int i = 17; i < 26; i++)
	{
		v2.push_back(i);
	}
	printVector(v2);
	//v2.assign(v.begin(),v.end());
	//printVector(v2);

	vector<int>v3(v);
	printVector(v3);
	v3 = v2;
	printVector(v3);
	pushback1(v3, v);
	printVector(v3);
	v3 = { 1,2,3 };
	printVector(v3); //输出1 2 3
	//v3的容量(动态分配的)始终比大小大,大小指的是存放的元素个数。
	cout << "v3的容量" << v3.capacity() << "v3的大小" << v3.size() << endl;
	v3.resize(5);
	//重新指定大小后,多余的大小用0代替,当vector插值或者复制等改变大小的操作时
	//相对于静态地数组,容器(动态分配)会重新找一个内存,将之前的元素拷贝过来,然后再完成各种操作。
	printVector(v3); //输出: 1 2  3  0  0
	cout << "v3的容量" << v3.capacity() << "v3的大小" << v3.size() << endl;
	//vector插值和删除
	v3 = { 0 };
	cout << "各种插入类型" << endl;
	//尾插
	v3.push_back(1);
	v3.push_back(2);
	v3.push_back(3);
	//尾删
	v3.pop_back();
	vector<int>v4(v3);
	//自定义位置插入(选哪个位置插哪个位置前面,选0,就插在首位)
	v3.insert(v3.begin(), 6);
	printVector(v3);
	//擦除也是需要穿迭代器
	vector<int>::iterator a = v3.begin()++;
	vector<int>::iterator b = v3.begin() + 2;
	v3.erase(v3.begin(), --v3.end());
	cout << "是否完全擦除" << endl;
	printVector(v3);
	v4 = { 3,2,6,1,2,5,7,2,5,7 };
	printVector(v4);  //打印:3,4,6,1,2,5,7,2,5,7
	//remove返回的是新的 end() ,将容器里面值为为2的元素放在容器后面(也即是原来的 end()后面)
	//因为不是Vector的函数,所以不会改变其大小和容量,原begin()和end()指向位置不变,但是begin()和新的end()之间移除2的位置由后一元素补充
	//但是新end()和旧end()之间仍然指向的是之前的元素,做的一种逻辑上的删除。
	auto p = remove(v4.begin(), v4.end(), 2);  //将容器中所有的不为2的元素前移,返回新的end()迭代器,指向后面全部2的第一个位置。
	printVector(v4);   //打印:3,4,6,1,5,7,5,7,5,7
	//用erase或者resize擦除所有2;
	//v4.erase(p, v4.end());
	v4.resize(8);
	printVector(v4);   //打印:3,4,6,1,5,7,5,7,
	v4.clear();//置空V4
	printVector(v4);
	cout << "v4的容量" << v4.capacity() << "v4的大小" << v4.size() << endl;

	//元素访问
	vector<string> str = { "ka","ka","molaiwei" };
	string str2 = "kakamolaiwei";
	//用at访问
	cout << str.at(1) << endl;
	cout << str2.at(1) << endl;
	//用back和front获取尾首元素
	cout << "首元素是:" << str.front() << "尾元素是:" << str.back() << endl;
	cout << "首元素是:" << str2.front() << "尾元素是:" << str2.back() << endl;
	//用迭代器访问
	//用[ ]访问
	cout << "用[ ]访问" << str[2] << endl;
	cout << str2[6] << endl;
	//同类型容器元素互换 利用swap()函数,容量大小也互换
	vector<string> str3 = { "临时", "参数" };
	cout << "交换前str :"; printStrVec(str);
	cout << "交换前str3 "; printStrVec(str3);
	cout << "交换前str容量大小:" << str.capacity() << " " << str.size() << endl;
	cout << "交换前str3容量大小:" << str3.capacity() << " " << str3.size() << endl;
	str3.swap(str);
	cout << "交换后str :"; printStrVec(str);
	cout << "交换后str3 "; printStrVec(str3);
	cout << "交换后str容量大小:" << str.capacity() << " " << str.size() << endl;
	cout << "交换后str3容量大小:" << str3.capacity() << " " << str3.size() << endl;
	//利用swap()和其本身同名匿名对象(用完销毁)收缩空间。
	vector<string>(str).swap(str);
	cout << "收缩后str容量大小:" << str.capacity() << " " << str.size() << endl;
	//利用reserve预留空间,让容器在插值时不用一直因为空间不足重新开辟新空间。
	vector<string> str5;
	str5.reserve(1000);  //预留的是size.

}

三、deque容器

3-1 被调函数外部实现
//遍历int型deque对象

void printDeqInt(deque<int>&d1)
{
	for (deque<int>::const_iterator it = d1.begin(); it != d1.end(); it++)
	{
		cout << *it << " ";
	}
	cout << endl;
}

3-2 主函数

void deque_test()
{
	//deque双端队列容器前后端插入比Vector效率高,deque将前后都在缓冲区预留有空间
	//不是像Vector插入多于容量时要重新申请空间,而且在前端插入元素也不像vector一樣需要把後面所有的元素往後移。
	//但是访问的时候没有vector快,因为中控区里面前后端缓冲区和中间队列不在同一个内存地址,
	//只是将他们的地址存在一起,实现逻辑上的连续,deque沒有容量限制,所以獲取不到容量,只能得到大小size
	//1、构造函数
	deque<int>d1{ 0,1,2,3 };
	d1[0] = 2;
	printDeqInt(d1);  //打印2 1 2 3
	//插入 前 後  指定位置
	d1.push_front(-1);
	d1.push_back(4);
	d1.insert(d1.begin() + 2, 1, 6);  //位置3插入 1 個 6.
	printDeqInt(d1);  //打印-1 2 6 1 2 3 4
	//刪除 前 後 指定位置
	d1.pop_back();
	d1.pop_front();
	d1.erase(d1.begin() + 2, d1.begin() + 4);//擦除3,4位置
	printDeqInt(d1);  //打印 2 6  3 
	//用assign賦值
	deque<int> d2;
	d2.assign(d1.begin(), d1.end());
	printDeqInt(d2);  //打印 2 6  3 
	//用resize重新指定大小,默認填充0,指定填充666
	d1.resize(100, 666);
	printDeqInt(d1);  //打印 2 6  3  666 666 666...
	//数据存取 back()  front()  at()  .[ index]
	cout << d1.back() << " " << d1.front() << " " << d1.at(3) << " " << d1[4] << endl;
	//利用sort()函数对指定区域内排序(vector也可使用sort)
	deque<char> ch = { '1','a','Z','?' };
	cout << (int)ch[2] << endl;
	sort(ch.begin(), ch.end()); //从小到大排序
	cout << ch[0] << " " << ch[1] << " " << ch[2] << " " << ch[3] << endl;
}

四、stcak栈容器

//stack栈容器(只能入栈和出栈) 栈底不能操作,栈顶进出,先进后出
//只有栈顶元素能被访问,所以不能遍历(可以判断空empty和size)

void stack_test()
{
	//常用接口
	stack<int> sk;
	sk.push(1);
	sk.push(12);
	sk.push(34);
	//查看每个元素
	while (!sk.empty())   //不为空
	{
		cout << sk.top() << " ";  //top为栈顶元素  打印: 34  12  1
		sk.pop();    //出栈
		cout << sk.size();//  2 1 0
	}
	cout << endl;

}

五、deque容器

//队列容器queue ,头进 尾出,先进先出,只有队头和队尾能被访问,不允许遍历。
//接口 pop 出队 push 入队(从尾部back入队); front 队头 back 队尾;

void test08()
{
	queue<int>  qe;
	for (int i = 0; i < 10; i += 2)
	{
		qe.push(i);
		cout << qe.back() << " ";  //尾部在增加新元素
	}
	if (!qe.empty())   //有可以判断是否为空和大小
	{
		cout << qe.size();
	}
}

## 六、List链表

//普通链表list  三要素: 节点地址指针header,数据域(data),尾指针next(尾指针指向下一个元素节点地址)
//链表最后元素尾指针指向NULL,可以对任意位置插入删除,但是遍历速度没有数组快(寻址作用),占用空间较大
//相对于普通的链表,STL中的list容器是双向循环的链表,利用prev指针指向前一个表头。
//迭代器只支持前移和后移,因为其不是一段连续的空间

```cpp
在这里插入代码片

6-1 被调函数外部实现
//int型list对象遍历

void printListInt(list<int> &p)
{
	for (list<int>::iterator it = p.begin(); it != p.end(); it++)
	{
		cout << *it << '\t';
	}
	cout << endl;
}

6-2 list使用

void test09()
{
	list<int> lis;
	lis.push_back(1);
	lis.push_back(34);
	lis.push_back(56);
	lis.push_back(84);
	lis.push_back(34);
	printListInt(lis);
	list<int> ls2;
	ls2.swap(lis);
	printListInt(lis);
	//函数接口 跟deque类似;尾插,头插,随机插入,擦除erase,清除所有clear()
	//说到底链表容器仍然是一个容器,只是存储的方式跟其他有区别。

	//list的 remove 成员函数
	ls2.remove(34);//移除所有值为34的元素。
	printListInt(ls2);  //打印:1 56 84
	lis = ls2;
	printListInt(lis);
	//list中的数据存取不能用[ ] 和 .at()访问,因为其不是一段连续线性存储空间
	//用迭代器++/--访问
	list<int>::iterator it = lis.end();
	it--;//执行完后位置为3    不能用 it+=1或者it+=2  ,只能逐个移动迭代器指针
	it--;//执行完后位置为2
	it--;//执行完后位置为1即 lis.begin()
	cout << *it << endl;  //打印 1 (第一个元素)
	cout << *++it << endl;  //打印 56 (第二个元素)
	cout << "打印首尾元素" << endl;
	cout << lis.front() << endl;
	cout << lis.back() << endl;

	//list 反转和排序 
	//notice: 所有不支持随机访问迭代器的容器都不支持全局算法<algorithm>
	lis.push_back(23); lis.push_back(85); lis.push_back(7);
	cout << "从小到大排序:  " << endl;
	lis.sort();  //不可以用全局sort,只能用list重载的成员函数.sort()
	printListInt(lis);
	cout << "从小到大排序:  " << endl;
	lis.sort(compare__kaka);  //默认从小到大排列,如果需要从大到小需要加入自己写的带bool返回值规则的函数名
	printListInt(lis);
	lis.reverse();//反转
	cout << "反转函数" << endl;
	printListInt(lis);
}

七、队列模式pair

void pair_test()
{
	//构造函数默认参数构造和make_pair
	pair<string, int> kaka("卡卡", 25);
	pair<string, int> kaka2 = make_pair("卡卡2", 25);
	//利用 .first和 .second访问
	cout << "第一个对组姓名:" << kaka.first << endl
		<< "第二个对组的年龄:" << kaka2.second << endl;
}

八、set/multiset map/multimap

8-1 被调函数外部实现

bool compare__kaka(int &a, int &a2)
{
	return a > a2;
}

//遍历int型set容器
void printSetInt(set<int>&s)
{
	for (set<int>::iterator it = s.begin(); it != s.end(); it++)
	{
		cout << *it << endl;
	}
}

//指定set容器排序规则
class set_compare
{
public:
	bool operator()(int v1, int v2)
	{
		return  v1 > v2;
	}
};

//map/multimap容器遍历操作函数
void printMapSTR(map<int, string>&mp)
{
	for (map<int, string>::iterator it = mp.begin(); it != mp.end(); it++)
	{
		cout << (*it).first << " ";
	}
	cout << endl;
}
void  printMultimapSTR(multimap<string, string>&mp2)
{
	for (multimap<string, string>::iterator it = mp2.begin(); it != mp2.end(); it++)
	{
		cout << (*it).first << " ";
	}
	cout << endl;

}
class map_compare
{
public:
	bool operator()(int a1,int a2)
	{
		return  a1 > a2;
	}
};

8-2 set/multiset容器
//set/multiset 容器:插入自动排序(二叉树),set不允许插入同一个值,multiset可以

void test10()
{
	//支持 swap,size  empty   erase /重载新增erase( elem)
	//不支持resize,和使用at和[ ]访问
	set<int> s1;
	s1.insert(10);   //不可以用push_back;
	s1.insert(110);
	s1.insert(150);
	s1.insert(56);
	printSetInt(s1);  //打印  10 56 110 150
	//查找  find()  找到返回元素位置迭代器,未找到返回.end()  
	cout << "找到元素: " << *s1.find(56) << endl; //打印 56
	//利用仿函数改变set排序规则(默认从小到大)
	set<int, set_compare> s2;
	s2.insert(10);   //不可以用push_back;
	s2.insert(110);
	s2.insert(150);
	s2.insert(56);
	cout << "遍历s2: ";
	for (set<int, set_compare>::iterator it = s2.begin(); it != s2.end(); it++)
	{
		cout << *it << " ";
	}
	cout << endl;//打印 150 110 56 10
}

8-3 map/multimap 容器

void map_test()
{
	//map的 key 值不允许重复,multimap 允许key值重复,并且插入值时会根据第一个即first键值来排序。
	map<int, string> mp;
	mp.insert(pair<int, string>(1, "卡卡"));  //利用对组pair创建匿名数组插入到map容器
	mp.insert(pair<int, string>(6, "卡卡2"));  //利用对组pair创建匿名数组插入到map容器
	mp.insert(pair<int, string>(2, "卡卡3"));  //利用对组pair创建匿名数组插入到map容器
	mp.insert(pair<int, string>(5, "卡卡4"));  //利用对组pair创建匿名数组插入到map容器
	//遍历key值
	cout << "遍历mp key值:  ";
	printMapSTR(mp);

	multimap<string, string> mp2;
	mp2.insert(pair<string, string>("momo", "卡卡"));  //利用对组pair创建匿名数组插入到map容器
	mp2.insert(pair<string, string>("momo", "卡卡2"));  
	mp2.insert(pair<string, string>("啦omo", "卡卡"));  
	mp2.insert(make_pair("啦omo", "卡卡"));  //利用对组pair创建匿名数组插入到map容器
	cout << "遍历mp2key值:  ";
	printMultimapSTR(mp2);

	//map的大小和交换: 可以用swap 和 empty  size  不赘诉
	//插入  insert
	mp2.insert(make_pair("kaak", "卡卡3"));  //利用make_pair  插入
	mp2.insert(map<string, string>::value_type("zailai", "卡卡4"));
	//mp2["momoss"] = "value";  //用 map[ 键值 ] = Value  进行赋值(不建议用作插值,用于访问比较合适)
	printMultimapSTR(mp2);

	//查找操作  find  找到返回迭代器,否则返回尾  .end( ), count(key) 计数
	cout <<"有多少个momo:"<< mp2.count("momo") << endl;  //输出mp2中有多少个 momo
	cout << "找到键值为 momo 的 value:" << (*mp2.find("momo")).second << endl;  //利用键值查找

	//删除操作  erase()  clear()
	mp2.erase(++mp2.begin());//按迭代器删除
	mp2.erase("啦omo");   //按照键值删除
	printMultimapSTR(mp2);
	mp2.erase(++mp2.begin(), --mp2.end());//按区间删除
	printMultimapSTR(mp2);
	//修改map排序方式(默认从小到大)
	map<int, string,map_compare> mp3;  //利用类 map_compare 中的仿函数
	mp3.insert(make_pair(4,"aaa"));
	mp3.insert(make_pair(1, "ssd"));
	mp3.insert(make_pair(2, "sd"));
	mp3.insert(make_pair(5, "sdf"));
	
}


  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值