函数模板
与普通函数区别:
1.普通函数调用存在隐式类型转换
2.自动类型推导调用时,不发生隐式类型转换
3.显示指定类型调用可以发生隐式类型转换
与普通函数重名时:
1,.默认调用普通函数
2.通过空模板参数类表(Max<>)强制调用函数模板
3.函数模板可发生重载(参数个数不同)
4.函数模板可产生更好的匹配时优先调用函数模板
例:普通函数:void Fun(int a,int b){}
函数模板:template viod Fun (T a,T b){};
调用Fun(a,b)//a,b为char类型时普通函数需隐式转换int为char,函数模板只需将T制定为char类型,即优先调用函数模板。
模板局限性:如自定义类型对比(解决方法1.在自定义类型中重置内置运算符,2.利用具体化模板实现代码)=>template <> bool Compare(Person p1,Person p2)
{
if(p1.name ==p2.name&&p1.age == p2.age)
return true;
else
return false;
};
声明格式:
template //或写成与class无区别
//需要不同类型参数时<typename T1,typename T2>u77
返回值 函数名 (形参表)
{
函数体;
}
template
T Max(T Inpute1, T Inpuet2)
{
return (Inpute1 > Inpute2) ? Inpute1 : Inpute2;
}
使用:
1.自动类型推导
Max(a,b);
2.显示指定类型
Max(a,b);
类模板//与函数模板区别:1.没有自动类型推导,
2.在模板参数列表中可以有默认参数template //未指定类型是默认为int

template
class 类名
{
类定义;
}
template <class T1,class T2>
class Person
{
public:
Person(T1 name,T2 age)
{
this->Name = name;
this->Age =age;
}
void ShowPerson(T1 name,T2 age);
private:
T1 Name;
T2 Age;
}
在类外定义成员函数时:
template
返回值类型 类名::函数名(T x,T y)
{
函数体;
}
template <typename T1, typenme T2>
void Person<T1,T2>::ShowPerson(T1 name,T2 age)
{
cout<<name<<age<<endl;
}
类模板声明对象:
类名<泛型数据类型> 对象名;
Person<string,int> p ("Wei",17);

类模板对象作为函数参数
1.指定传入类型
void PrintPerson(Person<string ,int> &p)
{
p.ShowPerson(p.name,p.age);
}
2.参数模板化
template <class T1,class T2>
void PrintPerson(Person<T1 ,T3> &p)
{
p.ShowPerson(p.name,p.age);
}
3.整个类模板化
template
void PrintPerson(T &p)
{
p.ShowPerson(p.name,p.age);
}

类模板与继承
1.当子类继承的父类为一个类模板时,子类在声明时必须指定父类中T的类型。
template
class Base
{
T m;
}
class Son :public Base//指定父类T类型
{

};
2.如果不指定 ,编译器无法为子类分配内存。
3.如想灵活指定父类T类型,则需将子类也定义为类模板。
template <class T1, class T2>//子类也定义为类模板
class Son :public Base
{
T1 obj;
};
Son<int,char> s1;
——————————————————————————————————————
STL

Vector:单端数组,动态拓展:开辟一块更大的空间拷贝数据,释放原来空间。
迭代器:v.begin()//指向容器首位置
v.end()//指向容器最后一位的下一个位置
v.rend()//首位的前一位置
v.rbegin()//指向最后一位元素
支持随机访问
构造函数:
vector v;// 默认构造函数
vector(v.begin(),v.end())// 将v的首末拷贝到本身
vector(n,elem)// 将n个elem拷贝给本身
vector(const vector &vec)// 拷贝构造函数
赋值操作:
operator=
v.assign(v1.begin(), v1.end())
v.assign(n,elem);
容量大小方法:
empty()//判断容易是否为空;
capacity()//容器容量
size()//容器中元素的个数
resize(int num)//重新制定容器的长度为num
resize(int num elem)//重新定义容器长度,并默认以elem填充
插入/删除方法:
push_back(ele);//在尾部插入数据
pop_back()//在尾部删除数据
insert(const_iterator pos, ele)//在迭代器所指向位置插入ele
insert(const_iterator pos, int count, ele)//在迭代器所指向位置插入count个ele
erase(const_iterator pos);//删除迭代器所指向的元素
erase(const_iterator start, const_iterator end)//清除迭代器s-e之间的元素
clear();//清空元素

