C++ STL list 及其简单模拟实现

STL 是C++的标准模板库(Standard Template Library),包含了常用数据结构的类实现(array,list,stack,queue,等等),一些常用算法的实现(查找,排序,关系,等等),以及迭代器,仿函数,等等。在项目开发过程中,使用标准模板库可以提高开发效率。

本篇来讲一下 STL 中的 list 的常用方法以及简单的模拟实现

STL list

链表 list,是一个模板类,在C++ std 命名空间内,使用时包含list头:

#include 
using namespace std;

指定一下放入链表中的数据类型,如 int,声明一个存放整数的链表 li:

list li;

就表示链表 li 中存储的数据都是 int 的,其它数据类型也是如此:

// 存储 string 类型
list ls;

list 的一些常用方法:

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

测试结果: 

C++ STL list 及其简单模拟实现_第1张图片

简单实现 MyList

MyList.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"
#include 
using 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;
}

你可能感兴趣的:(c++,list,stl)