C++实现单链表

#pragma once
#include <cstdint>
#include <memory>
#include <stdexcept>
#include <functional>

template <typename T>
class List
{
public:
	//无参构造函数
	explicit List();
	//拷贝构造函数
	List(const List& other);
	//移动构造函数
	List(List&& other);
	//虚析构器  确保子类对象删除
	virtual ~List();

public:
	//添加元素 data
	void push_back(const T& data);
	//删除末尾元素
	void pop_back();
	//释放内存
	void clear();
	//返回指定索引的值
	T& at(size_t index);
	//返回指定索引的值    只读操作
	const T& at(size_t index) const;
	//列表中元素的数量
	size_t size() const;

public:
	//返回两个元素是否相等
	bool operator==(const List<T>& other);
	//返回两个元素是否不相等
	bool operator!=(const List<T>& other);
	//赋值:将另一个List对象赋值给当前对象
	List<T>& operator=(const List<T>& other);
	//加:两个List相加 返回一个新的List对象 
	List<T>& operator+(const List<T>& other);
	//[]:返回指定索引的值
	T& operator[](size_t index);
	const T& operator[](size_t index)const;

private:
	//指向列表数据的指针
	T* datas;
	//存储的数量
	int64_t data_size;
};
//赋值 nullptr   元素数量0
template<typename T>
inline List<T>::List()
	: datas(nullptr), data_size(0)
{

}
//拷贝构造:
template<typename T>
inline List<T>::List(const List& other)
{
	//清空List的数据
	clear();
	//获取other列表中元素数量
	data_size = other.data_size;
	//申请内存 datas = new T[data_size];
	datas = (T*)malloc(sizeof(T) * data_size);
	//复制到新的列表中
	for (size_t i = 0; i < data_size; ++i)
	{
		datas[i] = other.datas[i];
	}
}
//移动构造
template<typename T>
inline List<T>::List(List&& other)
{
	//other的指针
	datas = other.datas;
	//other的元素数量给data_size
	data_size = other.data_size;
	//赋空值
	other.datas = nullptr;
	other.data_size = 0;
}
//释放内存
template<typename T>
inline List<T>::~List()
{
	clear();
}
//添加元素
template<typename T>
inline void List<T>::push_back(const T& data)
{
	//datas指向的内存块有数据存在
	if (datas != nullptr)
	{
		//重新分配内存以容纳新的元素
		T* tmp_ptr = (T*)realloc(datas, sizeof(T) * (data_size + 1));
		if (tmp_ptr)
		{
			//更新内存指针,指向新的内存块
			datas = tmp_ptr;
			//定位到新分配内存的位置
			T& tmp_data = *(datas + data_size);
			//将data拷贝到这个位置上
			new(&tmp_data) T(data);
		}
	}
	//第一次插入数据
	else
	{
		//分配内存
		datas = (T*)malloc(sizeof(T));
		//将data拷贝到这个位置上
		new(datas) T(data);
	}
	//元素个数+1
	++data_size;
}
//删除
template<typename T>
inline void List<T>::pop_back()
{
	//没有元素
	if (data_size == 0)
	{
		return;
	}
	//元素为1
	else if (data_size == 1)
	{
		//调用析构器销毁最后一个元素   使用malloc  和 realloc  动态分配内存  手动释放
		datas->~T();
		//释放分配给datas的内存
		free(datas);
		datas = nullptr;
		//元素个数-1
		--data_size;
	}
	//元素大于1
	else if (data_size > 1)
	{
		//调用析构器销毁最后一个元素
		datas[data_size - 1]->~T();
		//使用realloc减少datas指针指向的内存块大小  将其缩小为原来的data_size-1
		T* tmp_ptr = (T*)realloc(datas, sizeof(T) * (data_size - 1));
		//如果成功  将指针datas指向新的内存块
		if (tmp_ptr) datas = tmp_ptr;
		--data_size;
	}
}
//释放内存
template<typename T>
inline void List<T>::clear()
{
	if (datas)
	{
		free(datas);
		datas = nullptr;
		data_size = 0;
	}
}
//返回指定索引的值
template<typename T>
inline T& List<T>::at(size_t index)
{
	//索引超出范围  抛出异常
	if (index >= data_size)
		throw std::runtime_error("栈溢出");

	return datas[index];
}

template<typename T>
inline const T& List<T>::at(size_t index) const
{
	if (index >= data_size)
		throw std::runtime_error("栈溢出");

	return datas[index];
}

//元素数量
template<typename T>
inline size_t List<T>::size() const
{
	return data_size;
}
//返回两个List是否相等
template<typename T>
inline bool List<T>::operator==(const List<T>& other)
{
	//判断List的长度是否相等
	if (data_size != other.data_size) return false;
	//判断每个元素是否相等
	for (size_t i = 0; i < data_size; ++i)
	{
		if (datas[i] != other.datas[i])
			return false;
	}
	return true;
}
//返回两个List是否不相等
template<typename T>
inline bool List<T>::operator!=(const List<T>& other)
{
	return !operator==(other);
}
//赋值:将另一个List对象赋值给当前对象
template<typename T>
inline List<T>& List<T>::operator=(const List<T>& other)
{
	//清空List
	clear();
	//获取other元素数量
	data_size = other.data_size;
	//分配内存
	datas = (T*)malloc(sizeof(T) * data_size);
	//将other的数据复制给datas
	for (size_t i = 0; i < data_size; ++i)
	{
		datas[i] = other.datas[i];
	}
	//返回当前对象的引用
	return *this;
}
//两个链表相加
template<typename T>
inline List<T>& List<T>::operator+(const List<T>& other)
{
	//result指向当前对象
	List<T>& result = *this;
	//不执行
	while (true)
	{
		//other是否为空
		if (other.data_size == 0 || other.datas == nullptr)
			break;
		//分配内存:内存大小:data_size + other.data_size
		T* tmp_ptr = (T*)realloc(datas, data_size + other.data_size);
		if (!tmp_ptr)
			break;
		//datas指向新分配的内存
		datas = tmp_ptr;
		//将other List中的数据追加到当前的List的末尾
		for (size_t i = 0; i < other.data_size; ++i)
		{
			datas[data_size + i] = other.datas[i];
		}
		data_size += other.data_size;
	}

	return result;
}
//重载[]:访问List中的数据
template<typename T>
inline T& List<T>::operator[](size_t index)
{
	if (index >= data_size)
		throw std::runtime_error("栈溢出");

	return datas[index];
}

template<typename T>
inline const T& List<T>::operator[](size_t index) const
{
	if (index >= data_size)
		throw std::runtime_error("栈溢出");

	return datas[index];
}
#include <iostream>

#include "List.hpp"
#include <string>

int main(int argc, char* argv[])
{
	//创建test_list_1对象
	List<std::string> test_list_1;
	//添加元素
	test_list_1.push_back("abc");
	test_list_1.push_back("def");
	test_list_1.push_back("123");

	for (size_t i = 0; i < test_list_1.size(); ++i)
	{
		//通过[]访问元素
		std::string& str = test_list_1[i];
		std::cout << str << std::endl;
	}
	//创建test_list_2对象
	List<int> test_list_2;
	//添加元素
	test_list_2.push_back(1);
	test_list_2.push_back(2);
	test_list_2.push_back(3);

	for (size_t i = 0; i < test_list_2.size(); ++i)
	{
		//通过[]访问元素
		int& num = test_list_2[i];
		std::cout << num << std::endl;
	}

	return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值