模拟实现List容器(C++)

概述

List容器框架

List模拟实现

ListNode节点类

MyList结构

无参构造

List迭代器

完整的MyList类定义

Insert插入数据

Erase删除数据

Push插入数据

Pop删除数据

其他函数

Clear清除数据

析构函数

测试代码MyList.cpp

完整代码MyList.hpp


概述

向博主学习了一下:(84条消息) 【C++】手把手教你写出自己的list类_Ornamrr的博客-CSDN博客

List容器框架

List容器的底层数据结构实际上是带头双向循环链表,框架结构如图:

 

List模拟实现

ListNode节点类

在底层结构中,节点是基本单元,首先我们要定义节点类的模板:

节点模板
template<class T>
class ListNode {
public:
	ListNode<T>* _prev;
	T _val;
	ListNode<T>* _next;

	ListNode(const T& val) : _prev(nullptr), _val(val), _next(nullptr){}
};

MyList结构

定义了节点类,我们要明确List容器的实现逻辑:List容器主要维护一个头节点指针,以访问整个链表:

无参构造

由上面的结构可以对MyList类进行设计和初始化:

///list模板类的实现 维护一个头节点指针,且头仅做连接作用,不存数据
template<class T>
class MyList {
	typedef ListNode<T> Node;
private:
	Node* _head;
public:
	//无参构造
	MyList() {//带头节点的,不实际用
		_head = new Node(0);
		_head->_next = _head;
		_head->_prev = _head;
	}
}

List迭代器

在标准模板库STL中,每种容器都有其独特的迭代器,而List容器的迭代器本质上是一个节点指针,而由于List迭代器相较于vector容器更加复杂,这里对其进行封装,并重载了可能用到的运算符等:

/list迭代器的定义,并不只是简单的类型指针,它的下一位置是_next
template<class T>
struct _list_iterator//参数模板Ref,指针模板Ptr
{
	typedef _list_iterator <T> self;
	typedef ListNode<T> Node;

	Node* _node;

	//构造函数
	_list_iterator(Node* node)
		:_node(node)
	{}
	//重载解引用
	T operator*()
	{
		return _node->_val;
	}
	//重载++和--
	self operator++()
	{
		this->_node = this->_node->_next;
		return *this;
	}
	self operator--()
	{
		this->_node = this->_node->_prev;
		return *this;
	}
	//重载==和!=
	bool operator==(const self& it) const {
		return _node == it._node;
	}

	bool operator!=(const self& it) const {
		return _node != it._node;
	}
};

完整的MyList类定义

///list模板类的实现 维护一个头节点指针,且头仅做连接作用,不存数据
template<class T>
class MyList {
	typedef ListNode<T> Node;
	typedef _list_iterator<T> list_iterator;
private:
	Node* _head;
public:
	//无参构造
	MyList() {//带头节点的,不实际用
		_head = new Node(0);
		_head->_next = _head;
		_head->_prev = _head;
	}
	//拷贝构造
	MyList(MyList<T>& Lt) {
		_head = new Node(0);
		_head->_next = _head;
		_head->_prev = _head;
		Node* cur = Lt._head->_next;
		while (cur != Lt._head) {
			this->push_back(cur->_val);
			cur = cur->_next;
		}
	}
	//重载赋值
	MyList<T>& operator=(MyList<T>& Lt) {
		this->_head = Lt._head;
		return *this;
	}
	
	//成员函数
	void push_back(T val);
	void push_front(T val);
	void pop_back();
	void pop_front();
	void insert(list_iterator pos, T val);
	void erase(list_iterator pos);
	int size();
	bool empty();
	T front();//获取头部元素
	T back();//获取尾部元素
	void clear();//清除除了头节点以外的所有节点

	//迭代器iterator的模拟  头尾的迭代器
	list_iterator begin() {//在前一个位置插入节点insert 头插和尾插
		return _head->_next;//实际的头位置
	}
	list_iterator end() {
		return _head;//尾的下一个位置是头
	}

	//析构函数
	~MyList() {
		this->clear();//释放其他节点
		delete _head;//释放头节点
		_head = NULL;
	}
};

Insert插入数据

这里的插入是pos位置的前一个位置插入节点,头插和尾插也可适用,运行逻辑如图:

 

template<class T>
void MyList<T>::insert(list_iterator pos, T val) {
	Node* prev = pos._node->_prev;
	Node* new_node = new Node(val);
	prev->_next = new_node;
	new_node->_prev = prev;
	new_node->_next = pos._node;
	pos._node->_prev = new_node;
}

Erase删除数据

注意头节点的位置:

template<class T>
void MyList<T>::erase(list_iterator pos) {
	if (_head->_next == _head) {
		cout << "已经删除完毕了,不能再删了!!" << endl;
		return;
	}
	if (pos._node == _head) {//防止删除头部
		Node* prev = pos._node->_prev;
		Node* pprev = prev->_prev;
		pprev->_next = _head;
		_head->_prev = pprev;
		return;
	}
	Node* prev = pos._node->_prev;
	Node* next = pos._node->_next;
	prev->_next = next;
	next->_prev = prev;
	delete pos._node;
}

