【全CSDN最详细----C++数据结构】StaticList和DynamicList的实现


前言

在C++数据结构中,StaticList(静态链表)和DynamicList(动态链表)是两种常见的数据结构,它们在不同的场景中有着各自的优势和应用。链表是一种基础的数据结构,通过节点之间的指针连接实现数据的存储和访问。StaticList使用静态数组实现,预先分配了固定大小的存储空间,而DynamicList则采用动态内存分配,可以动态调整大小以适应实际需求。

静态链表具有固定大小的优势,这在一些场景中是非常有用的,特别是当我们对链表的最大长度有明确的预期时。这种实现方式避免了频繁的内存分配和释放操作,提高了空间利用率。然而,静态链表的缺点是一旦达到了最大长度,就无法再插入新的元素。

相比之下,动态链表的长度可以根据实际需求动态调整,这使得它更加灵活。动态链表可以在运行时动态分配和释放内存,适应不同规模的数据。但需要注意的是,动态链表的实现通常涉及到更多的内存管理细节,需要及时释放不再使用的内存,以避免内存泄漏。


一、StaticList

1.1 实现思路

我们首先来看一下我们的上个博客写的SeqList

template <typename T>
class SeqList :public List<T>
{
protected:
    T* m_array;
    int m_length;

public:
    //...
}

在这里插入图片描述

他使用指针来操作内存,但是我们在SeqList有没有申请对应的内存呢?
没有,那么我们应该让这个指针指向哪呢?
指向原生数组啊。
原生数组既符合我们顺序表

所以我们需要在StaticList指定大小的array

template <typename T,int N>
class StaticList :public SeqList<T>
{
protected:
	T m_space[N];
}

在这里插入图片描述

我们可以使用类模板先指定静态List的大小

1.2 具体实现

定义存储的数组

我们在上面的实现思路已经介绍了,直接使用原生数组即可,原始数组非常适合我们的顺序表的一个规则。

template <typename T,int N>
class StaticList :public SeqList<T>
{
protected:
	T m_space[N];
}

在这里插入图片描述

实现构造函数

我们可以看到下面我们的SeqList,我们的m_array和m_length都没有进行赋值,所以我们需要在子类的构造函数中赋值他!

template <typename T>
class SeqList :public List<T>
{
protected:
    T* m_array;
    int m_length;
}

在这里插入图片描述

那么如何实现呢?
我们把m_array 指向 具体的空间m_space
然后,我们的长度一开始是0,所以m_length=0即可

StaticList()
{
	this->m_array = m_space;
	this->m_length = 0;
}

在这里插入图片描述

实现capacity函数

那么为什么需要实现capacity这个函数呢?

template <typename T>
class SeqList :public List<T>
{
//...

    virtual int capacity() const = 0;
};

可以看到我们的父类SeqList没有实现capacity函数,而且他又是纯虚函数,所以我们需要在子类中实现他

那么在我们这个StaticList的类模板是这样的:

template <typename T,int N>

第二个就是数组的大小,或者说最大个数。
所以这不正合意吗。我们的capacity函数直接放回N不就好啦。

int capacity()const
{
	return N;
}

在这里插入图片描述

二、DynamicList的实现

2.1 思路

DynamicList是动态申请内存空间的所以我们就不需要用模板来指定内存空间大小了,
那么要动态申请,就要请出我们的new来了
那么既然是动态申请,所以我们的capacity是动态变化的,所以需要定义一个变量来记录他。

template <typename T>
class DynamicList :public SeqList<T>
{
protected:
	int m_capacity;
public:
	//...
}

我们可以抽象出上面这个DynamicList

2.2 构造函数实现

我们需要通过参数来指定我们数组的大小,所以需要一个int类型,接下来,我们需要new申请参数大的内存this->m_array = new T[capacity];就像这样。

接下来,为了安全,我们需要判断是否为空,是否没有内存了,申请不到了,如果申请不到,则需要抛出异常

if (this->m_array != nullptr)
{
	
}
else
	THROW_EXCEPTION(NoEnoughMemoryException, "No memory to create DynamicList object...");

最后,我们需要把父类的成员附上值

DynamicList(int capacity)
{
	this->m_array = new T[capacity];
	if (this->m_array != nullptr)
	{
		this->m_length = 0;
		this->m_capacity = capacity;
	}
	else
		THROW_EXCEPTION(NoEnoughMemoryException, "No memory to create DynamicList object...");
}

在这里插入图片描述

2.3 resize函数实现

思路

其实他就是一个申请指定大小的数组把原数组的元素放进去的过程而已
其中,申请指定大小的数组可能是大于原数组和小于原数组,
那么我们就需要确定到底是可以把原数组的全部放进去,还是放一部分

我们可以像下面这样做:

int length = this->m_length < capacity ? this->m_length : capacity;

具体代码实现

1、判断要申请的大小是否和现在的大小一样,如果一样那就没必要申请是吧:

void resize(int capacity)
{
	if (capacity != m_capacity)
	{
		
	}
}

在这里插入图片描述

2、如果不相等则申请新的数组,而且,如果申请失败,我们还要抛出异常

T* array = new T[capacity];

if (array != nullptr)
{
	
}
else
	THROW_EXCEPTION(NoEnoughMemoryException, "No memory to resize DynamicList object...");

在这里插入图片描述

3、申请指定大小的数组可能是大于原数组和小于原数组,
那么我们就需要确定到底是可以把原数组的全部放进去,还是放一部分

int length = this->m_length < capacity ? this->m_length : capacity;

在这里插入图片描述

4、把原数组的length个元素移动复制到新数组中

for (int i = 0; i < length; i++)
{
	array[i] = this->m_array[i];
}

在这里插入图片描述

5、把指针指向新申请数组,并且把成员复制成新的

T* temp = this->m_array;
this->m_array = array;

this->m_length = length;
this->capacity = capacity;

delete[] temp;

在这里插入图片描述

为什么需要使用temp存起m_array呢
因为当后面m_array指向新数组之后,这个m_array的原来内存不就没人管了?
所以需要这样,把原理的数组删除掉

2.5 capacity函数

那么最后就是我们最简单的capacity函数了
废话不多说,直接上代码:

int capacity()const
{
	return m_capacity;
}

在这里插入图片描述

2.6 析构函数

因为我们的m_array是动态申请的内存,所以我们需要手动释放,要不然就会内存泄露了

~DynamicList()
{
	delete[] this->m_array;
}

在这里插入图片描述


总结

StaticList和DynamicList都是链表的变种,各自适用于不同的场景。在选择使用哪种链表实现时,我们需要考虑数据规模的可预测性、内存管理的复杂性以及对性能的要求。StaticList适用于对链表长度有明确预期的情况,而DynamicList更适合处理不断变化的数据规模。在实际应用中,合理选择和使用这两种链表,可以更好地满足程序的需求,提高代码的效率和可维护性。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

人才程序员

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值