list的模拟实现

iterator insert(iterator pos,const T&x)
{
	Node* newnode = new Node(x);
	Node* cur = pos._node;//先存一下pos位置的指针
	Node* prev = cur->_prev;//再存一下没插入之前pos前面节点的指针

	cur->_prev = newnode;
	newnode->_next = cur;
	newnode->_prev = prev;
	prev->_next = newnode;
	
	return newnode;
}

开头 

#include<iostream>
#include<assert.h>
using namespace std;
namespace Ljw

//结点,节点要要公开,用struct就好

//结点,节点要要公开,用struct就好
template<class T>
struct list_node
{
	list_node<T>* _prev;
	list_node<T>* _next;
	T _val;

	//结点的初始化构造函数
	list_node(const T&val=T())//写成T(),是为了防止T不是内置类型
		:_val(val)
		,_prev(nullptr)
		,_next(nullptr)
	{}
};

迭代器指针

template<class T, class  Ref,   class Ptr>
struct __list_node
{
    typedef list_node<T> Node;
    typedef __list_node<T,Ref,Ptr>  KKK;
};

指向节点的指针

Node* _node;

构造函数

__list_node(Node*node)
	:_node(node)
{}

operator*

Ref& operator*()//这里是const迭代器的关键,返回的*it,就是指向的位置
{
	return _node->_val;
}

这里是const迭代器的关键,返回的*it,就是指向的位置 

operator++

	KKK operator++()
	{
		_node = _node->_next;
		return *this;
	}
    KKK operator++(int)
    {
	    KKK tmp(*this);
	    _node = _node->_next;
	    return tmp;
    }

operator--

KKK operator--()
{
	_node = _node->_prev;
	return *this;
}	
KKK operator--(int)
{
	Node tmp(*this);
	_node = _node->_prev;
	return tmp;
}

operator!=

bool operator!=(const KKK&it)//里面必须加const,因为返回的end()具有常性
{
	return _node != it._node;
}

里面必须加const,因为返回的end()具有常性

operator->

Ptr* operator->()//这里的T*也分为const和不带const,所以加上class Ptr
{
	return &_node->_val;
}

这里的T*也分为const和不带const,所以加上class Ptr

list

template<class T>
class list
{


private:
	Node*_head;
	size_t _size;
};

 三参数的传递

(第二个const迭代器,第三个是带不带const的->的重载)

	typedef list_node<T> Node;//相当于私有

public:
	//迭代器
	typedef __list_node<T,T&, T*>  iterator;//第三个T*是为了operator->的重载
	//const迭代器
	//typedef const __list_node<T>  const_iterator;这种写法是错误的,因为const后的对象无法
	                                                                             //修改,但我们需要的是it++,可以被修改,不被修改的是
														//指向的内容不被修改
														
	//正确写法
	typedef __list_node<T,const T&,const T*>  const_iterator;

//const迭代器
//typedef const __list_node<T>  const_iterator;这种写法是错误的,因为
const后的对象无法修改,但我们需要的是it++,可以被修改,不被修改的是指向的内容不被修改

构造函数

list()
{
	_head = new Node;// new一个类型就相当于new一个这个类型的空间
	_head->_next = _head;
	_head->_prev = _head;
}

new一个类型就相当于new一个这个类型的空间

尾插

void push_back(const T&x)
{
	//Node* newnode = new Node(x);//初始化为x,()是初始化[]开空间
	先把尾结点和头结点连接起来
	//Node* tail = _head->_prev;//一开始时,_head_>prev指向的是自己
	//tail->_next = newnode;//一开始要把_head的prev和next与newnode连接起来

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

	insert(end(),x);
}

iterator begin

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

iterator end()

iterator end()
{
	return _head;//左闭右开
}

const_iterator

const_iterator begin() const
{
	return _head->_next;
}
const_iterator end() const
{
	return _head;//左闭右开
}

pos位置前插入

iterator insert(iterator pos,const T&x)
{
	Node* newnode = new Node(x);
	Node* cur = pos._node;//先存一下pos位置的指针
	Node* prev = cur->_prev;//再存一下没插入之前pos前面节点的指针

	cur->_prev = newnode;
	newnode->_next = cur;
	newnode->_prev = prev;
	prev->_next = newnode;
	
	return newnode;
}

pos位置的删除

iterator erase(iterator pos)
{
	assert(pos != end());//不能删除头结点

	Node* cur = pos._node;//存一下pos的节点指针
	Node* prev = cur->_prev;//存一下pos之前节点的指针
	Node* next = cur->_next;//存一下pos下一个节点的指针

	//连接pos位置前一个和后一个的节点,然后释放pos的空间
	prev->_next = next;
	next->_prev = prev;
	
	delete[]  cur;//加不加[]都行
	return next;
}

