數據結構--動態數組

動態數組

總體表述

開發過程,經常需要對數據集合進行維護。
維護數據結合的數據結構可統稱爲容器。
動態數組是維護數據集合的容器的一種,
具備數組操作簡單的特點,但允許集合內元素的動態增加和刪除。

接口設計

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)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章