Push插入数据

可以通过分析实现,也可以利用Insert直接实现:

template<class T>
void MyList<T>::push_back(T val) {
	//Node* tail = _head->_prev;
	//Node* new_node = new Node(val);

	//tail->_next = new_node;
	//new_node->_prev = tail;
	//new_node->_next = _head;
	//_head->_prev = new_node;

	this->insert(this->end(), val);
}

template<class T>
void MyList<T>::push_front(T val) {
	//Node* next = _head->_next;
	//Node* new_node = new Node(val);

	//new_node->_next = next;
	//next->_prev = new_node;
	//new_node->_prev = _head;
	//_head->_next = new_node;
	this->insert(this->begin(), val);
}

Pop删除数据

可以通过分析实现,也可以利用Erase直接实现:

template<class T>
void MyList<T>::pop_back() {
	/*if (_head->_next == _head) {
		cout << "已经删除完毕了,不能再删了!!" << endl;
		return;
	}
	Node* tail = _head->_prev;
	Node* tailprev = tail->_prev;
	delete tail;
	tail = NULL;
	tailprev->_next = _head;
	_head->_prev = tailprev;*/
	this->erase(this->end());
}

template<class T>
void MyList<T>::pop_front() {
	/*if (_head->_next == _head) {
		cout << "已经删除完毕了,不能再删了!!" << endl;
		return;
	}
	Node* front = _head->_next;
	Node* next = front->_next;
	delete front;
	_head->_next = next;
	next->_prev = _head;*/
	this->erase(this->begin());
}

其他函数

template<class T>
int MyList<T>::size() {
	int count = 0;
	Node* cur = _head->_next;
	while (cur != _head) {
		count++;
		cur = cur->_next;
	}
	return count;
}

template<class T>
bool MyList<T>::empty() {
	return this->size() == 0;
}

template<class T>
T MyList<T>::front() {
	return _head->_next->_val;
}

template<class T>
T MyList<T>::back() {
	return _head->_prev->_val;
}

Clear清除数据

清除数据,释放除了头节点以外的所有节点:

template<class T>
void MyList<T>::clear() {
	//释放除了头节点以外的全部节点
	while (_head->_next != _head) {
		this->erase(this->begin());
	}
}

析构函数

释放所有节点:

//析构函数
template<class T>
MyList<T>::~MyList() {
	this->clear();//释放其他节点
	delete _head;//释放头节点
	_head = NULL;
}

测试代码MyList.cpp

#define _CRT_SECURE_NO_WARNINGS 1
#include"MyList.hpp"

int main() {
	MyList<int> lt;//无参构造
	lt.push_back(1);//尾插
	lt.push_back(2);
	lt.push_back(3);
	lt.push_back(4);
	lt.push_back(5);

	lt.push_front(6);//头插
	lt.push_front(7);
	lt.push_front(8);

	lt.pop_back();//尾删
	lt.pop_back();

	lt.pop_front();//头删
	lt.pop_front();

	MyList<int> lt1(lt);//拷贝构造

	MyList<int> lt2 = lt;//赋值运算

	lt.insert(lt.begin(), 9);//插入测试
	lt.insert(lt.end(), 10);

	cout << "size = " << lt.size() << endl;
	cout << "front = " << lt.front() << endl;
	cout << "back = " << lt.back() << endl;
	cout << "empty = " << lt.empty() << endl;

	for (_list_iterator<int> it = lt.begin(); it != lt.end(); ++it) {
		cout << *it << " ";
	}
	cout << endl;
	cout << endl;

	lt.erase(lt.begin());//删除测试
	lt.erase(lt.end());

	lt.clear();//清除测试
	cout << "清理过后: " << endl;
	cout << "empty = " << lt.empty() << endl;


	return 0;
}

完整代码MyList.hpp

#pragma once
#include<iostream>

using namespace std;

//类模板的使用,需要将函数声明和实现写在一个文件中,
//并且文件后缀改为.hpp,在使用时包含头文件。

/C++实现list  带头双向循环链表

节点模板
template<class T>
class ListNode {
public:
	ListNode<T>* _prev;
	T _val;
	ListNode<T>* _next;

	ListNode(const T& val) : _prev(nullptr), _val(val), _next(nullptr){}
};

/list迭代器的定义,并不只是简单的类型指针,它的下一位置是_next
template<class T>
struct _list_iterator//参数模板Ref,指针模板Ptr
{
	typedef _list_iterator <T> self;
	typedef ListNode<T> Node;

	Node* _node;

