数据结构--动态数组

动态数组

总体表述

开发过程,经常需要对数据集合进行维护。
维护数据结合的数据结构可统称为容器。
动态数组是维护数据集合的容器的一种,
具备数组操作简单的特点,但允许集合内元素的动态增加和删除。

接口设计

template<typename T>
class DynArray
{
public:
	DynArray();
	DynArray(int nInitialSize_, const T& nInitialValue_);
	~DynArray();

	void Add(const T& value_);
	void AddRange(const DynArray& arrItems_);
	void Insert(int nIndex_, const T& value_);
	void DeleteByIndex(int nIndex_ = -1);
	void DeleteByValue(const T& value_);
	void DeleteAll();
	bool SetValue(int nIndex_, const T& value_);
	bool GetValue(int nIndex_, T& value_) const;

	int GetSize() const;
	int GetCapacity() const;
	int Find(std::function<bool(const T&)> fun_) const;

	T& operator[](int nIndex_);
	const T& operator[](int nIndex_) const;
	DynArray(const DynArray<T>& arrElements_);
	DynArray<T>& operator=(const DynArray<T>& arrElements_);
	DynArray Sort(std::function<int(const T&, const T&)> fun_) const;
	void Sort(std::function<int(const T&, const T&)> fun_);

	void Reset();
private:
	void Check(int nSize_);
	void Shrink();

private:
	T* m_pSource;// 当T为引用类型时,sizeof无法获得其真实大小
	int m_nSize;
	int m_nCapacity;

	std::allocator<T> m_alloc;
};

实现

构造

template<typename T>
DynArray<T>::DynArray()
	:m_pSource(nullptr), m_nSize(0), m_nCapacity(0)
{
	m_pSource = m_alloc.allocate(100);
	if (m_pSource == nullptr)
	{
		throw "out of memory";
	}
	else
	{
		m_nSize = 0;
		m_nCapacity = 100;
	}
}

拷贝构造

template<typename T>
DynArray<T>::DynArray(const DynArray<T>& arrElements_)
	: m_pSource(nullptr), m_nSize(0), m_nCapacity(0)
{
	m_pSource = m_alloc.allocate(arrElements_.m_nCapacity);
	if (m_pSource == nullptr)
	{
		throw "out of memory";
	}
	else
	{
		m_nSize = arrElements_.m_nSize;
		m_nCapacity = arrElements_.m_nCapacity;
		std::uninitialized_copy_n(arrElements_.m_pSource, arrElements_.m_nSize, m_pSource);
	}
}

赋值

template<typename T>
DynArray<T>& DynArray<T>::operator=(const DynArray<T>& arrElements_)
{
	if (&arrElements_ == this)
	{
		return *this;
	}

	this->~DynArray();
	m_pSource = m_alloc.allocate(arrElements_.m_nCapacity);
	if (m_pSource == nullptr)
	{
		throw "out of memory";
	}
	else
	{
		m_nSize = arrElements_.m_nSize;
		m_nCapacity = arrElements_.m_nCapacity;
		std::uninitialized_copy_n(arrElements_.m_pSource, arrElements_.m_nSize, m_pSource);
	}
}

析构

template<typename T>
DynArray<T>::~DynArray()
{
	if (m_pSource == nullptr)
	{
		return;
	}

	T* _pEnd = m_pSource + m_nSize;
	while (_pEnd != m_pSource)
	{
		m_alloc.destroy(--_pEnd);
	}

	// 内存释放
	m_alloc.deallocate(m_pSource, m_nCapacity);
	m_pSource = nullptr;
	m_nSize = 0;
	m_nCapacity = 0;
	m_pSource = m_alloc.allocate(100);
	if (m_pSource == nullptr)
	{
		throw "out of memory";
	}
	else
	{
		m_nSize = 0;
		m_nCapacity = 100;
	}
}

插入

template<typename T>
void DynArray<T>::Insert(int nIndex_, const T& value_)
{
	if (nIndex_ > m_nSize)
	{
		throw "Insert position error";
	}

	Check(m_nSize + 1);
	m_alloc.construct(m_pSource + m_nSize, value_);
	m_nSize++;

	for (int _i = m_nSize - 1; _i >= nIndex_; _i--)
	{
		*(m_pSource + _i + 1) = *(m_pSource + _i);
	}

	*(m_pSource + nIndex_) = value_;
}

删除

template<typename T>
void DynArray<T>::DeleteByIndex(int nIndex_)
{
	if (nIndex_ < 0
		|| nIndex_ >= m_nSize)
	{
		return;
	}

	// 前移
	for (int _i = nIndex_ + 1; _i < m_nSize; _i++)
	{
		*(m_pSource + _i - 1) = *(m_pSource + _i);
	}

	m_alloc.destroy(m_pSource + m_nSize);
	m_nSize--;
	if (m_nSize <= m_nCapacity / 4)
	{
		Shrink();
	}
}

查找

template<typename T>
int DynArray<T>::Find(std::function<bool(const T&)> fun_) const
{
	int _nPosIndex = -1;
	for (int _i = 0; _i < m_nSize; _i++)
	{
		if (fun_(*(m_pSource + _i)))
		{
			_nPosIndex = _i;
			break;
		}
	}

	return _nPosIndex;
}

索引

template<typename T>
T& DynArray<T>::operator[](int nIndex_)
{
	if (nIndex_ < 0
		|| nIndex_ >= m_nSize)
	{
		throw "index is error";
	}

	return *(m_pSource + nIndex_);
}

排序

template<typename T>
void DynArray<T>::Sort(std::function<int(const T&, const T&)> fun_)
{
	if (m_nSize <= 1)
	{
		return;
	}

	Algorithm::Sort::Helper::QuickSort<T>(m_pSource,
		m_pSource + m_nSize,
		fun_);
		return;
}

动态增大

template<typename T>
void DynArray<T>::Check(int nSize_)
{
	if (m_nCapacity >= nSize_)
	{
		return;
	}

	int _nSize = m_nSize;
	int _nCapacity = nSize_ * 2;
	T* _pSource = m_alloc.allocate(_nCapacity);
	if (_pSource == nullptr)
	{
		throw "out of memory";
	}
	else
	{
		std::uninitialized_copy_n(m_pSource, m_nSize, _pSource);
		this->~DynArray();
		m_pSource = _pSource;
		m_nSize = _nSize;
		m_nCapacity = _nCapacity;
	}
}

动态减小

template<typename T>
void DynArray<T>::Shrink()
{
	int _nSize = m_nSize;
	int _nCapacity = (m_nCapacity / 2) > 100 ? (m_nCapacity / 2) : 100;
	T* _pSource = m_alloc.allocate(_nCapacity);
	if (_pSource == nullptr)
	{
		throw "out of memory";
	}
	else
	{
		std::uninitialized_copy_n(m_pSource, m_nSize, _pSource);
		this->~DynArray();
		m_pSource = _pSource;
		m_nSize = _nSize;
		m_nCapacity = _nCapacity;
	}
}

时间复杂度

以下分析皆假设数组内元素个数为n

构造

时间复杂度Θ(1)

拷贝构造

时间复杂度Θ(n)

赋值

时间复杂度Θ(n)

析构

时间复杂度Θ(n)

插入

最坏下Θ(n)

删除

最坏下Θ(n)

搜索

最坏下Θ(n)

位置索引

时间复杂度Θ(1)

排序

时间复杂度Θ(nlg(n))

动态增大

时间复杂度Θ(n)

动态收缩

时间复杂度Θ(n)
发布了117 篇原创文章 · 获赞 84 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/x13262608581/article/details/105318846