[C++系列] 56. list深度剖析及模拟实现

1. std::list的核心框架接口的模拟实现bit::List

namespace bit
{
    // List的节点类
    template<class T>
    struct ListNode
    {
        ListNode(const T& val = T())
        : _pPre(nullptr)
        , _pNext(nullptr)
        , _val(val)
        {}
 
        ListNode<T>* _pPre;
        ListNode<T>* _pNext;
        T _val;
    };
 
    /*
    List 的迭代器
    迭代器有两种实现方式:
      1. 原生态指针,比如:vector
      2. 将原生态指针进行封装,因迭代器的使用形式与指针完全相同,因此,在自定义的类中必须实现以下方法:
         1. 指针可以解引用,迭代器的类中必须重载operator*()
         2. 指针可以通过->访问其所指空间成员,迭代器类中必须重载oprator->()
         3. 指针可以++向后移动,迭代器类中必须重载operator++()与operator++(int)至于
            operator--()/operator--(int)释放需要重载,根据具体的结构来抉择,双向链表可以向前移动,
            所以需要重载,如果是forward_list就不需要重载--
         4. 迭代器需要进行是否相等的比较,因此还需要重载operator==()与operator!=()
    */
    template<class T, class Ref, class Ptr>
    class ListIterator
    {
        typedef ListNode<T>* PNode;		// 节点的指针
        typedef ListIterator<T, Ref, Ptr> Self;		// 自身的类型称为Self
    public:
        ListIterator(PNode pNode = nullptr)
            : _pNode(pNode)
        {}
          ListIterator(const Self& l)
            : _pNode(l._pNode)
        {}
 
        T& operator*()
        {
            return _pNode->_val;
        }
 
        T* operator->()
        {
            return &(operator*());
        }
 
        Self& operator++()
        {
            _pNode = _pNode->_pNext;
            return *this;
        }
        
        Self operator++(int)
        {
            Self temp(*this);
            _pNode = _pNode->_pNext;
            return temp;
        }
 
        bool operator!=(const Self& l)
        {
            return _pNode != l._pNode;
        }
 
        bool operator==(const Self& l)
        {
            return _pNode != l._pNode;
        }
 
        PNode _pNode;
    };
    
    /*
    List 的反向迭代器,反向迭代器与正向迭代器刚好是相反的,反向迭代器++,迭代器往前移动,反向迭代
器--,     迭代器往后移动,因此反向迭代器可以在正向迭代器的基础之上来实现
    */
    template<class T, class Ref, class Ptr, class Iterator>
    class ListReverseIterator
    {
        typedef ListReverseIterator<T, Ref, Ptr, Iterator> Self;
    public:
        ListReverseIterator(const Iterator& it)
            : _it(it)

        {}
        ListReverseIterator(const Self& s)
            : _it(s._it)
        {}
 
        Ref operator*()
        {
            Iterator temp = _it;
            return *(--temp);
        }
 
        Ptr operator->()
        {
            return &operator*();
        }
 
        // 反向迭代器的++,就是正向迭代器的--
        Self& operator++()
        {
            --_it;
            return *this;
        }
 
        Self operator++(int)
        {
            Iterator temp(_it);
            --_it;
            return temp;
        }
 
        // 反向迭代器的--,就是正向迭代器的++
        Self& operator--()
        {
            ++_it;
            return *this;
        }
 
        Self operator--(int)
        {
            Iterator temp(_it);
            ++_it;
            return temp;
        }
 
        bool operator!=(const Self& s)
        {
            return _it != s._it;
        }
 
        bool operator==(const Self& s)
        {
            return _it == s._it;

        }
        private:
        Iterator _it;
    };
 
    template<class T>
    class List
    {
        typedef ListNode<T> Node;
        typedef Node* PNode;
 
    public:
        typedef ListIterator<T, T&, T*> Iterator;
        typedef ListIterator<T, const T&, const T&> ConstIterator;
        typedef ListReverseIterator<T, T&, T*, Iterator> ReverseIterator;
        typedef ListReverseIterator<T, const T&, const T*, ConstIterator> ConstReverseIterator;
    public:
        ///
        // List的构造
        List()
        {
            CreateHead();
        }
 
        List(int n, const T& value = T())
        {
            CreateHead();
            for (int i = 0; i < n; ++i)
                PushBack(value);
        }
 
        template <class Iterator>
        List(Iterator first, Iterator last)
        {
            CreateHead();
            while (first != last)
            {
                PushBack(*first);
                ++first;
            }
        }
 
