1.STL
C++标准容器库,是惠普实验室开发的一系列软件的统称。它一共有六大组件:容器、迭代器、算法、适配器、空间适配器、仿函数。
序列式容器中有一个列表(list), 由节点组成的双向链表,每个结点包含着一个元素
2.list的应用及其模拟实现
(1)迭代器
标准库中的list是一个用模板实现的双向的循环链表,它其中包括了一些迭代器,用来访问容器。如下所示:
在用的过程当中,我们可以把迭代器看成是一个指针,事实上,C++的指针也是一种迭代器。但是,迭代器不仅仅是指针,因此你不能认为他们一定具有地址值。
因为标准库中是带一个头结点,所以begin()返回的是头结点的下一个结点,而end()返回的是尾结点的下一个结点,即头结点。而rbegin()和rend()是逆序访问list。
下面通过范例来理解一下:
// list::begin
#include <iostream>
#include <list>
using namespace std;
int main ()
{
int myints[] = {75,23,65,42,13};
list<int> mylist (myints,myints+5);
list<int>::iterator it;
cout << "mylist contains:";
for ( it=mylist.begin() ; it != mylist.end(); it++ )
cout << " " << *it;
cout << endl;
return 0;
}
结果显示:mylist contains: 75 23 65 42 13
// list::rbegin/rend
#include <iostream>
#include <list>
using namespace std;
int main ()
{
list<int> mylist;
for (int i=1; i<=5; i++) mylist.push_back(i);
cout << "mylist contains:";
list<int>::reverse_iterator rit;
for ( rit=mylist.rbegin() ; rit != mylist.rend(); ++rit )
cout << " " << *rit;
cout << endl;
return 0;
}
结果显示:mylist contains: 5 4 3 2 1
(2)成员函数
assign()是赋值操作,其函数原型为下:
void assign ( InputIterator first, InputIterator last );//参数为两个迭代器,用这两个迭代器补充内容
void assign ( size_type n, const T& u );//用n个u来填充
看如下测试范例,后面函数模拟实现中不做详细介绍:
// list::assign
#include <iostream>
#include <list>
using namespace std;
int main ()
{
list<int> first;
list<int> second;
first.assign (7,100); // 7 ints with value 100
second.assign (first.begin(),first.end()); // a copy of first
int myints[]={1776,7,4};
first.assign (myints,myints+3); // assigning from array
cout << "Size of first: " << int (first.size()) << endl;
cout << "Size of second: " << int (second.size()) << endl;
return 0;
}
输出结果:
Size of first: 3
Size of second: 7
push_front是在头部插入元素,其函数原型:void push_front ( const T& x );
pop_front头部删除,函数原型:void pop_front ( );
push_back,尾插,和头插类似
pop_back尾删
insert 插入操作,其函数原型如下:
iterator insert ( iterator position, const T& x ); //在position前面插入x
void insert ( iterator position, size_type n, const T& x ); //在position前面插入n个x
void insert ( iterator position, InputIterator first, InputIterator last );//从position前面插入从first到 last之间的内容
在后面的函数模拟实现中会将第三个insert简单的实现
erase删除操作,其函数原型如下:
iterator erase ( iterator position );//删除指定位置的元素且返回其后位置的迭代器
iterator erase ( iterator first, iterator last );//删除[first,last)区间的内容且返回last位置的迭代器
swap和容器适配器相关,暂且不讨论
clear,删除链表中的全部结点,函数原型:void clear ( );
3.list简单模拟实现:
//list.h
#include<iostream>
using namespace std;
#include<assert.h>
template<class T>
struct __ListNode
{
__ListNode<T>* _next;
__ListNode<T>* _prev;
T _data;
__ListNode(const T& x)
:_data(x)
, _next(NULL)
, _prev(NULL)
{}
};
//T T& T*
template < class T, class Ref, class Ptr >
struct __ListIterator
{
typedef __ListNode<T> Node;
typedef __ListIterator<T, Ref, Ptr> Self;
Node* _node;
__ListIterator(){}
__ListIterator(Node* node)
:_node(node)
{}
/**************操作数重载****************/
bool operator!=(const Self& s)
{
return _node != s._node;
}
Ref operator*()
{
return _node->_data;
}
Ptr operator->()
{
return &_node->_data;
}
Self& operator++()//前置++
{
_node = _node->_next;
return *this;
}
Self operator++(int)//后置++
{
Self tmp(*this);
_node = _node->_next;
return tmp;
}
Self& operator--()
{
_node = _node->_prev;
return *this;
}
Self operator--(int)
{
Self tmp(*this);
_node = _node->_prev;
return tmp;
}
};
template<class T>
class List
{
typedef __ListNode<T> Node;
public:
typedef __ListIterator<T, T&, T*> Iterator;
Node* BuyNode(const T& x)
{
return new Node(x);
}
List()
:_head(BuyNode(T()))
{
_head->_next = _head;
_head->_prev = _head;
}
/*************接口函数实现****************/
template<class InputIterator>
void Insert(Iterator pos, InputIterator first, InputIterator last)
{
while (first != last)
{
Insert(pos, *first);
++first;
}
}
void Insert(Iterator itpos, const T& x)//插入
{
assert(itpos._node);
Node* cur = itpos._node;
Node* prev = cur->_prev;
Node* tmp = new Node(x);
prev->_next = tmp;
tmp->_prev = prev;
tmp->_next = cur;
cur->_prev = tmp;
}
Iterator Erase(Iterator itpos)//删除
{
assert(itpos._node&&itpos._node != _head);
Node* prev = itpos._node->_prev;
Node* next = itpos._node->_next;
prev->_next = next;
next->_prev = prev;
delete itpos._node;
return next; //返回删除元素的下一个元素的迭代器
}
void PushFront(const T& x)//头插
{
Insert(Begin(), x);
}
void PopFront()//头删
{
Erase(Begin());
}
void PushBack(const T& x)//尾插
{
Insert(End(),x);
}
void PopBack()//尾删
{
Erase(--End());
}
/******************访问****************/
Iterator Begin()
{
return Iterator(_head->_next);
}
Iterator End()
{
return Iterator(_head);
}
protected:
Node* _head;
};
void PrintList(List<int> l)//输出函数,此处非list中的函数,为了方便,将打印输出封装成一个函数
{
List<int>::Iterator itpos = l.Begin();
while (itpos != l.End())
{
cout << *itpos << " ";
++itpos;
}
cout << endl;
}
测试部分:
//list.cpp
#include"list.h"
#include<iostream>
using namespace std;
void TestList()
{
List<int> l1;
l1.PushBack(1);
l1.PushBack(2);
l1.PushBack(3);
l1.PushBack(4);
PrintList(l1);
List<int> l2;
l2.PushBack(100);
l2.PushBack(200);
l2.PushBack(300);
l2.PushBack(400);
List<int>::Iterator itpos = l1.Begin();//如果直接向容器中插入元素,迭代器可能失效,所以此处需要重新赋值
l2.Insert(itpos, l2.Begin(), l2.End());
PrintList(l1);
l1.PopBack();
PrintList(l1);
l1.PushFront(16);
l1.PushFront(17);
PrintList(l1);
l1.PopFront();
PrintList(l1);
}
int main()
{
TestList();
system("pause");
return 0;
}
结果显示: