数据结构之线性表——数组描述

数据对象和数据结构

数据对象

数据对象是一组实例值,例如:
boollean={false,true}
digit={1,2,3,4,5,6,7,8,9}
letter={A,B,C,D,E,F,G,H,I,…,Z}
boollean,digit,letter这些都是数据对象,在每个数据对象中,比如在boollean中有true和false两个实例;而0,1,2,…,9是digit的实例。数据对象的实例要么是一个不可再分的“原子”要么是另一个数据对象的实例作为成员符合而成。对于后一种情景,用元素来表示这些成员。
比如数据对象string是由所有可能的串实例组成的集合。每一个实例都由字符组成。例如:good,a trip to Hawaii,going down hill,abcdouwcoadc都是串实例。第一个串由4个元素组成,每一个元素都是数据对象letter的实例。

数据结构

数据结构是一个数据对象,同时,这个对象的实例以及构成实例的元素都存在着联系,而且这些联系由相关的函数来规定。。
研究数据结构,关心的是数据对象(实际上是实例)的描述以及相关函数的具体实现。数据对象描述的好,函数的实现救回高效。
常用的数据对象以及操作都在C++中最为基本数据类型而实现,如整数对象(int)、布尔对象(bool)等。

线性表数据结构

线性表,也称有序表,它的每一个实例都是元素的一个有序集合。每一个实例的形式为(e0,e1,e2,e3…,en-1)其中n为又穷的自然数,ei是线性表的元素,i是元素ei的索引,n是线性表的长度和大小。元素可以被看作原子,他们本身的结构和线性表的结构无关。当n等于0的时候线性表为空;n>0的时候,e0是线性表的第0个元素或首元素,en-1是线性表的最后一个元素。可以认为e0先于e1…除了这种先后关系,线性表不再有其它关系。
对于一个线性表,我们要设计一些函数完成对线性表和线性表中元素的操作。下面列举一些线性表操作:
A 创建一个线性表
B 撤销一个线性表
C 确定线性表是否为空
D 确定线性表长度
E 按一个给定的索引查找一个元素
F 安一个元素查找其索引
G 安一个给定的索引删除一个元素
H 从左至右输出线性表元素

抽象数据类型

一个线性表可以用一个抽象数据类型来说明,既说明他的实例也说明对它的操作。

#include<iostream>
using namespace std;
teemplate<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;//把线性表插入到输出流 
	 
}; 

数组描述

描述

在数组描述中,用数组来储存线性表中的元素。我们用一个数组来储存一个数据对象的实例。
因此,我们需要一个映射使线性表的一个元素对应数组的一个位置。
location(i)=i;
上面公式:第i个线性表的元素在数组中储存的位置是i,(把线性表的一个位置i 带入到location函数中,算出线性表中这个元素在数组中所在的位置。)
location(i)=(location(0)+i)%arrayLength ;
上面公式表示的是线性表中的第i个元素带入到location函数中生成元素在数组中所在的位置。
比如:arrayLength为10, location(0)=7,
location(i)=(7+i)%10,所以线性表中第零号元素在数组中为第七号元素。(由这个公式可以生成一个首尾相接的环形数组)

变长一维数组

#include<iostream>
using namespace std;
void changeLength(T*& a,int oldLength,int newLength)
{
	if(newLength<0)
	{
		cerr<<"new length must >= 0 "<<endl;
	}
	T* temp = new T[newLength];
	int number = min(oldLength,newLength);
	copy(a,a+oldLength,temp);
	delete [] a;
	a=temp;
}

上面代码需要注意的是在函数定义中:T*&是指针引用类型,必须要用该类型,否则在函数中改变的数组不会继承到原数组中(关于这个问题我会单独写一篇博文进行解释)。其他的都还比较好理解。

类arrayList

我们定义一个抽象类linearList的派生类ArrayList,它利用公式实现抽象数据类型linearList。所以ArrayList中必须包含实现抽象类linearList的全部办法。不仅如此,它还应该包含基类linearList没有声明的方法,例如capacity,checkIndex。方法checkIndex是给出数字当前额长度,而方法checkIndex是确定元素在范围内的索引。
下面展示一些 内联代码片

#include<iostream>
using namespace std;
template<class T>
class arrayList:public linearList<T>
{
public:
	arrayList(int initialCapacity = 10);
	arrayList(const arrayList<T> &);//复制构造函数
	~arrayList() {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 arrayLength;}
protected :
	void checkIndex(int theIndex) const;
	//若索引无效,则抛出异常
	T* Element;//储存线性表的一维数组
	int arrayLength;//一维数组容量 
	int listSize; //线性表的元素个数 
};

类arrayList 的构造函数和复制构造函数

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


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

arrayList 的实例化
用数组描述的线性表需要使用下面的语句来创建

linearList *x=(linearList)new arrayList<int>(100);
或者
arrayList<double> y(100);
//利用容量的缺省值创建一个线性表
arrayList<char> z;
//利用线性表y,复制创建一个线性表
arrayList<double> w(y);

arrayList的基本方法

checkIndex:确定索引在【0,listSize-1】之间
get:返回索引值为theIndex的元素
indexOf:返回元素theElement第一次出现的索引值。
下面展示一些 内联代码片

template<class T>
void arrayList<T>::checkIndex(int theIndex) const
{//确定索引 theIndex在0和listSize-1之间
	if(theIndex < 0||theIndex >= listSize)
	{
		cout<<"the Index is not leagal"<<endl;
	 } 
}
template<class T>
T& arrayList<T>::get(int theIndex) const
{//返回索引值为theIndex的元素
	 
	checkIndex(theIndex); 
	return Element[theIndex];
}

template<class T>
int arrayList<T>::indexOf(const T& theElement) const
{
	//返回元素第一次出现时的索引
	//若元素不存在,则返回-1;
	//查找元素theElement;
	int theIndex = (int)(find(element,element+listSize,theElement)-Element);
	if (theElement == listSize) return -1;
	else return theIndex; 
}

删除一个元素或插入一个元素

#include<iostream>
using namespace std;
template<class T>
void arrayList<T>::erase(int theIndex)
{
	checkIndex(theIndex);
	copy(Element+theIndex+1,Element+listSize,Element + theIndex);
	Element[--listSize].~T();
}
#include<iostream>
using namespace std;
template <class T>
void arrayList<T>::(int theIndex,const T& theElement)
{
	if(theIndex < 0||theIndex > listSize)
	{
		cout<<"error";
	}
	if(listSize == arrayLength)
	{
		changeLength1D(Element,arrayLength,2*listSize);
		arrayLength *=2;
	}
	copy_backward(Element + theIndex,Element + listSize,Element + listSize + 1);
	Element[theIndex] = theIndex;
	listSize++;
}';

把一个线性表插入输出流
下面展示一些 内联代码片

#include<iostream>
using namespace std;
template <class T>
void arrayList<T>::output(cout->out) const 
{
	copy(Element,Element+listSize,ostream_iterator<T>(cout," "));
}
//重载<< 
template <class T>
ostream& operator<<(ostream& out,const arrayList<T>& x)
{
	x.output(out);return out;
}

c++迭代器

一个迭代器是一个指针,指向对象的一个元素。顾名思义,一个迭代器可以用来逐个访问对象的所有元素。

#include<iostream>
using namespace std;
int main()
{
	int a[3]={2,3,4};
	for(int* p=a;p!=a+3;p++){
		cout<<(*p)<<" ";
	}
	return 0 ; 
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

元解~殇怀

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

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

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

打赏作者

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

抵扣说明:

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

余额充值