list模拟实现

2023-05-16

双向链表代码实现:


#pragma once

//双向链表
template<class T>
struct ListNode
{
	T _data;		//当前节点中的数据
	ListNode<T>* _prev;		//当前节点的前一个
	ListNode<T>* _next;		//当前节点的后一个

	ListNode(const T& data)
		: _data(data)
		, _prev(NULL)
		, _next(NULL)
	{}
};

template<class T>
class List
{
	typedef ListNode<T> Node;
public:
	List()		//无参构造函数
		: _head(NULL)
		, _tail(NULL)
		, _size(0)
	{}

	List(const T* arr, size_t size)		//有参构造函数
		: _head(NULL)
		, _tail(NULL)
		, _size(0)
	{
		for (size_t i = 0; i < size; ++i)
		{
			PushBack(arr[i]);
		}
	}

	List(const List<T>& l)		//拷贝构造函数
		: _head(NULL)
		, _tail(NULL)
		, _size(0)
	{
		Node<T>* cur = l._head;
		while (cur)
		{
			PushBack(cur->_data);
			cur = cur->_next;
		}
	}

	List& operator=(const list<T>& l)		//复制运算符重载
	{
		if (Empty())	//对象的链表为空时
		{
			Node* cur = l._head;
			for (size_t i = 0; i < l._size; ++i)
			{
				PushBack(cur->_data);
				cur = cur->_next;
			}
		}
		else if (_size>l._size)		//当被赋值的链表大于要赋值的链表时
		{
			Node* cur = _head;
			Node* lcur = l._head;
			//先将l._size拷贝过去
			for (size_t i = 0; i < l._size; ++i)
			{
				cur->_data = lcur->_data;
				cur = cur->_data;
				lcur = lcur->_data;
			}
			//再将剩余的l._size到_size之间的元素删除
			for (size_t i = l._size; i < _size; ++i)
			{
				PopBack();
				cur = cur->_next;
			}
		}
		else      //_size小于等于l._size拷贝_size个元素过去即可
		{
			Node* cur = _head;
			Node* lcur = l._head;
			for (size_t i = 0; i < _size; ++i)
			{
				cur->_data = lcur->_data;
				cur = cur->_next;
				lcur = lcur->_next;
			}
		}
		return *this;
	}

	~List()			//析构函数
	{
		Clear();
	}

	bool Empty()		//判断链表是否为空
	{
		return _size == 0;
	}

	size_t Size()		//求链表中的元素个数
	{
		return _size;
	}

	T& Front()			//返回第一个元素
	{
		return _head;
	}

	T& Front() const
	{
		return _head;
	}

	T& Back()			//返回最后一个元素
	{
		return _tail;
	}

	T& Back() const
	{
		return _tail;
	}

	void PushBack(const T& data)		//尾插
	{
		if (Empty())		//链表为空时
		{
			Node* cur = BuyNewNode(data);
			_head = _tail = cur;
		}
		else      //链表不为空时
		{
			Node* cur = BuyNewNode(data);
			cur->_prev = _tail;
			_tail->_next = cur;
			_tail = cur;
		}
		++_size;
	}

	void PopBack()					//尾删
	{
		if (Empty())		//链表为空的情况
			return;
		else if (_head->_next == NULL)
		{
			Node* del = _head;
			_head = _tail = NULL;
			delete del;
		}
		else
		{
			Node* del = _tail;
			_tail = _tail->_prev;
			_tail->_next = NULL;
			delete del;
		}
	}

	void PushFront(const T& data)		//头插
	{
		if (Empty())
		{
			Node* cur = BuyNewNode(data);
			_head = _tail = cur;
		}
		else
		{
			Node* cur = BuyNewNode(data);
			cur->_next = _head;
			_head->_prev = cur;
			cur = _head;
		}
	}

	void PopFront()					//头删
	{
		if (Empty())
			return;
		else if (_head->_next = NULL)
		{
			Node* del = _head;
			_head = _tail = NULL;
			delete del;
		}
		else
		{
			Node* del = _head;
			_head = _head->_next;
			_head->_prev = NULL;
			delete del;
		}
		--_size;
	}

	Node* Find(const T& data)		//查找特定元素在链表中的第一次出现位置
	{
		Node* cur = _head;
		while (cur)
		{
			if (cur->_data == data)
				return cur;
			cur = cur->_next;
		}
		return NULL;
	}

	void Insert(Node* pos, const T& data)		//在指定位置插入元素
	{
		assert(pos);
		if (pos->_next == NULL)
		{
			PushBack(data);
		}
		else
		{
			Node* cur = BuyNewNode(data);
			cur->_prev = pos;
			cur->_next = pos->_next;

			pos->_next->_prev = cur;
			pos->_next = cur;
		}
		++_size;
	}

	void Erase(Node* pos)		//删除指定位置的元素
	{
		if (Empty())
			return;
		if (pos == _head)		//如果是头结点
		{
			PopFront();
		}
		else if (pos == _tail)	//如果是尾结点
		{
			PopBack();
		}
		else
		{
			Node* cur = pos;
			Node* prev = cur->_prev;
			Node* next = cur->_next;

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

			delete pos;
		}
		--_size;
	}

	void Clear()		//清空链表
	{
		if (Empty())
			return;
		else
		{
			Node* del = _head;
			Node* cur = _head->_next;
			while (cur->_next)
			{
				cur = cur->_next;
				del = cur->_prev;
				delete del;
			}
			delete cur;
			_tail = NULL;
			del = _head;
			delete del;
			_head = NULL;
			_size = 0;
		}
	}

	void Sort()		//排序
	{
		bool flag = true;
		Node* cur = _head;
		Node* tail = NULL;
		while (cur != tail)
		{
			while (cur->_next != tail)
			{
				if (cur->_data > cur->_next->_data)
				{
					T tmp = cur->_data;
					cur->_data = cur->_next->_data;
					cur->_next->_data = tmp;
					flag = false;
				}
				cur = cur->_next;
			}
			if (flag)
				break;
			tail = cur;
			cur = _head;
		}
	}

	void Remove(const T& data)		//删除第一个值为data的节点
	{
		Node* pos = Find(data);
		if (pos)
		{
			if (pos == _head)
			{
				PopFront();
			}
			else if (pos == _tail)
			{
				PopBack();
			}
			else
			{
				Erase(pos);
			}
		}
	}

	void Print()		//打印链表
	{
		if (Empty())
			return;
		Node* cur = _head;
		while (cur)
		{
			cout << cur->_data << " ";
			cur = cur->_next;
		}
		cout << endl;
	}

	void ReversePrint()			//逆序打印
	{
		if (Empty())
		{
			return;
		}
		Node* cur = _tail;
		while (cur)
		{
			cout << cur->_data << " ";
			cur = cur->_prev;
		}
		cout << endl;
	}

protected:
	Node* BuyNewNode(const T& data)
	{
		Node* tmp = new Node(data);
		return tmp;
	}

protected:
	Node* _head;
	Node* _tail;
	size_t _size;
};


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

list模拟实现 的相关文章

  • 比较和删除列表和数组java中不存在的元素

    我有一个String数组和一List
  • Python - 如何将列表保存为图像?

    我生成一个常规列表 是否可以将此列表保存为 JPEG 图像或 PNG 或其他格式 以便我可以打开图像并查看它 我目前正在尝试使用 python 成像库 PIL 来解决这个问题 这是可能的解决方案之一 使用以下方法创建一个空图像对象 Imag
  • 在Python中将整数附加到列表的开头[重复]

    这个问题在这里已经有答案了 如何在列表的开头添加一个整数 1 2 3 42 1 2 3 gt gt gt x 42 gt gt gt xs 1 2 3 gt gt gt xs insert 0 x gt gt gt xs 42 1 2 3
  • 如何按字段对列表进行排序

    美好的一天 4 你们大家 我有一个对象列表 我的对象喜欢 Product iPhone Category SmartPhone Product HP Category PC Product HTC Category SmartPhone 我
  • Python选择列表中最长字符串的最有效方法?

    我有一个可变长度的列表 并且正在尝试找到一种方法来测试当前正在评估的列表项是否是列表中包含的最长字符串 我正在使用Python 2 6 1 例如 mylist abc abcdef abcd for each in mylist if co
  • 省略号列表[...]并将列表连接到自身[重复]

    这个问题在这里已经有答案了 EDIT 我在最初的例子中很粗心 当我添加列表时不会发生该行为A本身 而是当我添加一个列表时含有 list A to A本身 请参阅下面更正的示例 我试图理解省略号如何列出 那些显示为 当你有一个列表引用本身时发
  • 在 any() 语句中迭代一个小列表是否更快?

    在低长度迭代的限制下考虑以下操作 d 3 slice None None None slice None None None In 215 timeit any type i slice for i in d 1000000 loops b
  • 如何在 Haskell 中向右或向左移动列表的 1 个元素?

    嗨 我一直在寻找答案 但找不到 假设我们有一个像这样的列表 1 10 4 5 3 我怎样才能将 5 向左移动 使这个列表变成 1 10 5 4 3 我尝试过了swapElementsAt通过找到该元素的索引 但它看起来非常不足 swapEl
  • 如何在 Python 中连接两个列表?

    这个问题的答案是社区努力 help privileges edit community wiki 编辑现有答案以改进这篇文章 目前不接受新的答案或互动 如何在 Python 中连接两个列表 Example listone 1 2 3 lis
  • 在不同进程之间共享列表?

    我有以下问题 我编写了一个函数 它将列表作为输入 并为列表中的每个元素创建一个字典 然后我想将这本字典附加到一个新列表中 这样我就得到了一个字典列表 我正在尝试为此生成多个进程 我的问题是 我希望不同的进程访问由其他进程更新的字典列表 例如
  • 如何在 switch 语句中将向量作为参数传递

    我对问题的谷歌搜索没有返回有用的结果和文档 switch没有告诉我如何做 所以我希望我能在这里得到答案 假设我有一个向量 cases lt c one two three 我想使用 switch 语句并将这些元素作为 switch 语句的参
  • Python range() 和 zip() 对象类型

    我了解功能如何range and zip 可以在 for 循环中使用 然而我期望range 输出一个列表 很像seq在 Unix shell 中 如果我运行以下代码 a range 10 print a 输出是range 10 表明它不是一
  • 属性错误:“列表”对象没有属性“拆分”

    我正在尝试读取一个文件并用逗号分隔每行中的一个单元格 然后仅显示第一个和第二个单元格 其中包含有关纬度和经度的信息 这是文件 time 纬度 经度 类型2015 03 20T10 20 35 890Z 38 8221664 122 7649
  • Python 将列表追加到列表中

    我正在尝试编写一个通过矩阵的函数 当满足条件时 它会记住该位置 我从一个空列表开始 locations 当函数遍历行时 我使用以下方法附加坐标 locations append x locations append y 函数末尾的列表如下所
  • 在 Haskell 中合并两个列表

    无法弄清楚如何合并两个列表通过以下方式在哈斯克尔 INPUT 1 2 3 4 5 11 12 13 14 OUTPUT 1 11 2 12 3 13 4 14 5 我想提出一个更懒的合并版本 merge ys ys merge x xs y
  • 如何在 R 中合并同名列表中的数据框?

    我有一个包含很多数据框的列表 如果它们具有相同的名称 我想合并它们 即合并所有具有相同名称 a 和 b 的数据框 像这样 a lt aaaaa b lt bbbbb c lt ccccc g lt list df1 lt data fram
  • 需要在R中按行绑定列表数据

    我在 R 中按行绑定列表时遇到问题 我的列表数据集是 id 1 data k 1 id k b c 1 1 1 3 data k 2 id k b c 1 2 1 4 id 2 data k 1 id k b c 2 1 1 6 data
  • 当顺序很重要时如何从元组列表中删除重复项

    我看过一些类似的答案 但我找不到针对这种情况的具体内容 我有一个元组列表 5 0 3 1 3 2 5 3 6 4 我想要的是仅当元组的第一个元素先前出现在列表中并且剩余的元组应该具有最小的第二个元素时 才从该列表中删除元组 所以输出应该是这
  • Prim 的迷宫生成算法:获取相邻单元格

    我基于 Prim 算法编写了一个迷宫生成器程序 该算法是 Prim 算法的随机版本 从充满墙壁的网格开始 选择一个单元格 将其标记为迷宫的一部分 将单元格的墙壁添加到墙壁列表中 While there are walls in the li
  • python中有没有一种方法可以将存储在列表中的正则表达式模式列表应用到单个字符串?

    我有一个正则表达式模式列表 存储在列表类型中 我想将其应用于字符串 有谁知道一个好方法 将列表中的每个正则表达式模式应用于字符串 和 如果匹配 则调用与列表中该模式关联的不同函数 如果可能的话我想用 python 来做这件事 提前致谢 im

随机推荐

  • 模板&仿函数的应用--冒泡排序

    普通版冒泡排序 对于冒泡排序的算法大家并不陌生 xff0c 将相临两个数一次比较 xff0c 然后将最大值或者最小值先排出来 xff0c 一般来说这样的话我们需要在碗面写两个函数来分别实现这两个算法 xff0c 程序代码如下 xff1a s
  • String类模拟

    span style font size 24px class String friend ostream amp operator lt lt ostream amp os String amp s 输出运算符重载 friend istr
  • win10主机ping不通win10虚拟机

    原因是ICMP回显请求规则未开启 xff0c 解决方法在文章末尾 环境说明 win10虚拟机 192 168 136 136 win10虚拟机采用的网络连接是 NAT 模式 ipconfig结果如下 xff1a 以太网适配器 Etherne
  • <操作系统> 理发店问题(选做)C语言实现

    问题描述 xff1a 代码 xff1a span class token macro property span class token directive keyword include span span class token str
  • 特殊矩阵的压缩存储及转置

    一 对称矩阵及其压缩存储 1 对称矩阵 在矩阵中最特殊的一类应该属于对称矩阵 xff0c 对称矩阵的行和列是对应相等的 对称矩阵就是关于主对角线对称 xff0c 两边的元素的值对应相等 xff0c 在数学中我们把用主对角线隔开 xff0c
  • STL浅析set&map

    map和set的底层实现原理和接口使用 1 set和map的底层实现 set和map属于STL中的一种关联式容器 xff0c 底层实现是红黑树 2 set容器的特点 1 set和map 容器中的元素自动进行有序排列 默认为升序排列 xff1
  • Linux下的文件操作权限

    Linux下进入一个目录需要什么权限 xff1f 普通用户下 xff1a 首先我们在普通用户下 xff0c 取消文件code的所有权限chmod 000 code 当我们执行cd code 想进入当前目录时 xff0c 发现权限不允许 接下
  • linux下的常见命令

    cd change directory 进入个人的主目录 cd home 进入 39 home 39 目录 39 cd 返回上一级目录 cd 返回上两级目录 cd 返回上次所在的目录 ls list 查看目录中的文件 ls l 显示文件和目
  • task_struct结构体成员小结

    背景知识 task stuct结构体 被称为进程描述符 xff0c 用 来管理进程Linux内核的进程 xff0c 这个结构体包含了一个进程所需的所有信息 它定义在 include linux sched h文件中 可以说它是linux内核
  • Linux下的简单进度条实现

    进度条 计算机在处理任务时 xff0c 实时的 xff0c 以图片形式显示处理任务的速度 xff0c 完成度 xff0c 剩余未完成任务量的大小 xff0c 和可能需要处理时间 xff0c 一般以长方形条状显示 主要功能 xff1a 1 显
  • 九大排序之——希尔排序

    希尔排序 xff1a 思想 xff1a 希尔排序是为了防止直接插入排序出现最坏情况所做的一种改进 xff0c 将原本的排序过程分为预排序和直接插入排序两个阶段 预排序阶段 xff1a 将整个预排序的序列分为若干个待排序的子序列 xff0c
  • 僵尸进程与孤儿进程模拟实现

    背景知识 僵尸进程 xff08 Zombies xff09 xff1a 1 僵尸进程是一个比较特殊的状态 xff0c 当进程退出父进程 xff08 使用wait 系统调用 xff09 没有没有读取到子进程退出的返回代码时就会产生僵尸进程 僵
  • 队列模拟实现

    队列的特点 xff1a 先进先出 后进后出 队列的常见操作 xff1a Push 往队尾插入一个元素 Pop 从队头删除一个元素 Front 返回队列的第一个元素 Back 返回队列的最后一个元素 Size 求队列的元素个数 Empty 判
  • ssh端口转发(之kettle ssh方式连接数据库)

    ssh参数解释 格式 ssh user 64 host command 选项 xff1a 1 xff1a 强制使用ssh协议版本1 xff1b 2 xff1a 强制使用ssh协议版本2 xff1b 4 xff1a 强制使用IPv4地址 xf
  • str库函数模拟实现

    常见str函数功能表 xff1a strcat 将字符串str2连接到str1之后 xff0c 并返回指针str1 strncat 将字符串from 中至多count个字符连接到字符串to中 xff0c 追加空值结束符 返回处理完成的字符串
  • min栈实现

    题目 xff1a 实现一个栈 xff0c 要求实现Push xff08 出栈 xff09 Pop xff08 入栈 xff09 Min xff08 返回最小值的操作 xff09 的时间复杂度为O 1 分析 xff1a 这道题目的主要难点在于
  • 栈实现队列&&队列实现栈

    背景知识 xff1a 动态栈的模拟实现 xff1a http blog csdn net double happiness article details 70170984 队列的模拟实现 xff1a http blog csdn net
  • 一个数组实现两个栈

    分析 xff1a 用一个数组实现两个栈有三种思路 xff1a xff08 1 xff09 将数组按照奇 偶为分成两组 xff08 2 xff09 将数组按照从两边到中间分成两组 xff08 3 xff09 将数组按照从中间到两边分成两组 比
  • 栈的压入弹出序列

    题目描述 xff1a 判断一个栈的输出序列是否是正确的 xff0c 时间复杂度要求O N 示例 xff1a 输入栈 xff1a 1 2 3 4 5 1 输出栈 xff1a 4 5 3 2 1 2 输出栈 xff1a 4 3 5 1 2 分析
  • list模拟实现

    双向链表代码实现 xff1a span style font size 24px pragma once 双向链表 template lt class T gt struct ListNode T data 当前节点中的数据 ListNod