《C++ STL —— 数据结构与算法实现》 第二章

模板

泛型编程,就是采用一种“通用”的类型来进行代码的编写,使程序独立于特定的数据类型。
此目的在于实现更快捷的代码重用,使程序设计者的主要精力集中在程序逻辑的实现,规避由于不同的数据类型给程序编写带来的麻烦。




函数模板


单类型模板

template <class T>
T Sum(T parameter1, T parameter2){
	
	T sum = paratemer1 + paratemer2;

	return sum;
}

int main(){
	int a=1;
	int b=2;
	float c=1.1;
	float d=2.2;
	
	cout<<Sum(a,b)<<" ";  //Sum<int>(a,b)
	cout<<Sum(c,d)<<" ";  //Sum<float>(c,d)
						  //完整写法

template是模板的关键字,class是标识模板中类型的关键字,替换成typename也行
T就是类型替换符,当我们使用模板时,程序会根据传入的参数类型,自动替换T



多类型模板

#include <iostream>
using namespace std;
template<typename T1,typename T2>

void swap(T1& p1, T2& p2){
	T1 tmp = p1;
	p1 = (T1)p2;
	p2 = (T2)tmp;
}

int main(){
	int a = 10;
	double b = 12.3;
	::swap<int,double>(a,b);
	cout<<a<<" "<<b;    //  12  10.0
}

因为在标准命名空间中,已经有swap这个函数名了,这里在自定义的函数swap前加上::,就表示是该swap函数名,是本次程序自定义的,而不是系统std命名空间下的swap



重载

函数模板重载其实和普通的函数重载一样

T Sum(T p1, T p2, T p3){
	T sum = p1+p2+p3;
	return sum;
}

与前面T Sum(T paratemer1, T paratemer2)重载

记得普通函数的重载条件

  1. 参数个数不同
  2. 参数类型不同
  3. 不同类型参数的顺序不同

本例是单类型模板的重载,那就去掉了第3种情况
而模板,本身就是服务于不同类型参数实现同一功能的函数,那第2点也就不需要考虑
所以这里也就只有第1点

而在多类型模板的重载中,就是1,3两点了

void swap(T1 &a, T2 &b);
void swap(T2 &a, T1 &b);





类模板

const int n = 10;
template <class T>
class Stack
{
	T stk[n];
	int top;  //栈顶	

	public:
	  Stack(){top = -1;}
	  void push(T ob);  //入栈
	  T pop();          //出栈
}

//类外定义成员函数
void Stack<T>::push(T ob){
	if(top == n-1){
		//栈满
		return ;
	}
	stk[++top] = ob;
}

T Stack<T>::pop(){
	if(top<0){
		//栈空
		return (0);
	}
	return stk[top--];
}

类模板的定义和函数模板的定义差不多,只是需要注意的细节多一些



类模板实例化

Stack<char> s1;
Stack<char> s2, *sp = &s2;

这不就和平常使用STL中vectorqueueunorder_map一样吗




类模板的其他语法规则

typedef string type;
template <class type>
class example{
	···
	type n;
}

全局类型名和局部类型名均是type,而类内的变量n的类型也是type
n根据“局部优先”规则,类型是在实例化过程中依据实参决定,而非是全局类型string



类型参数带缺省类型

template <class T1 = char, class T2 = int>
class example{
	T1 n;
	T2 m;
	···
}

对带有缺省值的类模板进行实例化过程中,通常有三种方式

  1. example<> e1
  2. example<double> e2,此处的类型double按从左到右的顺序进行实例化,T1double类型,T2是缺省的int类型
  3. example<int, bool> e3

其中需要注意的是,在定义带有缺省值的类模板时,只能从右到左开始缺省

template <class T1, class T2 = int>
template <class T1 = char, class T2>

前者正确,后者错误
上面三种方式中的第2点,类型参数实例化是从左往右进行的,如果定义类模板时,写成后者
结果就是,T1 = doubleT2没有实例化



函数模板没有参数的类型缺省

普通函数,有参数缺省值,但没有类型缺省值吧

int Sum(int a = 1, int b = 2)
{
	return a + b;
}





类模板组合

在类模板的定义中,内嵌自身或其他类模板的对象的定义

template <class U>
class A{
	A<U> *p;  //内嵌自身时,可以省去<U>
}

template <class T>
class B{
	A<U> a;   //不可省略<U>
}



类模板派生

熟悉类派生的话,这里就很简单了,
只需要在派生时,在基类后面加上基类的模板类型

template <class T>
class A{
	T t
}

template <class U>
class B:public A<T>   //派生时在基类后面加上基类的模板类型
{
	···
}




模板特化

特化,分为部分特化和全特化
看名字都能知道什么意思吧



函数模板特化


函数只有全特化
template <class T>
bool isEqual(T a, T b)
{
	if(a==b)
		return true;
	return false;
}

template<>
bool isEqual(char *a, char *b)
{
	if(strcmp(a,b)) 
		return true;
	return false;
}

int main(){
	char s1[] = "abc";
	char s2[] = "abd";
	cout<<isEqual(10,15)<<endl;    //  0
	cout<<isEqual(s1,s2)<<endl;    //  0
}
	



全特化template<>


如果全特化函数模板前的template<>模板声明去掉,就变成了普通函数。
C++对重载函数的匹配调用规则,普通函数最优,全特化函数模板次之,基础函数模板最后



类模板特化


全特化类模板,和全特化函数模板一样,必须用template<>声明

template<>
class A<char *>{
	···
}

部分特化类模板

template <class T1, class T2>
class A{
	T1 t1;
	T2 t2;
	···
}

template <class T>
class A<bool, T>{
	bool t1;
	T t2;
	···
}

类的调用匹配优先级
全特化类模板 > 偏特化类模板 > 基础类模板





操作符重载

关键字operate

class complex{
	double real;
	double imag;
	
  public:
	complex(double a = 0,double b = 0)
	{
		real = a;
		imag = b;
	}
	complex operate+(complex c){}	
}

//类外定义成员函数  complex:: 声明该函数是complex类的成员函数
complex complex::operate+(complex c)
{
	complex d;
	d.real = real + c.real;   //real 成员变量
	d.imag = imag + d.imag;   //imag 成员变量
	return d;
}

int main(){
	complex a(3,4),b(5,6),c;
	c = a + b;  // c = a.operate+(b);  所以二元运算符的重载,参数就是运算符后面的变量
}



一元运算符和二元运算符的重载有明显的差别。
因为一元运算符只有一个操作数,所以重载形式中不含参数
前置 ++ 的重载形式为 operate++()
后置 ++ 的重载形式为 operate++(int)




赋值号的重载

在用类的对象初始化另一个对象,可以定义时进行初始化,还可以直接使用=赋值
而其实这里就暗含了=的重载,一个对象的各种成员变量的值复制给另一个对象

通常来说并不需要我们自行重载=,但类的对象之间赋值,有深拷贝和浅拷贝之分
所以,是否需要重载=,得看情况

matrix.h: Simple matrix class dsexceptions.h: Simple exception classes Fig01_02.cpp: A simple recursive routine with a test program Fig01_03.cpp: An example of infinite recursion Fig01_04.cpp: Recursive routine to print numbers, with a test program Fig01_05.cpp: Simplest IntCell class, with a test program Fig01_06.cpp: IntCell class with a few extras, with a test program IntCell.h: IntCell class interface (Fig 1.7) IntCell.cpp: IntCell class implementation (Fig 1.8) TestIntCell.cpp: IntCell test program (Fig 1.9) (need to compile IntCell.cpp also) Fig01_10.cpp: Illustration of using the vector class Fig01_11.cpp: Dynamically allocating an IntCell object (lame) BuggyIntCell.cpp: Buggy IntCell class implementation (Figs 1.16 and 1.17) Fig01_18.cpp: IntCell class with pointers and Big Five FindMax.cpp: Function template FindMax (Figs 1.19 and 1.20) Fig01_21.cpp: MemoryCell class template without separation Fig01_25.cpp: Using function objects: Case insensitive string comparison LambdaExample.cpp: (Not in the book): rewriting Fig 1.25 with lambdas MaxSumTest.cpp: Various maximum subsequence sum algorithms Fig02_09.cpp: Test program for binary search Fig02_10.cpp: Euclid's algorithm, with a test program Fig02_11.cpp: Recursive exponentiation algorithm, with a test program RemoveEveryOtherItem.cpp: Remove every other item in a collection Vector.h: Vector class List.h: List class BinarySearchTree.h: Binary search tree TestBinarySearchTree.cpp: Test program for binary search tree AvlTree.h: AVL tree TestAvlTree.cpp: Test program for AVL trees mapDemo.cpp: Map demos WordLadder.cpp: Word Ladder Program and Word Changing Utilities SeparateChaining.h: Header file for separate chaining SeparateChaining.cpp: Implementation for separate chaining TestSeparateChaining.cpp: Test program for separate chaining hash tables (need to compile SeparateChaining.cpp also) QuadraticProbing.h: Header file for quadratic probing hash table QuadraticProbing.cpp: Implementation for quadratic probing hash table TestQuadraticProbing.cpp: Test program for quadratic probing hash tables (need to compile QuadraticProbing.cpp also) CuckooHashTable.h: Header file for cuckoo hash table CuckooHashTable.cpp: Implementation for cuckoo hash table TestCuckooHashTable.cpp: Test program for cuckoo hash tables (need to compile CuckooHashTable.cpp also) CaseInsensitiveHashTable.cpp: Case insensitive hash table from STL (Figure 5.23) BinaryHeap.h: Binary heap TestBinaryHeap.cpp: Test program for binary heaps LeftistHeap.h: Leftist heap TestLeftistHeap.cpp: Test program for leftist heaps BinomialQueue.h: Binomial queue TestBinomialQueue.cpp: Test program for binomial queues TestPQ.cpp: Priority Queue Demo Sort.h: A collection of sorting and selection routines TestSort.cpp: Test program for sorting and selection routines RadixSort.cpp: Radix sorts DisjSets.h: Header file for disjoint sets algorithms DisjSets.cpp: Efficient implementation of disjoint sets algorithm TestFastDisjSets.cpp: Test program for disjoint sets algorithm WordLadder.cpp: Word Ladder Program and Word Changing Utilities Fig10_38.cpp: Simple matrix multiplication algorithm with a test program Fig10_40.cpp: Algorithms to compute Fibonacci numbers Fig10_43.cpp: Inefficient recursive algorithm (see text) Fig10_45.cpp: Better algorithm to replace fig10_43.c (see text) Fig10_46.cpp: Dynamic programming algorithm for optimal chain matrix multiplication, with a test program Fig10_53.cpp: All-pairs algorithm, with a test program Random.h: Header file for random number class Random.cpp: Implementation for random number class TestRandom.cpp: Test program for random number class UniformRandom.h: Random number class using standard library Fig10_63.cpp: Randomized primality testing algorithm, with a test program SplayTree.h: Top-down splay tree TestSplayTree.cpp: Test program for splay trees RedBlackTree.h: Top-down red black tree TestRedBlackTree.cpp: Test program for red black trees Treap.h: Treap TestTreap.cpp: Test program for treap SuffixArray.cpp: Suffix array KdTree.cpp: Implementation and test program for k-d trees PairingHeap.h: Pairing heap TestPairingHeap.cpp: Test program for pairing heaps MemoryCell.h: MemoryCell class interface (Appendix) MemoryCell.cpp: MemoryCell class implementation (Appendix) MemoryCellExpand.cpp: MemoryCell instantiation file (Appendix) TestMemoryCell.cpp: MemoryCell test program (Appendix)
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值