您的位置:首页 > 其它

【STL】 list的应用及模拟实现

2016-12-04 18:17 585 查看
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[/b] ( 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;
}


结果显示:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: