【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"));
	
}


第一次作业 这个作业将让你去练习建立一些简单的类和使用C++的基本功能,包括:封装,引用,动态内存开辟, 简单构造函数和析构函数和const。 下面给的程序片段未经过编译或调试. 做出合理的错误修正是你任务的一部分。 一般的,我们会给你最基本部分的代码,如果你需要,你可以在一个类里添加额外的变量或方法,这个作业被分为三个部分,那么你们要按照步骤一步一步地完成。 1. 设计要求 第一部分) 构建简单的类 R1.1) 创建一个Person类, 其模型在下面的代码结构里。 R1.2) 人类(Persons)应该有一些属性: name, email_address, birthdate 作为表示人类的属性。 R1.3) 按下面的要求创建一个Date类。 R1.4) 每个类都应该可以使用输出运算符(<<)输出内容。 //file Date.h class Date { public: Date(); Date( int year, int month, int day ); ... private: int _year; int _month; int _day; }; //end file Date.h //file Person.h class Person { public: Person(void); Person(char * their_name, char * email, int day, int month, int year); char * GetName(); char * GetEmailAddress(); Date GetBirthDate(); void Print(); private: char* name; char* email_address; Date date; }; //end file Person.h 第二部分) 构建一个容器类 Set container. R2.1) 建立一个set的模型PersonSet类, 并且它只能保存Person的对象. R2.2) 这个set应该存储person的地址(指针),以便可以获取原始对象(非拷贝). R2.3) set的存储应该用动态数组来保存Person的指针(用new来创建), 但是set不应该有界限(数组大小), 它们应该在成员进添加或移除时,适当进扩展.. R2.4) 成员不按任何特定顺序存储(无排序). R2.5) set允许存储副本(相同对象). R2.6) Add() 函数应该当在添加的时候,并且需要的情况,进扩展数组大小并且输出一串信息. R2.7) Remove() 函数应该在移除的时候, 并且在需要的情况, 可以进缩小数组大小并输出一串信息. R2.8) Add() 函数应该带一个引用类型的参数(Person&). R2.9) 迭代应该通过NextElement()函数来提供. R2.10) NextElement()和 RemoveElement() 应该通过引用返回 对于现在我们将去建立sets去只保存Person对象,因此类名是PersonSet. //file PersonSet.h class PersonSet { public: //default constructor allocate appropriate heap storage store elements on //heap array declared like this: new Person*[initial_size]; PersonSet (int initial_size = 4); //store element in the set if the set is full allocate more memory ~ PersonSet (void); public: void Add(Person & element) ; Person & NextElement() ; // 从set中移除最后一个成员 //如果Set空的数据超过一半,释放一些内存 Person & RemoveElement(); // 从Set中的index索引处移除成员 // 如果Set空的数据超过一半, 释放一些内存 Person & RemoveElement( int index ); int Size(); //answer the number of elements in the set. void Print();
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值