近万字带你了解“c++“STL中的各种容器

目录

1.array容器

 vector 和 array镶嵌使用

4.链表容器(list)是一个库封装好的一个双向链表

5.priority_queue: 优先队列

6.map和multimap

7.set和multiset


1.array容器

包含头文件#include<array>才能使用

简单来说他就是一个数组 知识c++中把他封装成一个类 这样可以直接使用

使用方法是array<类型,长度> 

我们自己实现一个myarray带大家了解一下过程

#include<iostream>
#include<array>
using namespace std;
template<class _Ty,size_t size>
class myarray
{
public:
	
	myarray()
	{
		//由给定的长度类型构造出来
		memory = new _Ty[size];
	}
	//这里要返回引用 表示[]表示调用类中的数据
	_Ty& operator[](int index)
	{
		return memory[index];
	}
	_Ty front()
	{
		return memory[0];
	}
	_Ty back()
	{
		return memory[size - 1];
	}
	_Ty at(int index)
	{
		return memory[index];
	}
public:
	//迭代器可以理解为就是一个指针 
	class iterator
	{
	public:
		iterator(_Ty* pmove = nullptr) :pmove(pmove) {};
		//重载迭代器地址赋值=
		void operator=(iterator object)
		{
			this->pmove = object.pmove;
		}
		bool operator!=(iterator object)
		{
			return this->pmove != object.pmove;
		}
		iterator operator++(int)//里面有int为前置
		{
			pmove++;
			return (*this);
		}
		_Ty operator*()
		{
			return *pmove;
		}
	protected:
		_Ty* pmove;

	};
public:
	//使用这个函数时表示指向数组首地址
	iterator begin()
	{
		return iterator(memory + 0);//调用构造函数去赋值
	}
	iterator end()
	{
		return iterator(memory + size);//调用构造函数去赋值
	}

protected:
	_Ty* memory;
};
int main()
{
	
	myarray<int, 3>k;
	//因为我们这里简单实现没有在构造函数里面写初始化参数列表
	for (int i = 0; i < 3; i++)
	{
		//相当于调用重载函数[]
		k[i] = i;
	}
	myarray<int, 3>::iterator iter;
	for ( iter= k.begin(); iter != k.end(); iter++)
	{
		cout << *iter;//*调用*的重载函数
	}

	return 0;
}

2.vector容器

理解就是想当于一个长度可以变换的数组

包含头文件#include<vector>才可以使用

使用方法:

vector<类型>或者vector<类型>变量名(长度)//后置可以当一个以为数组去简单赋值

vector<int> testv;
	for (int i = 0; i < 5; i++)
	{
		testv.push_back(i);
	}
	vector<int>testv2(5);
	for (int i = 0; i < 5; i++)
	{
		testv2[i] = i;
	}

    所以一般在使用动态数组,有个习惯
    带长度创建的vector 一般都是用下标法使用
    不带长度的vector,采用成员函数的方式操作

 遍历vector容器和数组是一样的因为容器里面都包含了iterator(迭代器) 可以去实现遍历

 vector 和 array镶嵌使用

    No.1 array与array嵌套
    No.2 vecotr与vecotr嵌套
    No.3 array与vector互相嵌套

array和array

array<array<int, 3>, 2> test;
	//就相当一个二行每行有三个元素的数组
	//理解把array<int,3>看成一个类型
	for (int i = 0; i < 2; i++)
	{
		for (int j = 0; j < 3; j++)
		{
			test[i][j] = i;
		}
	}
	for (int i = 0; i < 2; i++)
	{
		for (int j = 0; j < 3; j++)
		{
			cout << test[i][j] << "  ";
		}
		cout << endl;
	}

array和vector

array<vector<int>, 3>test;
	//相当于有一个三个vector<int>数组
	for (int i = 0; i < 3; i++)
	{
		test[i].push_back(5);
		test[i].push_back(6);
	}
	test[1].push_back(1);
	for (int i = 0; i < 3; i++)
	{
		for (int j = 0; j < test[i].size(); j++)
		{
			cout << test[i][j]<<"  ";
		}
		cout << endl;
	}

vector和vector

vector<vector<int>>test(3);
	//有长度的表示有3个vector<int>
	//就等效于二维数组有三行但是每行的列数是可以变化的
	for (int i = 0; i < test.size(); i++)
	{
		test[i].push_back(5);
		test[i].push_back(6);
	}
	test[2].push_back(5);
	for (int i = 0; i < test.size(); i++)
	{
		for (int j = 0; j < test[i].size(); j++)
		{
			cout << test[i][j] << "  ";
		}
		cout << endl;
	}
	cout << endl;

4.链表容器(list)是一个库封装好的一个双向链表

里面包含的一些常使用函数

       push_back()
        pop_back();
        push_front();
        pop_front();
        size();
        empty();
        erase+find
        insert+
        sort();

void printflist(list<_Ty> data)
{
	for (auto v : data)
	{
		cout << v << endl;
	}
}
int main()
{
	list<string> testlist;
	testlist.push_back("fsdj");//相当于尾插
	testlist.push_back("erowe");
	testlist.push_front("erewe");//头插
	testlist.push_back("a");
	testlist.sort();//默认是小到大的//这里就是字母排序
	cout << "less<string>()排序准则" << endl;
	printflist(testlist);
	//大到小的排序准则
	cout << "greater<string>()排序准则" << endl;
	testlist.sort(greater<string>());
	printflist(testlist);

	return 0;
}

链表存储自定义类型:

主要了解排序准则

1.靠类中重载的方式调用括号来调用函数接口

2.直接写函数来调用接口

#include<iostream>
#include<vector>
#include<array>
#include<list>
#include<string>
using namespace std;
template<class _Ty>
void printflist(list<_Ty> data)
{
	for (auto v : data)
	{
		cout << v;
	}
}


class MM
{
public:
	MM(string name, int year) :name(name), year(year) {};
	//重载输出就可以打印对象成员
	friend ostream& operator<<(ostream& out, MM& object)
	{
		out << object.name << "  " << object.year << endl;
		return out;
	}
	//获取对象的年龄
	int& getyear()
	{
		return this->year;
	}
	string& getname()
	{
		return this->name;
	}
protected:
	string name;
	int year;
};
//重写排序准则仿函数
class compareyear
{
	//重载括号
public://要共有类 不然不能用()代表函数来提供接口
	bool operator()(MM object1, MM object2)
	{
		return object1.getyear() > object2.getyear();//年龄大到小的准则
	}
};
//
bool comparesname(MM object1, MM object2)
{
	return object1.getname() < object2.getname();
}
int main()
{

	list<MM>test1;
	test1.push_back(MM("张三", 18));
	test1.push_back(MM("李四", 28));
	test1.push_back(MM("王五", 78));
	cout << "按年龄大到小的排序准则" << endl;
	test1.sort(compareyear());
	//解释这个compareyear()这里括号就相当于调用了里面类中的函数
	//提供一个接口
	printflist(test1);
	test1.sort(comparesname);//提供一个函数 提供一个接口
	cout << "按姓名小到大的排序准则" << endl;
	printflist(test1);//按姓名排序
	return 0;
}

5.priority_queue: 优先队列

按照特定数据特定的标准排序的队列

 接下来用vector写一个容器中的优先队列带大家了解一下基础操作

//

#include<iostream>
#include<vector>
#include<array>
#include<list>
#include<string>
#include<algorithm>
using namespace std;
template<class _Ty,class _contain=vector<_Ty>,class _pr=less<_Ty>>
//分别为类型 容器 排序准则
class priority_queue
{
public:
	priority_queue() = default;//默认的构造函数
	void push(_Ty data)
	{
		mem.push_back(data);
		sort(mem.begin(), mem.end(), _pr());//容器排序
	}
	void pop()
	{
		mem.erase(mem.begin());//出队列
	}
	const _Ty& top()
	{
		return mem.begin();
	}
	bool empty()const
	{
		return mem.empty();
	}
	int size()const
	{
		return mem.size();
	}
protected:
	_contain mem;//就是容器
};


int main()
{
	priority_queue<int> test1;
	for (int i = 10; i >= 0; i--)
	{
		test1.push(i);
	}
	cout << test1.size() << endl;
	test1.pop();
	cout << test1.size();
}

6.map和multimap

    No.1 map是  映射,就是一种对应关系(数组:下表与值对应)
        1.1 排序性 (按照键的排序)
        1.2 唯一性 (按照键的唯一性)  相同键的时候,不做插入
        1.3 存储的数据是一个数对类型: pair<Type1,type2>;
            first:键  second:值

map<类型,类型,排序准则(默认缺省为小到大)>

排序准则是按键值来的