        List(const List<T>& l)
        {
            CreateHead();
 
            // 用l中的元素构造临时的temp,然后与当前对象交换
            List<T> temp(l.CBegin(), l.CEnd());
            this->Swap(temp);
        }
 

        List<T>& operator=(const List<T>& l)
         {
            if (this != &l)
            {
                List<T> temp(l);
                this->Swap(temp);
            }
 
            return *this;
        }
 
        ~List()
        {
            Clear();
            delete _pHead;
            _pHead = nullptr;
        }
 
        ///
        // List Iterator
        Iterator Begin()
        {
            return Iterator(_pHead->_pNext);
        }
 
        Iterator End()
        {
            return Iterator(_pHead);
        }
 
        ReverseIterator RBegin()
        {
            return ReverseIterator(End());
        }
 
        ReverseIterator REnd()
        {
            return ReverseIterator(Begin());
        }
 
        ConstIterator CBegin()const
        {
            return ConstIterator(_pHead->_pNext);
        }
 
        ConstIterator CEnd()const
        {
            return ConstIterator(_pHead);
        }
 
        ConstReverseIterator CRBegin()const
        {
            return ConstReverseIterator(CEnd());

        }
        ConstReverseIterator CREnd()const
        {
            return ConstReverseIterator(CBegin());
        }
        ///
        // List Capacity
        size_t Size()const
        {
            size_t count = 0;
            PNode pCur = _pHead->_pNext;
            while (pCur != _pHead)
            {
                ++count;
                pCur = pCur->_pNext;
            }
 
            return count;
        }
 
        bool Empty()const
        {
            return _pHead->_pNext == _pHead;
        }
 
        void ReSize(size_t newSize, const T& val = T())
        {
            size_t oldSize = Size();
            if (oldSize <= newSize)
            {
                for (size_t i = oldSize; i < newSize; ++i)
                    PushBack(val);
            }
            else
            {
                for (size_t i = newSize; i < oldSize; ++i)
                    PopBack();
            }
        }
 
        
        // List Access
        T& Front()
        {
            return _pHead->_pNext->_val;
        }
 
        const T& Front()const
        {
            return _pHead->_pNext->_val;
        }
 

        T& Back()
        {
            return _pHead->_pPre->_val;
        }
 
        const T& Back()const
        {
            return _pHead->_pPre->_val;
        }
        
        // List Modify
        void PushBack(const T& val)
        {
            PNode pNewNode = new Node(val);
 
            // 先把新节点尾插进去
            pNewNode->_pNext = _pHead;
            pNewNode->_pPre = _pHead->_pPre;
            // 再链接剩余两个指针
            _pHead->_pPre = pNewNode;
            pNewNode->_pPre->_pNext = pNewNode;
        }
 
        // 尾删
        void PopBack()
        {
            // 找到待删除节点
            PNode pDel = _pHead->_pPre;
            if (pDel != _pHead)
            {
                _pHead->_pPre = pDel->_pPre;
                pDel->_pPre->_pNext = _pHead;
                delete pDel;
            }
        }
 
        // 头插
        void PushFront(const T& val)
        {
            PNode pNewNode = new Node(val);
 
            // 先把新节点尾插进去
            pNewNode->_pNext = _pHead->_pNext;
            pNewNode->_pPre = _pHead;
            // 再链接剩余两个指针
            _pHead->_pNext = pNewNode;
            pNewNode->_pNext->_pPre = pNewNode;
        }
 
        // 头删
        void PopFront()
        {
            // 找到待删除节点

            PNode pDel = _pHead->_pNext;
              if (pDel != _pHead)
            {
                _pHead->_pNext = pDel->_pNext;
                pDel->_pNext->_pPre = _pHead;
                delete pDel;
            }
        }
 
        // 在pos位置前插入值为val的节点
        Iterator Insert(Iterator pos, const T& val)
        {
            PNode pNewNode = new Node(val);
            PNode pCur = pos._pNode;
            // 先将新节点插入
            pNewNode->_pPre = pCur->_pPre;
            pNewNode->_pNext = pCur;
            pNewNode->_pPre->_pNext = pNewNode;
            pCur->_pPre = pNewNode;
            return Iterator(pNewNode);
        }
 
        // 删除pos位置的节点,返回该节点的下一个位置
        Iterator Erase(Iterator pos)
        {
            // 找到待删除的节点
            PNode pDel = pos._pNode;
            PNode pRet = pDel->_pNext;
 
            // 将该节点从链表中拆下来并删除
            pDel->_pPre->_pNext = pDel->_pNext;
            pDel->_pNext->_pPre = pDel->_pPre;
            delete pDel;
 
            return Iterator(pRet);
        }
 
