STL 是C++的标准模板库(Standard Template Library),包含了常用数据结构的类实现(array,list,stack,queue,等等),一些常用算法的实现(查找,排序,关系,等等),以及迭代器,仿函数,等等。在项目开发过程中,使用标准模板库可以提高开发效率。
本篇来讲一下 STL 中的 list 的常用方法以及简单的模拟实现
STL list链表 list,是一个模板类,在C++ std 命名空间内,使用时包含list头:
#includeusing namespace std;
指定一下放入链表中的数据类型,如 int,声明一个存放整数的链表 li:
listli;
就表示链表 li 中存储的数据都是 int 的,其它数据类型也是如此:
// 存储 string 类型 listlist 的一些常用方法:ls;
| size() | 返回链表的当前大小 |
| front() | 返回链表的第一个元素 |
| back() | 返回链表的最后一个元素 |
| empty() | 判断链表是否为空(空返回true,非空返回false) |
| clear() | 清空链表 |
| push_back(要插入的数据) | 往链表尾部插入元素(尾插法) |
| push_front(要插入的数据) | 往链表头部插入数据(头插法) |
| remove(要删除的数据) | 删除链表中的某元素,所有这些值的元素都会被删除 |
| begin() | 返回链表中第一个元素的迭代器 |
| end() | 返回链表中最后一个元素的迭代器 |
list 的遍历
使用迭代器来遍历:
list::iterator iter;
li.begin() 是 li 的第一个元素的迭代器,li.end()是 li 的最后一个元素的迭代器,让 iter 从第一个迭代器开始一直到最后一个迭代器移动即可。怎么移动呢?迭代器重载了 ++ 运算符,使 iter 后移,并且重载了 * 运算符来获取当前迭代器的元素值。
使用下面方法来遍历链表:
list::iterator iter; for (iter = li.begin(); iter != li.end(); iter++) { cout << *iter << " "; } cout << endl;
可以看到这个很像指针,其实迭代器就是模仿了指针的行为。
也可以使用 C++11 中扩展的 for 循环来遍历:
for (auto v : li)
{
cout << v << " ";
}
cout << endl;
这种方法的本质也就是迭代器遍历,使用这种方法遍历的时候类中必须要有一个迭代器类!
简单测试一下 STL list#include#include
#include using namespace std; void testIntList() { list li; for (int i = 0; i < 10; i++) { // 尾部添加数据 li.push_back(i); } // 打印一下链表当前大小 cout << li.size() << endl; // 头部添加数据 li.push_front(1); // 打印一下链表的首个元素和最后一个元素 cout << li.front() << " " << li.back() << endl; // 迭代器遍历 list ::iterator iter; for (iter = li.begin(); iter != li.end(); iter++) { cout << *iter << " "; } cout << endl; // C++11 新的 for 循环遍历(本质是迭代器遍历) for (auto v : li) { cout << v << " "; } cout << endl; // 删除链表中的所有元素值为 1 的节点 li.remove(1); // C++11 新的 for 循环遍历(本质是迭代器遍历) for (auto v : li) { cout << v << " "; } cout << endl; } void testStringList() { list ls; ls.push_front(string("C")); ls.push_front(string("B")); ls.push_front(string("A")); for (auto v : ls) { cout << v << " "; } cout << endl; } int main() { testIntList(); cout << endl; testStringList(); return 0; }
测试结果:
简单实现 MyListMyList.hpp
#pragma once #include// 节点类 template struct Node { _T data; Node<_T>* next; Node(_T data) :data(data), next(nullptr) {} }; // 链表类 template class MyList { public: // 构造 explicit MyList() { frontNode = nullptr; backNode = nullptr; curSize = 0; } // 析构 virtual ~MyList() { Node<_T>* moveNode = frontNode; while (moveNode != nullptr) { Node<_T>* tmp = moveNode->next; delete moveNode; moveNode = tmp; } } // 返回头节点数据 _T front() const { return frontNode->data; } // 返回尾节点数据 _T back() const { return backNode->data; } // 返回链表当前大小 int size() const { return curSize; } // 判空 bool empty() const { return curSize == 0; } // 重载 [] 运算符 _T operator[](int idx) { int i = 0; iterator it; for (i = 0, it = begin(); it != end(); i++, it++) { if (i == idx) { return *it; } } } // 头插法 void push_front(_T data) { Node<_T>* newNode = new Node<_T>(data); newNode->next = frontNode; if (curSize == 0) { backNode = newNode; } frontNode = newNode; curSize++; } // 尾插法 void push_back(_T data) { Node<_T>* newNode = new Node<_T>(data); if (curSize == 0) { frontNode = newNode; } else { backNode->next = newNode; } backNode = newNode; curSize++; } // 重载 << 运算符 friend std::ostream& operator<<(std::ostream& out, const MyList& list) { Node<_T>* pMove = list.frontNode; while (pMove != nullptr) { out << pMove->data << " "; pMove = pMove->next; } return out; } public: // 迭代器类 class iterator { public: explicit iterator(Node<_T>* pNode) :pMove(pNode) {} iterator() = default; _T operator*() { return pMove->data; } iterator operator++() { pMove = pMove->next; return (*this); } iterator operator++(int) { pMove = pMove->next; return (*this); } iterator operator+=(int add) { for (int i = 0; i < add; i++) { pMove = pMove->next; } return (*this); } bool operator!=(iterator obj) { return obj.pMove->next != this->pMove; } protected: Node<_T>* pMove; }; iterator begin() const { return iterator(frontNode); } iterator end() const { return iterator(backNode); } protected: Node<_T>* frontNode; Node<_T>* backNode; int curSize; };
testMyList.cpp
#include "MyList.hpp" #includeusing namespace std; int main() { MyList myList; for (int i = 0; i < 10; i++) myList.push_back(i); // 这种循环就是迭代器遍历 for (auto i : myList) cout << i; cout << endl << "--------------------------------" << endl; cout << myList << endl; MyList ::iterator it; for (it = myList.begin(); it != myList.end(); it += 2) cout << *it << " "; cout << endl << myList[2] << endl; for (auto i : myList) cout << i << " "; cout << endl; return 0; }



