算法基础_线性表的C++实现

算法基础_线性表

线性表也称为有序表,他的每一个实例都是元素的一个有序集合。每个实例的形式为(a0, a1, a2, …a(n-1)),其中n是有穷自然数,ai是线性表的元素,i是ai的索引,n是线性表的长度或者大小。

线性表的操作

1.创建一个线性表。
2.撤销一个线性表。
3.确定线性表是否为空。
4.确定线性表的长度。
5.按一个给定的索引查找一个元素。
6.按一个给定的元素查找其索引。
7.按一个给定的索引删除一个元素。
8.按一个给定的索引插入一个元素。
9.从左至右的顺序输出线性表元素。

抽象类linearList

//一个线性表的抽象类
template<class T>
class linearList
{
	public:
		virtual ~linearList() {};
		virtual bool empty() const = 0;
		//当且仅当线性表为空时返回true
		virtual int size() const = 0;
		//返回线性表的元素个数
		virtual T& get(int theIndex) const = 0;
		//返回索引为theIndex的元素
		virtual int indexOf(const T& theElement) const = 0;
		//返回元素theElement第一次出现时的索引
		virtual void erase(int theIndex) = 0;
		//删除索引为theIndex的元素
		virtual void insert(int theIndex, const T& theElement) = 0;
		//把theElement插入到线性表中索引为theIndex的位置。
		virtual void output(ostream& out) const = 0;
		//把线性表插入输出流out
};

数组描述

使用数组来存储线性表的元素,这里采用一个数组来存储一个线性表的实例。
将线性表中的元素映射到数组中有多种对应方式,最常用的是location(i) = i,也可以有其他的映射方式。

具体类arrList

1、定义一个抽象类linearList的派生类arrList,arrList不仅包含前面抽象类的所有方法,还包含有capacity和checkIndex,方法capacity给出数组element当前的长度,方法checkIndex确定一个元素在范围0-listSize-1内的索引。

//类定义
template<class T>
class arrList : public linearList<T>
{
	public:
		//构造函数,复制构造函数和析构函数
		arrList(int iniCapacity = 10);
		arrList(const arrList<T>&);
		~arrList(){delete [] element;}
		//ADT方法
		bool empty() const {return listSize == 0;}		
		int size() const = {return listSize;}		
		T& get(int theIndex) const;		
		int indexOf(const T& theElement) const;		
		void erase(int theIndex);		
		void insert(int theIndex, const T& theElement);
		void output(ostream& out) const;
		//其他方法
		int capacity() const {return arrLength;}

	protected:
		void checkIndex(int theIndex) const;
		//如果索引无效,抛出异常
		T* element; //存储线性表元素的一维数组
		int arrLength;//一维数组的容量
		int listSize;//线性表的元素个数

}
//构造函数
template<class T>
arrList<T>::arrList(int iniCapacity)
{
	//构造函数
	if (iniCapacity < 1)
	{
		ostringstream s;
		s << "Initial capacity = " << iniCapacity<<"Must be > 0";
		throw illegalParameterValue(s.str());
	}
	arrLength = iniCapacity;
	element = new T[arrLength];
	listSize = 0;
}

template<class T>
arrList<T>::arrList(const arrList<T>& theList)
{
	//复制构造函数
	arrLength = theList.arrLength;
	listSize = theList.listSize;
	element = new T[arrLength];
	copy(theList.element, theList.element + listSize, element);
}

2、arrList实例化

//创建两个容量为100的线性表
linearList *x=(linearList)new arrList<int>(100);
arrList<double> = y(100);

//利用容量的缺省值创建一个线性表
arrList<char> z;

//用线性表y复制创建一个线性表
arrList<double> w(y);

3、基本方法
包含方法checkIndex、get、和indexOf的实现。

template<class T>
void arrList<T>::checkIndex(int theIndex) const
{
	//确定索引theIndex在0和listSize - 1之间
	if(theIndex < 0 || theIndex >= listSize)
	{
		ostringstream s;
		s << "index = " << theIndex << "size = " << listSize;
		throw illegalIndex(s.str());
	}
}

