简单介绍list
上文我们讲到了STL库中的vector的使用和模拟实现,其实list和vector在很多地方都有相似之处。STL库中的list是一个双向循环链表。它的简单的结构如图
我们还是先来看看它里面有什么。
list的内容与使用
一.
首先还是雷打不动的三个成员函数,构造函数,析构函数和赋值运算符重载。
二.
其次是迭代器。这里需要注意一下的是,begin()返回的是第一个元素的位置,也就是头节点head的下一个位置;end()返回的是最后一个元素的下一个位置,也就是头节点head的位置。在这里我们讲一下迭代器失效的问题。
int main()
{
int a[] = { 1,2,3,4 };
list<int> mylist(a,a+4);
list<int>::iterator it = mylist.begin();
while (it != mylist.end())
{
if (*it % 2 == 0)
{
mylist.erase(it);
}
else
{
++it;
}
}
return 0;
}
上面的代码程序会崩溃,因为在STL里,我们不能以指针来看待迭代器,指针是与内存绑定的,而迭代器是与容器里的元素绑定的,删除了之后,该迭代器就失效了,在对其重新赋值之前,不能再访问此迭代器。
int main()
{
int a[] = { 1,2,3,4 };
list<int> mylist(a,a+4);
list<int>::iterator it = mylist.begin();
while (it != mylist.end())
{
if (*it % 2 == 0)
{
it= mylist.erase(it);
}
else
{
++it;
}
}
}
这样就不会崩溃了,用it重新接收一下erase的返回值,因为erase的返回值是删除节点的下一个节点。
rbegin()与rend()是逆序访问链表的意思,和vector的用法差不多。
三.
上面的用法与vector的也差不多,就不一一介绍了。
四.
front():返回第一个节点的数据;
back():返回最后一个节点的数据;
五.
这些操作中,只比vector多了两个操作函数。
push_front():头插。
pop_front():头删。
这两个函数非常的简单,就不举例一一测试了。
insert函数有两种参数的用法;
int main()
{
int a[] = { 1,2,3,4 };
list<int> mylist(a,a+4);
mylist.insert(mylist.begin(), 0);//在首元素的前面插入一个0
mylist.insert(mylist.end(), 3, 5);//在尾元素的后面插入三个5
list<int>::iterator it;
for (it = mylist.begin(); it != mylist.end(); ++it)
{
cout << *it << " ";
}
cout << endl;
system("pause");
return 0;
}
六.
这是list中容器适配器的内容,我们来仔细看一下。
splice():往一个list1的某一个位置插入list2的内容。
int main()
{
list<int> mylist1, mylist2;
for (size_t i = 1; i <= 3; ++i)
{
mylist1.push_back(i); //mylist1: 1 2 3
mylist2.push_back(i * 10);// mylist2: 10 20 30
}
list<int>::iterator it;
it = mylist1.begin();
++it;//"it" points 2 now
mylist1.splice(it, mylist2);//mylist1: 1 10 20 30 2 3
//mylist2(empty)
//"it" still points to 2
mylist2.splice(mylist2.begin(), mylist1, it);//mylist1: 1 10 20 30 3
//mylist2: 2
//"it" now is invalid
it = mylist1.begin();
advance(it, 3);//"it" points to 30
mylist1.splice(mylist1.begin(), mylist1, it, mylist1.end());
//mylist1: 30 3 1 10 20
for (it = mylist1.begin(); it != mylist1.end(); ++it)
{
cout << *it << " ";
}
cout << endl;
for (it = mylist2.begin(); it != mylist2.end(); ++it)
{
cout << *it << " ";
}
cout << endl;
system("pause");
return 0;
}
remove():找出value然后删除;
int main()
{
int a[] = { 1, 2, 3, 4 };
list<int> mylist(a,a+4);
list<int>::iterator it;
mylist.remove(1);
for (it = mylist.begin(); it != mylist.end(); ++it)
{
cout << *it << " ";
}
cout << endl;
system("pause");
return 0;
}
remove_if():条件删除,把不符合条件的删除;
bool check(const int& value)//判断是否小于4
{
return(value < 4);
}
int main()
{
int a[] = { 1, 2, 3, 4 };
list<int> mylist(a,a+4);
list<int>::iterator it;
mylist.remove_if(check);
for (it = mylist.begin(); it != mylist.end(); ++it)
{
cout << *it << " ";
}
cout << endl;
system("pause");
return 0;
}
unique():去掉重复的数值(需要注意的是,unique是有序的条件下去重,使用之前最好先排序)
int main()
{
int a[] = { 1, 2, 4, 4 };
list<int> mylist(a,a+4);
list<int>::iterator it;
mylist.unique();
for (it = mylist.begin(); it != mylist.end(); ++it)
{
cout << *it << " ";
}
cout << endl;
system("pause");
return 0;
}
sort():排序
int main()
{
int a[] = { 1, 4 ,2, 3 };
list<int> mylist(a,a+4);
list<int>::iterator it;
mylist.sort();
for (it = mylist.begin(); it != mylist.end(); ++it)
{
cout << *it << " ";
}
cout << endl;
system("pause");
return 0;
}
reverse():逆序
int main()
{
int a[] = { 1, 4 ,2, 3 };
list<int> mylist(a,a+4);
list<int>::iterator it;
mylist.reverse();
for (it = mylist.begin(); it != mylist.end(); ++it)
{
cout << *it << " ";
}
cout << endl;
system("pause");
return 0;
}
merge():合并有序的链表。
int main()
{
int a[] = { 1, 2 ,3, 4 };
int b[] = { 5, 6, 7, 8 ,9};
list<int> mylist1(a,a+4);
list<int> mylist2(b, b + 5);
list<int>::iterator it;
mylist1.merge(mylist2);
for (it = mylist1.begin(); it != mylist1.end(); ++it)
{
cout << *it << " ";
}
cout << endl;
system("pause");
return 0;
}
模拟实现list
#pramga once
#include <iostream>
using namespace std;
#include <assert.h>
//链表节点的结构
template <class T>
struct ListNode
{
T _data;
ListNode<T>* _prev;
ListNode<T>* _next;
ListNode(const T& data)//给一个const T类型的引用
:_data(data)
, _prev(NULL)
, _next(NULL)
{}
};
//链表的迭代器
template <class T,class Ptr,class Ref>
struct ListIterator
{
typedef ListNode<T> Node;
typedef ListIterator<T, T*, T&> Iterator;
typedef ListIterator<T,Ptr,Ref> Self;
Node* _node;
ListIterator(Node* node)//给一个链表节点的指针
:_node(node)
{}
ListIterator()
{}
ListIterator(const Self& it)
{
_node = it._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;
}
bool operator==(const Self& it)
{
return _node == it._node;
}
bool operator!=(const Self& it)
{
return _node != it._node;
}
};
//双向循环链表
template <class T>
class MyList
{
typedef ListNode<T> Node;
public:
typedef ListIterator<T, T*, T&> Iterator;
MyList()
{
_head = BuyNode(T());
_head->_next = _head;
_head->_prev = _head;
}
~MyList()
{
Clear();
delete _head;
_head = NULL;
}
//访问相关接口
Iterator Begin()
{
return _head->_next;
}
Iterator End()
{
return _head;
}
T& Front()
{
return _head->_next->_data;
}
T& Back()
{
return _head->_prev->_data;
}
bool Empty()
{
return _head->_next == _head&&_head->_prev == _head;
}
size_t Size()
{
size_t count = 0;
Node* cur = _head->_next;
while (cur != _head)
{
count++;
cur = cur->_next;
}
return count;
}
//插入相关接口
void PushBack(const T& x)
{
/*Node* newNode = BuyNode(x);
Node* tail = _head->_prev;
newNode->_next = _head;
tail->_next = newNode;
newNode->_prev = _head;
_head->_prev = newNode;*/
Insert(End(), x);
}
void PushFront(const T& x)
{
/*Node* newNode = BuyNode(x);
Node* next = _head->_next;
newNode->_next = next;
next->_prev = newNode;
newNode->_prev = _head;
_head->_next = newNode;*/
Insert(Begin(), x);
}
Iterator Insert(Iterator pos, const T& x)
//在pos前面插入一个元素,返回新加入元素的迭代器
{
Node* newNode = BuyNode(x);
Node* cur = pos._node;
newNode->_next = cur;
cur->_prev->_next = newNode;
newNode->_prev = cur->_prev;
cur->_prev = newNode;
return Iterator(newNode);
}
void Insert(Iterator pos, size_t n, const T& x)
//在pos位置之前插入n个x元素,与上一个Insert形成重载
{
for (size_t i = 0; i < n; ++i)
{
Insert(pos, x);
}
}
void Insert(Iterator pos, Iterator b, Iterator e)
//在pos的位置插入[b,e)的内容
{
Iterator tmp = b;
for (tmp = b; tmp != e; tmp++)
{
Insert(pos, tmp._node->_data);
}
}
//删除相关接口
Iterator Erase(Iterator pos)
{
assert(pos != End());
Node* cur = pos._node;
Node* del = cur;
cur = cur->_next;
del->_prev->_next = del->_next;
del->_next->_prev = del->_prev;
delete del;
del = NULL;
return Iterator(cur);
}
void PopBack()
{
Erase(--End());
}
void PopFront()
{
Erase(Begin());
}
//打印相关接口
void Print()
{
Node* cur = _head->_next;
while (cur != _head)
{
cout << cur->_data << " ";
cur = cur->_next;
}
}
protected:
Node* BuyNode(const T& x)
{
Node* newNode = new Node(x);
return newNode;
}
void Clear()
{
Node* cur = _head->_next;
while (cur != _head)
{
Node* tmp= cur->_next;
delete cur;
cur = tmp;
}
_head->_next = _head;
_head->_prev = _head;
}
protected:
Node* _head;
};
相关测试代码如下
void TestMyList1()//测试PushBack
{
int a[] = { 1, 2, 3, 4 };
MyList<int> list;
for (size_t i = 0; i < sizeof(a) / sizeof(a[0]); ++i)
{
list.PushBack(a[i]);
}
list.Print();
cout << endl;
}
void TestMyList2()//测试PushFront
{
int a[] = { 1, 2, 3, 4 };
MyList<int> list;
for (size_t i = 0; i < sizeof(a) / sizeof(a[0]); ++i)
{
list.PushBack(a[i]);
}
list.PushFront(0);
list.Print();
cout << endl;
}
void TestMyList3()//测试Insert
{
int a1[] = { 1, 2, 3, 4 };
MyList<int> list1;
for (size_t i = 0; i < sizeof(a1) / sizeof(a1[0]); ++i)
{
list1.PushBack(a1[i]);
}
MyList<int>::Iterator it=list1.Begin();
//测试第一个insert
it=list1.Insert(it, 0);
list1.Print();
cout << endl;
//测试第二个insert
it = list1.End();
list1.Insert(it, 3, 5);
list1.Print();
cout << endl;
//测试第三个insert
it--;
int a2[] = { 1, 2, 3, 4 };
MyList<int> list2;
for (size_t i = 0; i < sizeof(a2) / sizeof(a2[0]); ++i)
{
list2.PushBack(a2[i]);
}
list1.Insert(it, list2.Begin(), list2.End());
list1.Print();
cout << endl;
}
void TestMyList4()//测试PopBack、PopFront、Erase
{
int a[] = { 1, 2, 3, 4 };
MyList<int> list;
for (size_t i = 0; i < sizeof(a) / sizeof(a[0]); ++i)
{
list.PushBack(a[i]);
}
list.PopBack();//删除4,剩1 2 3
list.PopFront();//删除1,剩2 3
list.Erase(list.Begin());//删除2
list.Print();
cout << endl;
}
void TestMyList5()//测试其他接口
{
int a[] = { 1, 2, 3, 4 };
MyList<int> list;
for (size_t i = 0; i < sizeof(a) / sizeof(a[0]); ++i)
{
list.PushBack(a[i]);
}
int size = list.Size();
cout << size;
cout << endl;
int num1 = list.Front();
cout << num1;
cout << endl;
int num2 = list.Back();
cout << num2;
cout << endl;
list.PopBack();
list.PopBack();
list.PopBack();
cout << list.Empty();
cout << endl;
}