list的介绍及使用
- list是可以在常数范围内在任意位置进行插入和删除的序列式容器,并且该容器可以前后双向迭代。
- list的底层是双向链表结构,双向链表中每个元素存储在互不相关的独立节点中,在节点中通过指针指向 其前一个元素和后一个元素。
- list与forward_list非常相似:最主要的不同在于forward_list是单链表,只能朝前迭代,已让其更简单高 效。
- 与其他的序列式容器相比(array,vector,deque),list通常在任意位置进行插入、移除元素的执行效率 更好。
- 与其他序列式容器相比,list和forward_list最大的缺陷是不支持任意位置的随机访问,比如:要访问list 的第6个元素,必须从已知的位置(比如头部或者尾部)迭代到该位置,在这段位置上迭代需要线性的时间 开销;list还需要一些额外的空间,以保存每个节点的相关联信息(对于存储类型较小元素的大list来说这 可能是一个重要的因素)
list的使用
list中的接口比较多,此处类似,只需要掌握如何正确的使用,然后再去深入研究背后的原理,已达到可扩展 的能力。以下为list中一些常见的重要接口
List 的迭代器
迭代器有两种实现方式,具体应根据容器底层数据结构实现:
-
原生态指针,比如:vector
-
将原生态指针进行封装,因迭代器使用形式与指针完全相同,因此在自定义的类中必须实现以下方法:
2.1 .指针可以解引用,迭代器的类中必须重载operator*() 2.2. 指针可以通过->访问其所指空间成员,迭代器类中必须重载oprator->() 2.3. 指针可以++向后移动,迭代器类中必须重载operator++()与operator++(int) 至于operator--()/operator--(int)释放需要重载,根据具体的结构来抉择,双向链表可以向前移动,所以需要重载,如果是forward_list就不需要重载- 2.4. 迭代器需要进行是否相等的比较,因此还需要重载operator==()与operator!=()
namespace bite
{
// list: 带头结点双向循环链表
template<class T>
struct ListNode
{
ListNode(const T& data = T())
: _pNext(nullptr)
, _pPre(nullptr)
, _data(data)
{ }
ListNode<T>* _pNext;
ListNode<T>* _pPre;
T _data;
};
// list迭代器:将节点类型的指针重新封装
template<class T>
struct list_iterator
{
typedef ListNode<T> Node;
typedef list_iterator<T> Self;
public:
list_iterator(Node* pCur)
: _pCur(pCur)
{}
// 2、按照指针的方式进行应用
T& operator*()
{
return _pCur->_data;
}
T* operator->()
{
return &(_pCur->_data);
}
// 3. 移动
Self& operator++()
{
_pCur = _pCur->_pNext;
return *this;
}
Self operator++(int)
{
Self temp(*this);
_pCur = _pCur->_pNext;
return temp;
}
Self& operator--()
{
_pCur = _pCur->_pPre;
return *this;
}
Self operator--(int)
{
Self temp(*this);
_pCur = _pCur->_pPre;
return temp;
}
// 4. 比较
bool operator!=(const Self& s)
{
return _pCur != s._pCur;
}
bool operator==(const Self& s)
{
return _pCur == s._pCur;
}
Node* _pCur;
};
template<class Iterator, class T>
struct list_reverse_iterator
{
typedef list_reverse_iterator<Iterator, T> Self;
public:
list_reverse_iterator(Iterator it)
: _it(it)
{}
T& operator*()
{
Iterator temp = _it;
--temp;
return *temp;
}
T* operator->()
{
return &(operator*());
}
Self& operator++()
{
--_it;//对于正向--
return *this;
}
Self operator++(int)
{
Self temp(*this);
_it--;
return temp;
}
Self& operator--()
{
++_it;
return *this;
}
Self operator--(int)
{
Self temp(*this);
_it++;
return temp;
}
bool operator!=(const Self& s)
{
return _it != s._it;
}
bool operator==(const Self& s)
{
return _it == s._it;
}
Iterator _it;//使用迭代器实例化
};
template<class T>
class list
{
typedef ListNode<T> Node;
public:
typedef list_iterator<T> iterator; //非原生态指针
typedef list_reverse_iterator<iterator, T> reverse_iterator;
public:
list()
{
CreateHead();
}
list(int n, const T& data)
{
CreateHead();
for (size_t i = 0; i < n; ++i)
push_back(data);
}
template<class Iterator>
list(Iterator first, Iterator last)
{
CreateHead();
while (first != last)
{
push_back(*first);
++first;
}
}
list(const list<T>& L)
{
CreateHead();
Node* pCur = L._pHead->_pNext;
while (pCur != L._pHead)
{
push_back(pCur->_data);
pCur = pCur->_pNext;
}
}
// L1 = L2;
list<T>& operator=(const list<T>& L)
{
if (this != &L)
{
clear(); // 清空当前元素的有效节点
Node* pCur = L._pHead->_pNext;
while (pCur != _pHead)
{
push_back(pCur->_data);
pCur = pCur->_pNext;
}
}
return *this;
}
~list()
{
clear();
delete _pHead;
}
public:
iterator begin()
{
return iterator(_pHead->_pNext);// 返回构造迭代器类型
}
iterator end()
{
return iterator(_pHead);
}
reverse_iterator rbegin()
{
return end();
}
reverse_iterator rend()
{
return begin();
}
/
// 容量
size_t size()const
{
size_t count = 0;
Node* pCur = _pHead->_pNext;
while (pCur != _pHead)
{
++count;
pCur = pCur->_pNext;
}
return count;
}
size_t empty()const
{
return _pHead->_pNext == _pHead;
}
void resize(size_t newsize, const T& data = T()) // const T&既可以接收const 也可以接收普通类型变量
{
size_t oldsize = size();
if (newsize > oldsize)
{
// 节点增多
for (size_t i = oldsize; i < newsize; ++i)
push_back(data);
}
else
{
// 节点减少
// oldsize:10 newsize:5
for (size_t i = newsize; i < oldsize; ++i)
pop_back();
}
}
///
// 元素访问
T& front()
{
return _pHead->_pNext->_data;
}
const T& front()const
{
return _pHead->_pNext->_data;
}
T& back()
{
return _pHead->_pPre->_data;
}
const T& back()const
{
return _pHead->_pPre->_data;
}
///
// modify
void push_back(const T& data)
{
insert(end(), data);
}
void pop_back()
{
erase(--end());
}
void push_front(const T& data)
{
insert(begin(), data);
}
void pop_front()
{
erase(begin());
}
iterator insert(iterator pos, const T& data)
{
Node* pNewNode = new Node(data);
Node* pCur = pos._pCur;
pNewNode->_pPre = pCur->_pPre;
pNewNode->_pNext = pCur;
pNewNode->_pPre->_pNext = pNewNode;
pCur->_pPre = pNewNode;
return iterator(pNewNode);
}
iterator erase(iterator pos)
{
Node* pDelNode = pos._pCur;
if (pDelNode == _pHead)
return end();
Node* pRet = pDelNode->_pNext;
pDelNode->_pPre->_pNext = pDelNode->_pNext;
pDelNode->_pNext->_pPre = pDelNode->_pPre;
delete pDelNode;
return iterator(pRet);
}
void clear()
{
Node* pCur = _pHead->_pNext;
// 头删法
// []-->1-->2-->3...
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->_pNext = _pHead;
_pHead->_pPre = _pHead;
}
protected:
Node* _pHead;
};
}
#include <vector>
void TestList1()
{
bite::list<int> L1;
bite::list<int> L2(10, 5);
vector<int> v{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
bite::list<int> L3(v.begin(), v.end());
bite::list<int> L4(L3);
auto it = L2.begin();
while (it != L2.end())
{
cout << *it << " ";
++it;
}
cout << endl;
for (auto e : L3)
cout << e << " ";
cout << endl;
auto rit = L4.rbegin();
while (rit != L4.rend())
{
cout << *rit << " ";
++rit;
}
cout << endl;
}
void TestList2()
{
bite::list<int> L;
L.push_back(1);
L.push_back(2);
L.push_back(3);
L.push_back(4);
cout << L.size() << endl;
cout << L.front() << endl;
cout << L.back() << endl;
L.push_front(0);
cout << L.size() << endl;
cout << L.front() << endl;
cout << L.back() << endl;
L.pop_front();
cout << L.size() << endl;
cout << L.front() << endl;
cout << L.back() << endl;
L.pop_back();
cout << L.size() << endl;
cout << L.front() << endl;
cout << L.back() << endl;
L.clear();
if (L.empty())
cout << "clear is OK" << endl;
}
void TestList3()
{
bite::list<int> L;
L.push_back(1);
L.push_back(2);
L.push_back(3);
L.resize(10, 5);
for (auto e : L)
cout << e << " ";
cout << endl;
L.resize(2);
for (auto e : L)
cout << e << " ";
cout << endl;
}
int main()
{
TestList1();
// TestList2();
//TestList3();
return 0;
}