pop_back

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

push_front

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

pop_front

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

size

size_t size()
{
	size_t i = 0;
	auto it = begin();
	while (it != end())
	{
		i++;
		it++;
	}
	return i;
}

clear

clear,顺序表vector不需要释放空间,因为没法单独释放一部分空间,而链表list可以

void clear()
{
	auto it = begin();
	while (it != end())
	{
		it = erase(it);//这里会释放空间
		it++;
	}
	_size = 0;
}

erase(it);//这里会释放空间

析构

~list()
{
	clear();
	delete _head;
	_head = nullptr;
}

拷贝构造

必须要有一个头结点 

list(const list<T>& It)
{
	//必须要有一个头结点
	_head = new Node;
	_head->_next = _head;
	_head->_prev = _head;
	auto it = It.begin();
	while (it != It.end())
	{
		push_back(*it);
		it++;
	}
}

swap

	void swap(list<T>&It)
	{
		std::swap(_head, It._head);
		std::swap(_size, It._size);
	}

operator=

//=的实现
list<T>& operator=(list<T>&It)
{
	//现代写法用swap
	swap(It);
	return *this;
}

总代码加测试

//list.h
#pragma once
#include<iostream>
#include<assert.h>
using namespace std;
namespace Ljw
{
	//结点,节点要要公开,用struct就好
	template<class T>
	struct list_node
	{
		list_node<T>* _prev;
		list_node<T>* _next;
		T _val;

		//结点的初始化构造函数
		list_node(const T&val=T())//写成T(),是为了防止T不是内置类型
			:_val(val)
			,_prev(nullptr)
			,_next(nullptr)
		{}
	};

	//迭代器指针
	template<class T, class  Ref,   class Ptr>
	struct __list_node
	{
		typedef list_node<T> Node;
		typedef __list_node<T,Ref,Ptr>  KKK;

		Node* _node;//指向节点的指针

		//构造函数
		__list_node(Node*node)
			:_node(node)
		{}

		Ref& operator*()//这里是const迭代器的关键,返回的*it,就是指向的位置
		{
			return _node->_val;
		}

		KKK operator++()
		{
			_node = _node->_next;
			return *this;
		}
		KKK operator--()
		{
			_node = _node->_prev;
			return *this;
		}	
		KKK operator--(int)
		{
			Node tmp(*this);
			_node = _node->_prev;
			return tmp;
		}


		KKK operator++(int)
		{
			KKK tmp(*this);
			_node = _node->_next;
			return tmp;
		}

		bool operator!=(const KKK&it)//里面必须加const,因为返回的end()具有常性
		{
			return _node != it._node;
		}

		Ptr* operator->()//这里的T*也分为const和不带const,所以加上class Ptr
		{
			return &_node->_val;
		}
	};

	//list,带头双向链表
	template<class T>
	class list
	{
		typedef list_node<T> Node;//相当于私有

	public:
		//迭代器
		typedef __list_node<T,T&, T*>  iterator;//第三个T*是为了operator->的重载
		//const迭代器
		//typedef const __list_node<T>  const_iterator;这种写法是错误的,因为const后的对象无法
		                                                                             //修改,但我们需要的是it++,可以被修改,不被修改的是
															//指向的内容不被修改
															
		//正确写法
		typedef __list_node<T,const T&,const T*>  const_iterator;


		//构造函数
		list()
		{
			_head = new Node;// new一个类型就相当于new一个这个类型的空间
			_head->_next = _head;
			_head->_prev = _head;
		}

		//尾插
		void push_back(const T&x)
		{
			//Node* newnode = new Node(x);//初始化为x,()是初始化[]开空间
			先把尾结点和头结点连接起来
			//Node* tail = _head->_prev;//一开始时,_head_>prev指向的是自己
			//tail->_next = newnode;//一开始要把_head的prev和next与newnode连接起来

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

			insert(end(),x);
		}
		iterator begin()
		{
			return _head->_next;
		}
		iterator end()
		{
			return _head;//左闭右开
		}
		const_iterator begin() const
		{
			return _head->_next;
		}
		const_iterator end() const
		{
			return _head;//左闭右开
		}

		//pos位置前插入
		iterator insert(iterator pos,const T&x)
		{
			Node* newnode = new Node(x);
			Node* cur = pos._node;//先存一下pos位置的指针
			Node* prev = cur->_prev;//再存一下没插入之前pos前面节点的指针

			cur->_prev = newnode;
			newnode->_next = cur;
			newnode->_prev = prev;
			prev->_next = newnode;
			
			return newnode;
		}

		//pos位置的删除
		iterator erase(iterator pos)
		{
			assert(pos != end());//不能删除头结点

			Node* cur = pos._node;//存一下pos的节点指针
			Node* prev = cur->_prev;//存一下pos之前节点的指针
			Node* next = cur->_next;//存一下pos下一个节点的指针

			//连接pos位置前一个和后一个的节点,然后释放pos的空间
			prev->_next = next;
			next->_prev = prev;
			
			delete[]  cur;//加不加[]都行
			return next;
		}

		void pop_back() 
		{ 
			erase(--end()); 
		}
		void push_front(const T& val) 
		{ 
			insert(begin(), val); 
		}
		void pop_front() 
		{ 
			erase(begin()); 
		}
		size_t size()
		{
			size_t i = 0;
			auto it = begin();
			while (it != end())
			{
				i++;
				it++;
			}
			return i;
		}

		//clear,顺序表vector不需要释放空间,因为没法单独释放一部分空间,而链表list可以
		void clear()
		{
			auto it = begin();
			while (it != end())
			{
				it = erase(it);//这里会释放空间
				it++;
			}
			_size = 0;
		}

		//析构
		~list()
		{
			clear();
			delete _head;
			_head = nullptr;
		}

		//拷贝构造//必须要有一个头结点
		list(const list<T>& It)
		{
			//必须要有一个头结点
			_head = new Node;
			_head->_next = _head;
			_head->_prev = _head;
			auto it = It.begin();
			while (it != It.end())
			{
				push_back(*it);
				it++;
			}
		}

		void swap(list<T>&It)
		{
			std::swap(_head, It._head);
			std::swap(_size, It._size);
		}

		//=的实现
		list<T>& operator=(list<T>&It)
		{
			//现代写法用swap
			swap(It);
			return *this;
		}


	private:
		Node*_head;
		size_t _size;
	};

	void test1()
	{
		list<int>v;
		v.push_back(1);
		v.push_back(2);
		v.push_back(3);

		list<int>::iterator it = v.begin();//这里是浅拷贝,不是赋值,迭代器不用写析构
		while (it != v.end())
		{
			cout << *it << " ";
			it++;
		}
	}
	void test2()
	{
		list<int>v;
		v.push_back(1);
		v.push_back(2);
		v.push_back(3);
		v.push_back(4);
		v.push_back(3);

		v.insert(v.begin(), 9);
		
		auto it = v.begin();
		while(it!=v.end())
		{
			if (*it % 3 == 0)
			{
				it = v.erase(it);
			}
			else
			{
				it++;
			}	
		}
		for (auto e : v)
		{
			cout << e << " ";
		}
		cout << endl;
		cout<<v.size();
	}

	void test3()
	{
		list<int>v;
		v.push_back(1);
		v.push_back(2);
		v.push_back(3);
		v.push_back(4);
		v.push_back(3);

		list<int>v1(v);
		for (auto e : v1)
		{
			cout << e << " ";
		}
		cout << endl;

		list<int>v2;
		v2.push_back(10);
		v2.push_back(20);
		v2.push_back(30);
		v1 = v2;
		for (auto e : v1)
		{
			cout << e << " ";
		}
		cout << endl;
	}
}

  • 42
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 11
    评论
引用和提供了关于实现vector的两种方法。其中,引用展示了一个使用reserve和push_back方法的示例,而引用展示了一个使用new和memcpy函数的示例。这两种方法都是常见的实现vector的方式。 在第一种方法中,通过reserve函数可以预留足够的内存空间,然后使用push_back函数逐个将元素添加到vector中。这种方法的好处是可以避免不必要的内存重分配,提高了效率。 而第二种方法使用new操作符在堆上分配内存空间,并使用memcpy函数将已有的vector对象的数据复制到新的内存空间中。通过这种方式,可以实现深拷贝,即两个vector对象拥有独立的内存空间。这种方法的好处是可以在不修改原始vector对象的情况下创建一个新的vector对象。 除了以上两种方法,还可以使用其他方式实现vector类。例如,可以使用动态数组来实现vector的底层数据结构,然后通过成员函数实现vector的各种操作,如增加、删除、查找等。 总结来说,c语言模拟实现vector的关键是动态内存管理和对元素的增删改查操作。可以使用预留空间和逐个添加元素的方式,也可以使用动态数组和复制数据的方式来实现vector类。具体的实现方式可以根据需求和实际情况选择。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [C++——vector模拟实现](https://blog.csdn.net/weixin_49449676/article/details/126813526)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值