#include
#include "pch.cpp"
#include
#include
using namespace std;

int main()
{
//cout << "WEI" << endl;
Fun1();
return 0;

}
void Fun1()
{
//创建Vector容器
vector v;

//向容器中插入数据
v.push_back(10);
v.push_back(20);
v.push_back(30);
v.push_back(40);
v.push_back(50);

////通过迭代器访问容器中的数据
//vector<int >::iterator itBegin = v.begin();//起始迭代器,指向容器第一个元素
//vector<int >::iterator itEnd = v.end();//结束迭代器,指向最后一个元素的下一个位置

////遍历方式
//while (itBegin != itEnd)
//{
//	cout << *itBegin << endl;
//	itBegin++;
//}

//遍历方式二
for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
{
	cout << *it << endl;
}

//第三种 STL提供的遍历算法
for_each (v.begin(), v.end(), MyPrint);

}
void MyPrint(int var)
{
cout << var << endl;
}

C++链表List
优点:可在任意位置插入大量元素,修改指针即可不需要移动大量元素;动态内存分配,不会造成内存浪费和溢出
缺点:空间(占用空间比较大),时间(遍历速度慢)的额外消耗较大;插入和删除操作不会造成原来的迭代器失效,这在vector中是不成立的(数组装满后会开辟新的更大的空间拷贝源数据,但迭代器仍指向原地址)
//遍历方法
void MyList::printList(const list& L)
{
for (list::const_iterator it = L.begin(); it!= L.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
void MyList::List()
{
//创建Lis容器
list Li; //默认构造

	//添加数据
	Li.push_back(10);
	Li.push_back(20);
	Li.push_back(30);
	Li.push_back(40);

	//遍历容器
	printList(Li);

	//区间构造
	list<int> L2(Li.begin(), Li.end());
	printList(L2);

	//拷贝构造
	list<int > L3 (L2);
	printList(L3);

	//N个ELE构造
	list<int> L4(10, 999);
	printList(L4);

    //**赋值 **=
	list<int> L5;
	L5 = L4;
	//区间
	list<int> L6;
	L6.assign(L4.begin(), L4.end());
	//n*Ele
	list<int> L7;
	L7.assign(5, 7);

	//交换
	printList(L6);
	printList(L7);
	L7.swap(L6);
	printList(L6);
	printList(L7);

    //**list大小操作**
	cout<<L7.size()<<endl;//返回容器元素个数
	cout << L7.empty()<<endl;//容器是否为空
	L7.resize(7);//重新定义容器长度,多则0填充,少则从末尾删除
	printList(L7);
	L7.resize(10, 777);//重新定义容器长度,多则ele填充,少则从末尾删除
	printList(L7);

    //**插入/删除**
	list<int> insDle(5,7);
	//头插
	insDle.push_front(3);
	insDle.push_front(2);
	insDle.push_front(1);
	//尾插
	insDle.push_back(7);
	insDle.push_back(8);
	insDle.push_back(9);
	printList(insDle);
	//尾删除
	insDle.pop_back();
	//头部删除
	insDle.pop_front();
	printList(insDle);

	//insert插入
	list<int>::iterator it = insDle.begin();
	insDle.insert(++it, 23);
	printList(insDle);
	//删除
	it = insDle.begin();
	insDle.erase(it);
	printList(insDle);
	//移除所有同样的元素
	insDle.remove(7);
	printList(insDle);
	//清空
	insDle.clear();
	printList(insDle);
    //数据存取
	L7.front();
	L7.back();
	list<int>::iterator Linklist_it = L7.begin();
	Linklist_it++;//支持双向
	Linklist_it--;//不支持--则为单相访问
	//Linklist_it = Linklist_it + 1;//可以这样写着表示可以支持随机访问,链表不支持随机访问。

	//链表反转/排序
	printList(L7);
	L7.reverse();
	printList(L7);
	//排序
	list<int> ls;
	ls.push_back(3);
	ls.push_back(1);
	ls.push_back(2);
	//所有不支持随机访问到迭代器的容器,不支持标准算法
	//容器内部会提供对应的一些算法
	ls.sort();//默认升生序排序
	//MyList l;
	//ls.sort(l.MyCompare);
	printList(ls);
}
}
例:两数之和LC
list<int> TowAddList(list<int>* l1, list<int>* l2)

{
list res;
list::iterator pos1 = l1->begin();
list::iterator pos2 = l2->begin();
int digit = 0;
while (pos1!=l1->end()||pos2!=l2->end())
{
int total = digit;
if (pos1 != l1->end())
{
total += *pos1;
pos1++;
}
if (pos2 != l2->end())
{
total += *pos2;
pos2++;
}
digit = total / 10;
res.push_back(total % 10);
}
if (digit != 0)
{
res.push_back(digit);
}
return res;
}
—————————————————————————————————————————
哈希表/(键值对)
map/multimap:元素为pair键值对,底层容器由二叉树实现
优点:根据key可以快速找到value
map不允许有重复的key
multimap允许有重复的key
class MyTable
{
public:
void MapText()
{
//默认构造
map<int, string> m1;//map会根据键的值进行默认的排序,与先后插入顺序无关
m1.insert(pair<int, string>(1, "A"));
m1.insert(pair<int, string>(3, "C"));
m1.insert(map<int, string>::value_type(2,"B"));
//m1.insert(pair<int, string>(3, "C"));
m1.insert(pair<int, string>(7, "W"));
printMap(m1);

		//拷贝构造
		map<int, string>m2(m1);
		printMap(m2);
		//赋值
		map<int, string> m3 = m2;
		m3.erase(7);
		m3.insert(pair<int ,string>(11, "Z"));
		printMap(m3);

		//大小和交换
		cout << m1.size()<<endl;
		cout << m1.empty()<<endl;

		m2.swap(m3);
		printMap(m2);
		printMap(m3);

		//插入/删除
		map<int, string> m7;
		m7.insert(pair<int ,string>(1, "A"));			
		m7.insert(pair(2, "B"));
		m7.insert(make_pair(3, "C"));
		m7.insert(map<int, string>::value_type(7, "W"));
		m7[5] = "Z";//不存在Key时,会创建该键值为类型默认值,不建议使用,可以用来读取键中的值
		printMap(m7);

		//删除
		m7.erase(m7.begin());
		m7.erase(3);//按照key删除
		//m7.erase(m7.begin(), m7.end());
		//m7.clear();
		m7.insert(pair(17, "Z"));
		printMap(m7);

		//查找,返回值为迭代器,未找到2时返回容器的end()
		map<int, string>::iterator pos = m7.find(7);
		if (pos != m7.end())
			cout << (*pos).first <<" "<<(*pos).second << endl;
		//统计,1/0,multimap允许键重复适用此方法
		int n = m7.count(7);
		cout << n << endl;
	}
	void printMap(map<int, string> m)
	{
		for (map<int, string>::iterator it = m.begin(); it != m.end(); it++)
		{
			cout << "KEY: "<<(*it).first <<" "<< "Value:"<<(*it).second<<endl;
		}
		cout << endl;
	}
};

//改为降序排序的仿函数

class MyMapSort
{
public:
bool operator() (int a,int b)
{
//降序:第一个数大于第二个数
return a > b;
}
};
void textmap()
{
map<int, int,MyMapSort> m;//默认按照键从小到大排序
m.insert(pair(1, 1));
m.insert(pair(3, 3));
m.insert(pair(2, 2));

//m.insert(pair(3, 3));
m.insert(pair(4, 4));
m.insert(pair(5, 5));

for (map<int,int, MyMapSort>::iterator it = m.begin(); it!=m.end(); it++)
{
	cout << "key:" << (*it).first << " " << (*it).second << endl;
}

}