        void Clear()
        {
            PNode pCur = _pHead->_pNext;
            while (pCur != _pHead)
            {
                _pHead->_pNext = pCur->_pNext;
                delete pCur;
                pCur = _pHead->_pNext;
            }
 
            _pHead->_pNext = _pHead;
            _pHead->_pPre = _pHead;
        }
 
        void Swap(List<T>& l)
        {
            swap(_pHead, l._pHead);
        }
 
    private:
        void CreateHead()
        {
            _pHead = new Node;
            _pHead->_pPre = _pHead;
            _pHead->_pNext = _pHead;
        }
    private:
        PNode _pHead;
    };
}

2. 对模拟的bit::List进行测试

// 正向打印链表
template<class T>
void PrintList(bit::List<T>& l)
{
    auto it = l.Begin();
    while (it != l.End())
    {
        cout << *it << " ";
        ++it;
    }
 
    cout << endl;
}
 
// 反向打印链表
template<class T>
void PrintListReverse(const bit::List<T>& l)
{
    auto it = l.CRBegin();
    while (it != l.CREnd())
    {
        cout << *it << " ";
        ++it;
    }
 
    cout << endl;
}
 
// 测试List的构造
void TestList1()
{
    bit::List<int> l1;
    bit::List<int> l2(10, 5);
    PrintList(l2);
 
    int array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
    bit::List<int> l3(array, array+sizeof(array)/sizeof(array[0]));
        PrintList(l3);
 
    bit::List<int> l4(l3);
    PrintList(l4);
 
    l1 = l4;
    PrintList(l1);
    PrintListReverse(l1);
}
 
// PushBack()/PopBack()/PushFront()/PopFront()
void TestList2()
{
    // 测试PushBack与PopBack
    bit::List<int> l;
    l.PushBack(1);
    l.PushBack(2);
    l.PushBack(3);
    PrintList(l);
 
    l.PopBack();
    l.PopBack();
    PrintList(l);
 
    l.PopBack();
    cout << l.Size() << endl;
 
    // 测试PushFront与PopFront
    l.PushFront(1);
    l.PushFront(2);
    l.PushFront(3);
    PrintList(l);
 
    l.PopFront();
    l.PopFront();
    PrintList(l);
 
    l.PopFront();
    cout << l.Size() << endl;
}
 
void TestList3()
{
    int array[] = { 1, 2, 3, 4, 5 };
    bit::List<int> l(array, array+sizeof(array)/sizeof(array[0]));
 
    auto pos = l.Begin();
    l.Insert(l.Begin(), 0);
    PrintList(l);
    
    ++pos;
    l.Insert(pos, 2);

    PrintList(l);
      l.Erase(l.Begin());
    l.Erase(pos);
    PrintList(l);
 
    // pos指向的节点已经被删除,pos迭代器失效
    cout << *pos << endl;
 
    auto it = l.Begin();
    while (it != l.End())
    {
        it = l.Erase(it);
    }
    cout << l.Size() << endl;
}
 
// ReSize/Clear/Swap
void TestList4()
{
    int array[] = { 1, 2, 3, 4, 5 };
    bit::List<int> l1(array, array + sizeof(array) / sizeof(array[0]));
    cout << l1.Size() << endl;
    PrintList(l1);
 
    l1.ReSize(10, 6);
    cout << l1.Size() << endl;
    PrintList(l1);
 
    l1.ReSize(4);
    cout << l1.Size() << endl;
    PrintList(l1);
 
    bit::List<int> l2(array, array + sizeof(array) / sizeof(array[0]));
    PrintList(l1);
    PrintList(l2);
 
    l1.Swap(l2);
    PrintList(l1);
    PrintList(l2);
 
    l2.Clear();
    cout << l2.Size() << endl;
}

上述的模拟实现较有难度,有STL中list底层实现的风格在其中,但相较于难懂的STL内核来讲还算简单易懂,实现的也比较完整,有实践参考价值。

2. 通过内部类模拟实现list

#pragma once

namespace yl {
template<class T>	// ListNode 是一个模板类
class ListNode {
public:
	T m_val;
	ListNode * m_prev;
	ListNode * m_next;