#include<iostream>
#include<string>
#include<algorithm>
#include<map>
using namespace std;
int main()
{


	map<int, string> test;
	//下标插入
	test[1] = "sdfj";
	test[-1] = "oiwer";
	//用pair类构造
	test.insert(pair<int, string>(6, "sfewr"));
	//insert插入 用make_pair构造
	test.insert(make_pair(5, "sfd"));
	
	for (map<int, string>::iterator iter = test.begin(); iter != test.end(); iter++)
	{
		cout << iter->first << "  " << iter->second << endl;
		//分别为打印键和打印值
	}
	//存在默认的排序函数 
	return 0;
}

用map去操作自定义类型主要:是重写排序函数 

排序准则下的比较要加const修饰安全起见防止被修改里面的值

#include<iostream>
#include<map>
using namespace std;
class Boy
{
public:
	friend ostream& operator<< (ostream& out, Boy one)
	{
		out << one.getAge() << "  " << one.getName();
		return out;
	}
	Boy() = default;
	Boy(string name, int age) :name(name), age(age) {}
	string getName()const
	{
		return name;
	}
	int getAge()const
//作为排序准则比较要加const
因为map内部是一个const对象
	{
		return age;
	}
protected:
	string name;
	int age;
};
class MM
{
public:
	MM() = default;
	MM(string name, int age) :name(name), age(age) {}
	friend ostream& operator<< (ostream & out, MM one)
	{
		out << one.getAge() << "  " << one.getName();
		return out;
	}
	string getName() 
	{
		return name;
	}
	int getAge()
	{
		return age;
	}
protected:
	string name;
	int age;
};
class LessByAge
{
public://重写的排序准则要加const
	bool operator()(const Boy& one, const Boy& two)const
	{
		return one.getAge() < two.getAge();
	}
};
int main()
{

	map<Boy, MM, LessByAge> bm;
	bm[Boy("张三", 28)] = MM("小芳", 28);
	bm[Boy("李四", 18)] = MM("小美", 28);
	bm[Boy("王五", 38)] = MM("小丽", 18);
	bm.insert(make_pair(Boy("李六",19) ,MM("燕子", 19)));
	bm.insert(pair<Boy, MM>({ Boy("老七",15),MM( "颗粒", 17 )}));
	for (auto v : bm)  //v pair<Boy,MM>
	{
		cout << v.first << "配对" << v.second << endl;
		
	}
	return 0;
}

注意;

以什么为排序准那么这个排序准则中的数字就不能相同

如:这里中Boy类型不能用相同年龄的有就会取第一个后面一个不取

multimap

 //多重映射: 只具有排序性
//键是允许重复,所以不存在下标法访问

    multimap<int,string> test;
	//因为multimap可以存在相同的键值所有这样是错的
	test[1] = "kk";

插入的方法:

    test.insert(make_pair(5, "ksdf"));
	test.insert(pair<int, string>(5, "fsd"));
	for (map<int, string>::iterator iter = test.begin(); iter != test.end(); iter++)
	{
		cout << iter->first << "  " << iter->second << endl;
	}

7.set和multiset

    No.1 set:集合  用来存储数据
        1.1 有序性,默认从小到大
        1.2 唯一性,不重复

    set<int> test = { 8,5,6,2,2,4 };
	for (set<int>::iterator iter = test.begin(); iter != test.end(); iter++)
	{
		cout << *iter << "  ";
	}
输出后是一个2 4 5 6 8
    set<int,greater<int>> test = { 8,5,6,2,2,4 };
	for (set<int>::iterator iter = test.begin(); iter != test.end(); iter++)
	{
		cout << *iter << "  ";
	}
输出结果是8 6 5 4 2
这里的排序准则直接写个对象greater<int>
是因为在调用set里面排序的时候会自动去调用对象里面的函数

multiset

只具有排序的功能可以出现相同的数字

multiset<int> test = { 1,1,2,2,3,5 };
	for (set<int>::iterator iter = test.begin(); iter != test.end(); iter++)
	{
		cout << *iter << "  ";
	}
输出就是1 1 2 2  3 5
	multiset<int,greater<int>> test = { 1,1,2,2,3,5 };
	for (set<int>::iterator iter = test.begin(); iter != test.end(); iter++)
	{
		cout << *iter << "  ";
	}
输出就是5 3 2 2 1 1

猜你喜欢

转载自blog.csdn.net/weixin_56366633/article/details/121569303