list的模拟实现

2023-11-18

1、创建 链表结点

namespace JPC
{

   //创建 链表结点
	template<class T>
	struct list_node
	{
	   //成员变量
		T _data;    //结点的数据
		list_node<T>* _next; //结点的尾指针
		list_node<T>* _prev; //结点的头指针

		// 构造函数(对结点进行初始化)
		list_node(const T& x=T())
      //本质上:Node(const T& x=T())
			:_data(x)
			,_next(nullptr)
			,_prev(nullptr)
		{}

	};

2、创建 链表迭代器

//创建 链表迭代器 
	template<class T,class Ref,class Ptr>
	struct __list_iterator
	{
		typedef list_node<T> Node;
		typedef __list_iterator<T,Ref,Ptr> iterator;

		//成员变量
		Node* _node; //结点指针(结点地址)

		//构造函数
		__list_iterator(Node* node) //list的迭代器是借助于 结点指针 实现的
			:_node(node)  //迭代器初始化过程是赋值给各个结点的地址(也就是将结点指针赋值过去)
		{}

		// !=
		bool operator!=(const iterator& it)const  
		{
			return _node != it._node;  //这儿相当于: this->_node != it._node;
		}

		// ==
		bool operator==(const iterator& it)const
		{
			return _node == it._node;  //这儿相当于: this->_node != it._node;
		}


		// *it
		//T& operator*()
		// const T& operator*()
		Ref operator*() //通过模板参数把实例化的过程 泛型化了
		{
			return _node->_data;  //这儿相当于: this->_node->_data;
		}

		// -> 为:结点指针 直接访问 成员变量的方式
		//T* operator->()
		//const T* operator->()
		Ptr operator->()
		{
			return &(operator*()); //这儿相当于返回的是:&(_node->_data) 【结点指针】
		}                          // 返回的是地址,也是指针


		// ++it;
		iterator& operator++()
		{
			_node = _node->_next; //这儿相当于:this->_node = this->_node->_next;
			return *this; //返回的是当前所处结点的地址
		}

		// --it;
		iterator& operator--()
		{
			_node = _node->_prev; //这儿相当于:this->_node = this->_node->_prev;
			return *this; //返回的是当前所处结点的地址
		}

		//it++
		iterator& operator++(int)
		{
			iterator tmp(*this);
			_node = _node->_next;

			return tmp;
		}
		
	};

3、创建 链表

//创建 链表
	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(_head->_next) 是迭代器的构造函数,相当于 __list_iterator(_head->_next) 
		}  //返回的是 首结点的地址

		iterator end()
		{
			return iterator(_head);     // 相当于 __list_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)
		{
			//Node* tail = _head->_prev;   // 找list的尾结点  
			//Node* newnode = new Node(x); // 创建newnode

			再理清结点顺序
			 _head   tail   newnode
			//tail->_next = newnode;
			//newnode->_prev = tail;
			//newnode->_next = _head;
			//_head->_prev = newnode;

			insert(end(),x);
		}

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

		//插入
		iterator insert(iterator pos, const T& x)
		{
			//确定 cur结点、prev结点,并且构建新结点
			Node* cur = pos._node;
			Node* prev = cur->_prev;

			Node* newnode = new Node(x);
			// cur  prev newnode既可以做各个结点的名字,也可以作为迭代器类的成员变量
			// 而 _next 、_prev 分别为:结点的尾指针、头指针
			
			// prev  newnode  cur
			prev->_next = newnode;
			newnode->_prev = prev;
			newnode->_next = cur;
			cur->_prev = newnode;

			return iterator(newnode); //这儿返回的是 迭代器构造函数的结果
		}


		//尾删
		void pop_back()
		{
			erase(--end());
		}


		//头删
		void pop_front()
		{
			erase(begin());
		}

		//删除
		iterator erase(iterator pos)
		{
			assert(pos != end()); //不能删除头结点
			Node* cur = pos._node;
			Node* prev = cur->_prev;
			Node* next = cur->_next;

			// prev   cur   next
			prev->_next = next;
			next->_prev = prev;
			delete cur;

			return iterator(next);
		}

	private:
		Node* _head;  //哨兵位的头结点
	};

4、测试 模拟实现的list的功能

4.1 测试 iterator

void test_list1()
	{
		list<int> lt;
		lt.push_back(1);
		lt.push_back(2);
		lt.push_back(3);
		lt.push_back(4);
		lt.push_back(5);

		list<int>::iterator it= lt.begin();
		while (it != lt.end())
		{
			cout<< *it <<" ";
			++it;
		}
		cout << endl;

		//范围for
		for (auto e:lt)
		{
			cout<< e <<" ";
		}
		cout << endl;

	}

4.2 测试 ->

struct Pos
	{
		int _a1;
		int _a2;

		Pos(int a1=1,int a2=1)
			:_a1(a1)
			,_a2(a2)
		{}
	};

	// ->
	void test_list2()
	{
		list<Pos> lt;
		lt.push_back(Pos(10,20));
		lt.push_back(Pos(10, 21));

		list<Pos>::iterator it = lt.begin();
		while (it != lt.end())
		{
			//cout<< (*it)._a1 << ":" <<(*it)._a2 <<endl;
			cout<< it->_a1 << ":" << it->_a2 <<endl;
            //这儿的 it->_a1; 原本是:it->->_a1;
			//【第一个 -> 为运算符重载:it.operator->() 】
			//【第二个 -> 为 结点指针访问成员变量】
			//【为了提升语法的可读性,编译器进行了特殊处理,省略了一个 ->】

			++it;
		}
		cout << endl;
	}

4.3 测试 const_iterator

//const_iterator
	void Func(const list<int>& l)
	{
		list<int>::const_iterator it = l.begin();
		while (it != l.end())
		{
			cout<< *it <<" ";
			++it;
		}
		cout << endl;
	}

	void test_list3()
	{
		list<int> lt;
		lt.push_back(1);
		lt.push_back(2);
		lt.push_back(3);
		lt.push_back(4);
		lt.push_back(5);

		Func(lt);
	}

4.4 测试 头插、尾插、头删、尾删

void test_list4()
	{
		list<int> lt;
		lt.push_back(1);
		lt.push_back(2);
		lt.push_back(3);
		lt.push_back(4);
		lt.push_back(5);

		for (auto e : lt)
		{
			cout << e << " ";
		}
		cout << endl;

		lt.push_front(1);
		lt.push_front(1);

		for (auto e : lt)
		{
			cout << e << " ";
		}
		cout << endl;

		lt.pop_front();
		lt.pop_front();

		lt.pop_back();
		lt.pop_back();

		for (auto e : lt)
		{
			cout << e << " ";
		}
		cout << endl;

	}
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

list的模拟实现 的相关文章

  • 结构化绑定中缺少类型信息

    我刚刚了解了 C 中的结构化绑定 但有一件事我不喜欢 auto x y some func is that auto正在隐藏类型x and y 我得抬头看看some func的声明来了解类型x and y 或者 我可以写 T1 x T2 y
  • C++11 删除重写方法

    Preface 这是一个关于最佳实践的问题 涉及 C 11 中引入的删除运算符的新含义 当应用于覆盖继承父类的虚拟方法的子类时 背景 根据标准 引用的第一个用例是明确禁止调用某些类型的函数 否则转换将是隐式的 例如最新版本第 8 4 3 节
  • 如何从 Visual Studio 将视图导航到其控制器?

    问题是解决方案资源管理器上有 29 个项目 而且项目同时具有 ASP NET MVC 和 ASP NET Web 表单结构 在MVC部分中 Controller文件夹中有大约100个子文件夹 每个文件夹至少有3 4个控制器 视图完全位于不同
  • 传递给函数时多维数组的指针类型是什么? [复制]

    这个问题在这里已经有答案了 我在大学课堂上学习了 C 语言和指针 除了多维数组和指针之间的相似性之外 我认为我已经很好地掌握了这个概念 我认为由于所有数组 甚至多维 都存储在连续内存中 因此您可以安全地将其转换为int 假设给定的数组是in
  • -webkit-box-shadow 与 QtWebKit 模糊?

    当时有什么方法可以实现 webkit box shadow 的工作模糊吗 看完这篇评论错误报告 https bugs webkit org show bug cgi id 23291 我认识到这仍然是一个问题 尽管错误报告被标记为RESOL
  • 用于 FTP 的文件系统观察器

    我怎样才能实现FileSystemWatcherFTP 位置 在 C 中 这个想法是 每当 FTP 位置添加任何内容时 我都希望将其复制到我的本地计算机 任何想法都会有所帮助 这是我之前问题的后续使用 NET 进行选择性 FTP 下载 ht
  • WPF 数据绑定到复合类模式?

    我是第一次尝试 WPF 并且正在努力解决如何将控件绑定到使用其他对象的组合构建的类 例如 如果我有一个由两个单独的类组成的类 Comp 为了清楚起见 请注意省略的各种元素 class One int first int second cla
  • 重载 (c)begin/(c)end

    我试图超载 c begin c end类的函数 以便能够调用 C 11 基于范围的 for 循环 它在大多数情况下都有效 但我无法理解和解决其中一个问题 for auto const point fProjectData gt getPoi
  • C# 列表通用扩展方法与非通用扩展方法

    这是一个简单的问题 我希望 集合类中有通用和非通用方法 例如List
  • WcfSvcHost 的跨域异常

    对于另一个跨域问题 我深表歉意 我一整天都在与这个问题作斗争 现在已经到了沸腾的地步 我有一个 Silverlight 应用程序项目 SLApp1 一个用于托管 Silverlight SLApp1 Web 的 Web 项目和 WCF 项目
  • C# - 当代表执行异步任务时,我仍然需要 System.Threading 吗?

    由于我可以使用委托执行异步操作 我怀疑在我的应用程序中使用 System Threading 的机会很小 是否存在我无法避免 System Threading 的基本情况 只是我正处于学习阶段 例子 class Program public
  • 两个类可以使用 C++ 互相查看吗?

    所以我有一个 A 类 我想在其中调用一些 B 类函数 所以我包括 b h 但是 在 B 类中 我想调用 A 类函数 如果我包含 a h 它最终会陷入无限循环 对吗 我能做什么呢 仅将成员函数声明放在头文件 h 中 并将成员函数定义放在实现文
  • 实例化类时重写虚拟方法

    我有一个带有一些虚函数的类 让我们假设这是其中之一 public class AClassWhatever protected virtual string DoAThingToAString string inputString retu
  • 复制目录下所有文件

    如何将一个目录中的所有内容复制到另一个目录而不循环遍历每个文件 你不能 两者都不Directory http msdn microsoft com en us library system io directory aspx nor Dir
  • 如何实例化 ODataQueryOptions

    我有一个工作 简化 ODataController用下面的方法 public class MyTypeController ODataController HttpGet EnableQuery ODataRoute myTypes pub
  • 如何在 Android 中使用 C# 生成的 RSA 公钥?

    我想在无法假定 HTTPS 可用的情况下确保 Android 应用程序和 C ASP NET 服务器之间的消息隐私 我想使用 RSA 来加密 Android 设备首次联系服务器时传输的对称密钥 RSA密钥对已在服务器上生成 私钥保存在服务器
  • C# 中的 IPC 机制 - 用法和最佳实践

    不久前我在 Win32 代码中使用了 IPC 临界区 事件和信号量 NET环境下场景如何 是否有任何教程解释所有可用选项以及何时使用以及为什么 微软最近在IPC方面的东西是Windows 通信基础 http en wikipedia org
  • 当文件流没有新数据时如何防止fgets阻塞

    我有一个popen 执行的函数tail f sometextfile 只要文件流中有数据显然我就可以通过fgets 现在 如果没有新数据来自尾部 fgets 挂起 我试过ferror and feof 无济于事 我怎样才能确定fgets 当
  • 指针和内存范围

    我已经用 C 语言编程有一段时间了 但对 C 语言还是很陌生 有时我对 C 处理内存的方式感到困惑 考虑以下有效的 C 代码片段 const char string void where is this pointer variable l
  • 现代编译器是否优化乘以 1 和 -1

    如果我写 template

随机推荐