	// 构造函数传入val
	ListNode(const T &val = T()) :
		m_prev(nullptr),
		m_next(nullptr),
		m_val(val)
	{

	}
};

//size empty swap front back operator=
template<class T>
class list
{
	ListNode<T> * m_head;	// 注意ListNode为一个模板类,且为指针

	void createHead()
	{
		m_head = new ListNode<T>;
		m_head->m_next = m_head->m_prev = m_head;	// 单节点循环
	}

public:
	// 内部类可使用外部类的一切数据资源
	// 外部类属于内部类的友元
	// iterator应该是任意节点的地址
	class iterator
	{
	public:
		ListNode<T> * m_pos;
		// 拷贝构造不需要写出
		iterator(ListNode<T> * val = nullptr) :
			m_pos(val)
		{

		}

		// 解引用运算符可以做左值,返回T引用 T & 
		T & operator*() const
		{
			return m_pos->m_val;
		}

		// 返回T * 是它的地址,为一个指针
		T * operator->() const
		{
			return &m_pos->m_val;
		}

		// 返回值为iterator,++()为前置++
		iterator operator++()
		{
			m_pos = m_pos->m_next;
			return *this;
		}

		// 返回值为iterator,++()为后置++
		iterator operator++(int)
		{
			iterator tmp = *this;	
			m_pos = m_pos->m_next;
			return tmp;
		}

		iterator operator--()
		{
			m_pos = m_pos->m_prev;
			return *this;
		}

		iterator operator--(int)
		{
			iterator tmp = *this;
			m_pos = m_pos->m_prev;
			return tmp;
		}

		// bool 类型
		bool operator==(const iterator & ci) const
		{
			return m_pos == ci.m_pos;
		}

		bool operator!=(const iterator & ci) const
		{
			return m_pos != ci.m_pos;
		}
	};

	// list无参构造
	list()
	{
		createHead();
	}

	// n个val的构造
	list(int n, const T &val = T())
	{
		createHead();

		int i;
		for (i = 0; i < n; i++)
		{
			push_back(val);
		}
	}

	list(iterator start, iterator finish)
	{
		createHead();

		insert(end(), start, finish);
	}

	list(T * start, T * finish)
	{
		createHead();

		insert(end(), start, finish);
	}

	// 拷贝构造函数
	list(list<T> & l)
	{
		createHead();

		insert(end(), l.begin(), l.end());
	}

	~list()
	{
		erase(begin(), end());
		delete m_head;
	}

	void clear()
	{
		erase(begin(), end());
	}

	// 尾插
	void push_back(const T &val)
	{
		insert(end(), val);
	}

	// 头插
	void push_front(const T &val)
	{
		insert(begin(), val);
	}

	void pop_back()
	{
		erase(--end());
	}

	void pop_front()
	{
		erase(begin());
	}

	iterator insert(iterator pos, const T &val)
	{
		ListNode<T> * cur = new ListNode < T >;
		ListNode<T> * npos = pos.m_pos;

		cur->m_val = val;

		cur->m_prev = npos->m_prev;
		cur->m_prev->m_next = cur;

		cur->m_next = npos;
		npos->m_prev = cur;

		return cur;
	}

	// 传入iterator为链表, T * 将其认为数组
	iterator insert(iterator pos, T * start, T * finish)
	{
		T * tmp;
		iterator tmpit = --pos;		// tmpit为pos前一个位置
		pos++;		// 保持pos位置不变

		for (tmp = start; tmp != finish; tmp++)
		{
			insert(pos, *tmp);
		}

		return ++tmpit;		// tmpit在插入的begin位置,即pos位置
	}

	// 两个链表进行的插入
	iterator insert(iterator pos, iterator start, iterator end)
	{
		iterator tmp;
		iterator tmpit = --pos;
		pos++;

		for (tmp = start; tmp != end; tmp++)
		{
			insert(pos, *tmp);
		}

		return ++tmpit;
	}

	// 删除单个节点
	iterator erase(iterator pos)
	{
		ListNode<T> * npos = pos.m_pos;
		ListNode<T> * res = npos->m_next;

		npos->m_next->m_prev = npos->m_prev;
		npos->m_prev->m_next = npos->m_next;
		delete npos;

		return res;
	}

	// 删除区间内的所有节点
	iterator erase(iterator start, iterator finish)
	{
		iterator i = start;

		while (i != finish)
		{
			i = erase(i);
		}

		return finish;
	}

	iterator begin()
	{
		return m_head->m_next;
	}

	iterator end()
	{
		return m_head;
	}
};

};

你可能感兴趣的:([C++系列],C++,list,STL)