	//构造函数
	_list_iterator(Node* node)
		:_node(node)
	{}
	//重载解引用
	T operator*()
	{
		return _node->_val;
	}
	//重载++和--
	self operator++()
	{
		this->_node = this->_node->_next;
		return *this;
	}
	self operator--()
	{
		this->_node = this->_node->_prev;
		return *this;
	}
	//重载==和!=
	bool operator==(const self& it) const {
		return _node == it._node;
	}

	bool operator!=(const self& it) const {
		return _node != it._node;
	}
};

///list模板类的实现 维护一个头节点指针,且头仅做连接作用,不存数据
template<class T>
class MyList {
	typedef ListNode<T> Node;
	typedef _list_iterator<T> list_iterator;
private:
	Node* _head;
public:
	//无参构造
	MyList() {//带头节点的,不实际用
		_head = new Node(0);
		_head->_next = _head;
		_head->_prev = _head;
	}
	//拷贝构造
	MyList(MyList<T>& Lt) {
		_head = new Node(0);
		_head->_next = _head;
		_head->_prev = _head;
		Node* cur = Lt._head->_next;
		while (cur != Lt._head) {
			this->push_back(cur->_val);
			cur = cur->_next;
		}
	}
	//重载赋值
	MyList<T>& operator=(MyList<T>& Lt) {
		this->_head = Lt._head;
		return *this;
	}
	
	//成员函数
	void push_back(T val);
	void push_front(T val);
	void pop_back();
	void pop_front();
	void insert(list_iterator pos, T val);
	void erase(list_iterator pos);
	int size();
	bool empty();
	T front();//获取头部元素
	T back();//获取尾部元素
	void clear();//清除除了头节点以外的所有节点

	//迭代器iterator的模拟  头尾的迭代器
	list_iterator begin() {//在前一个位置插入节点insert 头插和尾插
		return _head->_next;//实际的头位置
	}
	list_iterator end() {
		return _head;//尾的下一个位置是头
	}

	//析构函数
	~MyList() {
		this->clear();//释放其他节点
		delete _head;//释放头节点
		_head = NULL;
	}
};

template<class T>
void MyList<T>::push_back(T val) {
	//Node* tail = _head->_prev;
	//Node* new_node = new Node(val);

	//tail->_next = new_node;
	//new_node->_prev = tail;
	//new_node->_next = _head;
	//_head->_prev = new_node;

	this->insert(this->end(), val);
}

template<class T>
void MyList<T>::push_front(T val) {
	//Node* next = _head->_next;
	//Node* new_node = new Node(val);

	//new_node->_next = next;
	//next->_prev = new_node;
	//new_node->_prev = _head;
	//_head->_next = new_node;
	this->insert(this->begin(), val);
}

template<class T>
void MyList<T>::pop_back() {
	/*if (_head->_next == _head) {
		cout << "已经删除完毕了,不能再删了!!" << endl;
		return;
	}
	Node* tail = _head->_prev;
	Node* tailprev = tail->_prev;
	delete tail;
	tail = NULL;
	tailprev->_next = _head;
	_head->_prev = tailprev;*/
	this->erase(this->end());
}

template<class T>
void MyList<T>::pop_front() {
	/*if (_head->_next == _head) {
		cout << "已经删除完毕了,不能再删了!!" << endl;
		return;
	}
	Node* front = _head->_next;
	Node* next = front->_next;
	delete front;
	_head->_next = next;
	next->_prev = _head;*/
	this->erase(this->begin());
}

template<class T>
void MyList<T>::insert(list_iterator pos, T val) {
	Node* prev = pos._node->_prev;
	Node* new_node = new Node(val);
	prev->_next = new_node;
	new_node->_prev = prev;
	new_node->_next = pos._node;
	pos._node->_prev = new_node;
}

template<class T>
void MyList<T>::erase(list_iterator pos) {
	if (_head->_next == _head) {
		cout << "已经删除完毕了,不能再删了!!" << endl;
		return;
	}
	if (pos._node == _head) {//防止删除头部
		Node* prev = pos._node->_prev;
		Node* pprev = prev->_prev;
		pprev->_next = _head;
		_head->_prev = pprev;
		return;
	}
	Node* prev = pos._node->_prev;
	Node* next = pos._node->_next;
	prev->_next = next;
	next->_prev = prev;
	delete pos._node;
}

template<class T>
int MyList<T>::size() {
	int count = 0;
	Node* cur = _head->_next;
	while (cur != _head) {
		count++;
		cur = cur->_next;
	}
	return count;
}

template<class T>
bool MyList<T>::empty() {
	return this->size() == 0;
}

template<class T>
T MyList<T>::front() {
	return _head->_next->_val;
}

template<class T>
T MyList<T>::back() {
	return _head->_prev->_val;
}

template<class T>
void MyList<T>::clear() {
	//释放除了头节点以外的全部节点
	while (_head->_next != _head) {
		this->erase(this->begin());
	}
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值