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

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;
}

结果显示:
这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值