c++的学习之路:15、list(2)

本章主要是讲模拟实现list,文章末附上代码。

目录

一、创建思路

二、构造函数

三、迭代器

四、增删

五、代码


一、创建思路

如下方代码,链表是由一块一块不连续的空间组成的,所以这里写了三个模板,一个是节点,一个是迭代器,分别放在struct创建的类,因为这个是可以直接访问,从下方代码可以看出我是在list里面定义了一个head,这个就是哨兵位头节点,然后在list_node里面写的就是节点的初始化,需要使用时直接new一个,_list_iterator这个就是迭代器写的地方了,这里也是直接写了两个一个普通的迭代器,一个const的。

namespace ly

{

template<class T>

struct list_node

{

list_node<T>* _next;

list_node<T>* _prev;

T _data;

list_node(const T& x = T())

:_next(nullptr)

, _prev(nullptr)

, _data = x

{}

};

template<class T,class Ref,class Ptr>

struct _list_iterator

{

typedef list_node<T> node;

typedef __list_iterator<T, Ref, Ptr> self;

node* _node;

node* _node;

_list_iterator(node* n)

:_node(n)

{}

};

template<class T>

class list

{

public:

typedef list_node<T> node;

typedef _list_iterator<T, T&, T*> iterator;

typedef _list_iterator<T, const T&, const T*> const_iterator;

private:

node* _head;

};

}

二、构造函数

如下方代码所示就是我写的构造函数,因为这个链表是一个双向循环带头链表所以,直接new一个node在把哨兵位的next和prev指向自己,就创建出了一个链表,如下方图片可以看出创造出来了。

list()

{

_head = new node;

_head->_next = _head;

_head->_prev = _head;

}

三、迭代器

这里是把迭代器能用到的都写了,例如解引用,就是利用这个节点指针直接访问就可以了,但是考虑到了可能访问常量指针所以,这里就是利用模板参数进行访问的,第二个就是相当于访问数据了,因为在流输出的时候正常是访问不到,因为迭代器访问的是这个节点的额指针,这时重载了一个->就可以正常访问了,++就是下一个节点的地址,也就是这个节点里面存入的next,前置和后置在之前文章中都说过,这里就不详细介绍了,后置就是价格int以作区分,--也是类似操作,==与!=直接判断节点的地址是否相同就可以了。

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& s)

{

return _node == s._node;

}

bool operator!=(const self& s)

{

return _node != s._node;

}

四、增删

再写数据结构的顺序表的时候就知道了,头插尾插头删尾删是可以直接使用inster的,所以这里是直接写了inster在进行调用的,代码如下,测试代码如下,结果如图,这里是直接调用insert的所以就不测试这个了。

iterator begin()

{

return iterator(_head->_next);

}

iterator end()

{

return iterator(_head);

}

const_iterator begin() const

{

return const_iterator(_head->_next);

}

const_iterator end() const

{

return const_iterator(_head);

}

void push_back(const T& x)

{

insert(end(),x);

}

void push_front(const T& x)

{

insert(begin(), x);

}

void pop_back()

{

erase(--end());

}

void pop_front()

{

erase(begin());

}

void insert(iterator pos,const T& x)

{

node* cur = pos._node;

node* prev = cur->_prev;

node* new_node = new node(x);

prev->_next = new_node;

new_node->_prev = prev;

new_node->_next = cur;

cur->_prev = new_node;

}

void erase(iterator pos)

{

assert(pos != end());

node* prev = pos._node->_prev;

node* next = pos._node->_next;

prev->_next = next;

next->_prev = prev;

delete pos._node;

}

void Test1()

{

list<int> l1;

l1.push_back(1);

l1.push_back(2);

l1.push_back(3);

l1.push_back(4);

print(l1);

l1.push_front(5);

l1.push_front(6);

l1.push_front(7);

l1.push_front(8);

print(l1);

l1.pop_back();

l1.pop_back();

print(l1);

l1.pop_front();

l1.pop_front();

print(l1);

}

五、代码

#pragma once
#include <assert.h>
namespace ly
{
	template<class T>
	struct list_node
	{
		list_node<T>* _next;
		list_node<T>* _prev;
		T _data;

		list_node(const T& x = T())
			:_next(nullptr)
			, _prev(nullptr)
			, _data(x)
		{}
	};

	template<class T, class Ref, class Ptr>
	struct _list_iterator
	{
		typedef list_node<T> node;
		typedef _list_iterator<T, Ref, Ptr> self;
		node* _node;

		_list_iterator(node* n)
			:_node(n)
		{}

		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& s)
		{
			return _node == s._node;
		}

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

	template<class T>
	class list
	{
	public:
		typedef list_node<T> node;
		typedef _list_iterator<T, T&, T*> iterator;
		typedef _list_iterator<T, const T&, const T*> const_iterator;

		list()
		{
			_head = new node;
			_head->_next = _head;
			_head->_prev = _head;
		}

		iterator begin()
		{
			return iterator(_head->_next);
		}

		iterator end()
		{
			return iterator(_head);
		}
		
		const_iterator begin() const
		{
			return const_iterator(_head->_next);
		}

		const_iterator end() const
		{
			return const_iterator(_head);
		}

		void push_back(const T& x)
		{
			insert(end(),x);
		}

		void push_front(const T& x)
		{
			insert(begin(), x);
		}

		void pop_back()
		{
			erase(--end());
		}

		void pop_front()
		{
			erase(begin());
		}

		void insert(iterator pos,const T& x)
		{
			node* cur = pos._node;
			node* prev = cur->_prev;
			node* new_node = new node(x);
			prev->_next = new_node;
			new_node->_prev = prev;
			new_node->_next = cur;
			cur->_prev = new_node;
		}

		void erase(iterator pos)
		{
			assert(pos != end());
			node* prev = pos._node->_prev;
			node* next = pos._node->_next;
			prev->_next = next;
			next->_prev = prev;
			delete pos._node;
		}

	private:
		node* _head;
	};

	void print(list<int> l)
	{
		list<int>::iterator it = l.begin();
		while (it != l.end())
		{
			cout << *it << ' ';
			it++;
		}
		cout << endl;
	}

	void Test1()
	{
		list<int> l1;
		l1.push_back(1);
		l1.push_back(2);
		l1.push_back(3);
		l1.push_back(4);
		print(l1);
		l1.push_front(5);
		l1.push_front(6);
		l1.push_front(7);
		l1.push_front(8);
		print(l1);
		l1.pop_back();
		l1.pop_back();
		print(l1);
		l1.pop_front();
		l1.pop_front();
		print(l1);
	}
}

#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>

using namespace std;

#include "list.h"

int main()
{
	ly::Test1();
}
相关推荐
EnigmaCoder14 分钟前
蓝桥杯刷题周计划(第二周)
学习·算法·蓝桥杯
银河小铁骑plus1 小时前
Go学习笔记:基础语法6
笔记·学习·golang
xcyxiner1 小时前
snmp wireshark 抓包
c++
rocksun1 小时前
BJARNE STROUSTRUP谈C++的演变
c++
我不是代码教父2 小时前
[原创](Modern C++)现代C++的关键性概念: 非常独特的std::sentinel_for概念(哨兵概念)
开发语言·c++·sentinel
JuicyActiveGilbert2 小时前
【C++设计模式】第十六篇:迭代器模式(Iterator)
c++·设计模式·迭代器模式
汤姆和杰瑞在瑞士吃糯米粑粑2 小时前
【Linux学习篇】--开发工具第一期
linux·运维·学习
commonbelive2 小时前
考研机试常见基本题型
c语言·c++·算法
希望_睿智2 小时前
C++网络编程之套接字选项配置
c++·网络协议
sealaugh322 小时前
aws(学习笔记第三十二课) 深入使用cdk(API Gateway + event bridge)
笔记·学习·aws