template<class T>
T& arrList<T>::get(int theIndex) const
{
	//返回索引为theIndex的元素
	//若此元素不存在,则抛出异常
	checkIndex(theIndex);
	return element[theIndex];
	
}

template<class T>
int arrList<T>::indexOf(const T& theElement) cosnt
{
	//返回元素theElement第一次出现时的索引
	//若该元素不存在,则返回-1
	
	//查找元素theElement
	int theIndex = (int)(find(element, element + listSize, theElement) - element);
	//确定元素theElement是否找到
	if (theIndex == listIndex)
	//没有找到
		return -1;
	else return theIndex;
}

4、删除索引为theIndex元素

template<class T>
void arrList<T>::erase(int theIndex)
{
	//检查索引
	checkIndex(theIndex);
	//有效索引,移动其索引大于theIndex的元素
	copy(element + theIndex + 1, element + listSize, element + theIndex);
	//调用析构函数
	element[--listSize].~T();
	
}

5、在索引为theIndex的位置上插入元素
1)先将索引从theIndex到listSize的元素向右移动一个位置。
2)然后将新元素插入索引为theIndex的位置
3)将listSize的值增加1。
4)如果在插入前数组已满,那么将数组长度加倍。

template<class T>
void arrList<T>::insert(int theIndex, const T& theElement)
{
	//检查索引
	checkIndex(theIndex);
	//有效索引,确定数组是否已满
	if(listSize == arrLength)
	{
		//数组空间满了,长度加倍
		changeLength1D(element, arrLength, 2 * arrLength);
		arrayLength *= 2;
	}	
	//把元素向右移动一个位置
	copy_backward(element + theIndex, element + listSize,
	element + listSize + 1);
	
	element[theIndex] = theElement;
	listSize++;
}

6、输出output和重载流插入符<<

template<class T>
void arrList<T>::output(cout -> out) const
{
	//把线性表插入输出流
	copy(element, element + listSize, ostream_iterator<T>(cout, " "));	
}
//重载
template<class T>
ostream& operator<< (ostream& out, const arrList<T>& x)
{
	x.output(out);
	return out;
}

7、STL中copy函数的一种写法

template<class iterator>
void  copy(iterator start, iterator end, iterator dst)
{
	//从[start,end)复制到[dst, dst + end-start)
	while(start !=end )
	{
		*dst = *start;
		start++;
		dst++:
	}
}

arrList的一个迭代器

添加实现指向首元素指针和尾后元素指针的方法、

class iterator;
iterator begin() {return iterator(element);}
iterator end() {return iterator(element+listSize);}
//类arrList的一个迭代器,仅适用于STL的基于双向迭代器的算法。
class iterator
{
	public:
		//用C++的typedef语句实现双向迭代器
	typedef bidirectional_iterator_tag iterator_category;
	typedef T value_type;
	typedef	ptrdiff_t difference_type;
	typedef T* pointer;
	typedef T& reference;
	
	//构造函数
	iterator(T* thePosition = 0) {position = thePosition;}
	//解引用操作符
	T& operator*() const {return *position;}
	T* operator->() const {return &*postion;}
	//迭代器的值增加
	
	iterator operator++()	//前加
	{
		++position;
		return *this;
	}
	iterator operator++(int)//后加
	{
		iterator old = *this;
		++position;
		return old;
	}
	//迭代器的值减少
	iterator operator--()	//前减
	{
		--position;
		return *this;
	}
	iterator operator--(int)//后减
	{
		iterator old = *this;
		--position;
		return old;
	}
	//测试是否相等
	bool operator !=(const iterator right) const
	{
		return position != right.position;
	}
	bool operator ==(const iterator right) const
	{
		return position == right.position;
	}
	protected:
		T* position; //指向表元素的指针
	
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值