1.容器
容器是特定类型的对象的集合,也就是为了保存一组对象而设计的类。
容器一般提供插入、删除、查找以及访问容器中的所有对象等功能。
用户不必关心容器中的对象是如何保存的。用户只需要使用容器提供的插入操作将对象放入容器,用删除操作将对象从容器中删除。
容器只关心对象之间的关系,不关心对象本身的类型。容器可以存放各种同类型的对象(如存放一组整型对象、实型对象,也可以存放用户自定义类型的对象)。通常来说容器都会被设计成一个类。
数组是容器的一种实现,链表也是容器的一种实现。
2.迭代器
当要访问容器中的某一对象时,必须要有一种方式标识该对象。如果用一个数组保存对象,则可用数组的下标标识正在访问的元素,也可以用指向数组元素的指针来表示。当用链表保存对象时,可以用一个指向某一节点的指针来标识链表中的某一个元素。但容器是抽象的,它保存对象的方法对用户是保密的,因而用户无法指导该如何标识容器中的某一对象。
通常为每种容器定义一个相应的表示其中对象位置的类型,称为迭代器。迭代器对象相当于是指向容器中对象的指针。有了迭代器可以进一步隐藏数据的存储方式。
把迭代器看出是一种抽象的指针。迭代器的常用操作和指针类似,包括赋值、比较、移动到下一个对象或上一个对象、取出指向的对象值。
迭代器一般作为相应类的友元类或内嵌类
迭代器类的对象定义:
容器类名::迭代器类名 迭代器对象名;
template <class T>
class seqlist
{
private:
int size; //数组规模
int current_size; //容器中对象个数
T *storage; //数组的起始地址
void doubleSpace(); //将数组容量扩大一倍
public:
seqlist(int s = 10):size(s)
{
storage = new T[size]; current_size = 0;
}
~seqlist() {delete [] storage;}
void push_back(const T &x) //在容器尾部添加对象
{
if (size == current_size)
doubleSpace();
storage[current_size++] = x;
}
void pop_back( ) //删除容器尾部的对象
{
if (current_size == 0)
cout<< "这是一个空容器\n";
else
cout<<current_size;
}
T &operator[](int i) { return storage[i]; } //下标运算符重载
class Itr //内嵌的迭代器类定义
{
T *pos; //指向容器中的某一对象
public:
Itr(T *obj = NULL) {pos = obj;}
Itr &operator++() { ++pos; return *this;} //指向容器中的下一个对象
T &operator*() { return *pos;} //取出迭代器指向的对象的值
bool operator!=(const Itr &p) //比较两个迭代器对象是否相同
{return pos != p.pos;}
friend class seqlist<T>;
};
Itr begin() {return Itr(storage);} //返回指向第一个对象的迭代器
Itr end() { return Itr(storage + current_size);} //返回指向最后一个对象的迭代器
void insert(Itr &p, const T &x) ; //在迭代器指定的位置上插入对象
void erase(const Itr &p); //删除迭代器指定的位置上的对象
};
//函数实现doubleSpace
template <class T>
void seqlist<T>::doubleSpace()
{
T *tmp = storage;
size *= 2;
storage = new T[size];
for (int i = 0; i < current_size; ++i)
storage[i] = tmp[i];
delete [] tmp;
}
//函数实现insert
template <class T>
void seqlist<T>::insert( Itr &p, const T &x)
{
T *q;
if(size == current_size)
{
int offset = p.pos - storage;
doubleSpace();
p.pos = storage + offset;
}
q = storage + current_size;
//插入对象p在q之前(q表示容器中最后一个对象位置),需要把插入对象p之后的元素向后移动腾出位置
while (q > p.pos) { *q = *(q-1); --q;}
*p.pos = x;
++current_size; //插入元素后,数组长度+1
}
//函数实现erase
template <class T>
void seqlist<T>::erase(const Itr &p)
{
T *q =p.pos ;
--current_size;
while (q < storage + current_size)
{ *q = *(q+1); ++q;}
}
应用
int main()
{
seqlist<int> sq(10); //容器类对象
seqlist<int>::Itr itr1; //容器内嵌类--迭代器类对象定义
for (int i = 0; i < 10; ++i)
sq.push_back(2 * i + 1);
cout << "用下标运算符输出:\n";
for (i = 0; i < 10; ++i)
cout << sq[i] << '\t';
cout << "用迭代器输出:\n";
for (itr1 = sq.begin() ; itr1 != sq.end(); ++itr1)
cout << *itr1 << '\t';
// 插入0,2,4,6,8,10,12,14,16,18
for (itr1 = sq.begin(), i = 0 ; i < 20;
++itr1, ++itr1, i += 2)
sq.insert(itr1, i);
cout << "插入0,2,4,6,8,10,12,14,16,18:\n";
for (itr1 = sq.begin() ; itr1 != sq.end(); ++itr1)
cout << *itr1 << '\t';
//删除0,2,4,6,8,10,12,14,16,18
for (itr1 = sq.begin(); itr1 != sq.end(); ++itr1)
sq.erase(itr1);
cout << "删除0,2,4,6,8,10,12,14,16,18:\n";
for (itr1 = sq.begin() ; itr1 != sq.end(); ++itr1)
cout << *itr1 << '\t';
return 0;
}