【仿STL实现变长数组】( Iterator | Allocator | 动态扩容)

#include <iostream>
#include <sstream>

#include <stdexcept>
#include <exception>

#include <algorithm>
#include <iterator>
#include <type_traits>

#include <cstdint>
#include <cstddef>
#include <assert.h>

template<typename T> class arrayList;
template <typename value_type>
bool operator<( const arrayList<value_type>& lhs,
			     const arrayList<value_type>& rhs){
	register int i;
	for(i = 0; i < std::min( lhs.listSize, rhs.listSize ); ++i)
		if( !( *( lhs.elements + i ) == *(rhs.elements + i) ) )
			return *( lhs.elements + i) < *(rhs.elements + i);
	return lhs.listSize < rhs.listSize;
}

template <typename value_type>
bool operator==( const arrayList<value_type>& lhs,
			     const arrayList<value_type>& rhs){
	if( !( lhs.listSize == rhs.listSize ) ) return false;
	register int i;
	for(i = 0; i < lhs.listSize; ++i)
		if( !( *( lhs.elements + i ) == *(rhs.elements + i) ) )
			return false;
	return true;
}

template <typename value_type>
bool operator!=( const arrayList<value_type>& lhs,
			     const arrayList<value_type>& rhs){
	return !( lhs == rhs );
}

template < typename T >
std::ostream& operator<<( std::ostream& os, const arrayList< T >& x){
	x.output( os );
	return os;
}

template < class T > class linearList{
public:
	virtual ~linearList( void ) {};
	virtual bool empty( void ) const = 0;
	virtual std::size_t size( void ) const = 0;
	virtual T& get( int theIndex ) const = 0;
	virtual int indexOf( const T& theElement ) const = 0;
	virtual void erase( int theIndex ) = 0;
	virtual void insert( int theIndex, const T& theElement ) = 0;
	virtual void output( std::ostream& os ) const = 0;
};

template <class T> class arrayList
	: public linearList< T >{
		friend bool operator==<T>( const arrayList<T>&,
					     const arrayList<T>&);
		friend bool operator< <T>( const arrayList<T>&,
					     const arrayList<T>&);
		friend bool operator!=<T>( const arrayList<T>&,
					     const arrayList<T>&);
		friend std::ostream& operator<< <T>( std::ostream&,
					     const arrayList<T>&);
class iterator{
	public:
		typedef std::bidirectional_iterator_tag iterator_category;
		typedef T value_type;
		typedef std::ptrdiff_t difference_type;
		typedef value_type* pointer;
		typedef value_type& reference;

		iterator(pointer thePosition = nullptr) : position( thePosition ) {}

		reference operator*( void ) const { return *position; }
		pointer operator->( void ) const { return &(*position); }

		iterator& operator++( void ) {
			++position;
			return *this;
		}
		iterator& operator--( void ){
			--position;
			return *this;
		}
		iterator operator++( int dummy ){
			iterator tmp = *this;
			++position;
			return tmp;
		}
		iterator operator--( int dummy ){
					iterator tmp = *this;
					--position;
					return tmp;
		}

		bool operator!=( const iterator rhs ) const{
			return position != rhs.position;
		}
		bool operator==( const iterator rhs ) const{
					return position == rhs.position;
		}
	protected:
		pointer position;
};
public:
	arrayList(int initialCapacity = 10, std::size_t Scaler = 2);
	arrayList( const arrayList< T >&);
	~arrayList( void ){
		if(elements) delete[]elements;
		elements = nullptr;
	}
	virtual bool empty( void ) const { return listSize == 0; }
	virtual std::size_t size( void ) const { return listSize; }
	virtual T& get( int theIndex ) const;
	virtual int indexOf( const T& theElement ) const;
	virtual void erase( int theIndex );
	virtual void insert( int theIndex, const T& theElement );
	virtual void output( std::ostream& os ) const;
	
	T& operator[]( std::size_t position ) const;

	std::size_t capacity( void ) const { return arrayLength; }

	iterator begin( void ){ return iterator( elements ); }
	iterator end( void ){ return iterator( elements + listSize ); }
	
	inline void trimToSize( void );
	void setSize( std::size_t _Size );
	
protected:
	void checkIndex(int theIndex) const;
	T* elements { nullptr };
	std::size_t arrayLength { 10 };
	std::size_t listSize { 0 };
	uint8_t Scaler;
};

template < class T >
void arrayList< T >::checkIndex( int theIndex ) const{
	if( theIndex < 0 || theIndex >= listSize ){
		std::ostringstream oss;
		char buf[ 64 ];
		sprintf( buf, "given index = %d; size = %d", theIndex, listSize );
		oss << buf;
		throw std::invalid_argument( oss.str() );
	}
	return;
}

template < class T >
arrayList< T >::arrayList(int initialCapacity, std::size_t Scaler)
:Scaler( Scaler ){
	if( initialCapacity < 1 ){
		std::ostringstream oss;
		char buf[ 64 ];
		sprintf( buf, "initial capacity = %d Must be > 0", initialCapacity);
		oss << buf;
		throw std::invalid_argument( oss.str() );
	}
	arrayLength = initialCapacity;
	elements = new T[ arrayLength ];
}

template < class T >
inline void arrayList< T >::trimToSize( void ){
	changeLength1D( elements, arrayLength, std::max( listSize, 1ULL ) );
	arrayLength = std::max( listSize, 1ULL );
}

template <class T>
void arrayList< T >::setSize( std::size_t _Size ){
	if( listSize > _Size )
		for( std::ptrdiff_t i = _Size; i < listSize; ++i)
			delete (elements + i);
	listSize = _Size;
}

template <class T>
T& arrayList< T >::operator[]( std::size_t position ) const{
	checkIndex( position );
	return *(elements + position);
}

template < class T >
arrayList< T >::arrayList( const arrayList< T >& theList )
	:arrayLength( theList.arrayLength )
	,listSize( theList.listSize )
	,elements( new T[ arrayLength ])
{
	std::copy(theList.elements, theList.element + listSize, elements );
}

template < class T >
int arrayList< T >::indexOf( const T& theElement ) const{
	int ret {};
	return
		( int )( ( ret =
			std::find(elements, elements + listSize, theElement) - elements) )
				== listSize ? -1 : ret;
}

template < typename T >
void arrayList< T >::erase(int theIndex ){
	checkIndex( theIndex );
	std::copy( elements + theIndex + 1, elements + listSize, elements + theIndex );
	elements[ --listSize ].~T();
}

template < typename T >
void arrayList< T >::insert( int theIndex, const T& theElement ){
	checkIndex( theIndex );
	if(listSize == arrayLength ){
		changeLength1D( elements, arrayLength, arrayLength * Scaler );
		arrayLength *= Scaler;
	}
	std::copy_backward( elements + theIndex, elements + listSize, elements + listSize+1 );
	elements[ theIndex ] = theElement;
}

template < typename T >
void arrayList< T >::output( std::ostream& os ) const{
	std::copy( elements, elements + listSize, std::ostream_iterator< T >( os, "\t") );
}

template < typename value_type >
void changeLength1D( value_type*& pArray,
					 const signed long& N,
					 const signed long& M )
{
//	static_assert(typename std::is_copy_constructible<value_type>::value, "requires copying");
	if( nullptr == pArray )
		throw std::domain_error( "array is nullptr" );
	if( N < 0 || M < 0)
		throw std::invalid_argument( "illegalParameterValue N|M given" );
	std::size_t checkedN  = static_cast< std::size_t >( N );
	std::size_t checkedM  = static_cast< std::size_t >( M );
	value_type* temp = new value_type[ checkedM ];
	std::copy( pArray, pArray + std::min( checkedN, checkedM ), temp );
	delete [] pArray;
	pArray = temp;
}

template < class T >
T& arrayList< T >::get( int theIndex ) const{
	checkIndex( theIndex );
	return elements[ theIndex ];
}

template < typename value_type, std::size_t formerN, std::size_t formerM >
value_type** chanegeLeagth2D( value_type (&_Matrix)[ formerN ][ formerM],
					  const signed long& newN,
					  const signed long& newM){
	assert(newN > 0 && newM > 0 || "invalid argument nagetive N | M given");
//	static_assert(typename std::is_copy_constructible<value_type>::value, "requires copying");
	value_type ** _ScaledMatrix = new value_type*[ newN ];
	for( std::ptrdiff_t i = 0; i < newM; ++i) _ScaledMatrix[ i ] = new value_type[ newM ];
	int i,j;
	std::size_t checkedN  = static_cast< std::size_t >( newN );
	std::size_t checkedM  = static_cast< std::size_t >( newM );
	for(i = 0; i < std::min( formerN, checkedN ); ++i)
		for(j = 0; j < std::min( formerM, checkedM ); ++j)
			_ScaledMatrix[i][j] = _Matrix[i][j];
	return _ScaledMatrix;
}

template < typename InputIterator >
void myCopy(InputIterator begIt, InputIterator endIt, InputIterator resIt ){
	while( !( begIt == endIt ) )
		*resIt++ = *begIt++;
}

int main( void ){
	int *pArray = new int[5] { 1, 2, 3, 4, 5 };
	changeLength1D( pArray, 5L, 10L );
	int i;
	for(i = 0;i < 10;++i) std::clog << *( pArray + i ) << '\n';
	
	constexpr int N { 5 };
	int *pEnd = pArray + N;
	for( std::ptrdiff_t i { N }; i > 0; --i )
		std::clog << ( *( pEnd - i ) = i ) << '\t';
	std::endl( std::cout );
	return 0;
}

  • 8
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

XNB's Not a Beginner

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

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

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

打赏作者

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

抵扣说明:

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

余额充值