线性表-数组描述

线性表的数据结构

线性表应该实施下列操作:

  • 创建一个线性表
  • 撤销一个线性表
  • 确定线性表是否为空
  • 确定线性表的长度
  • 按一个给定的索引查找一个元素
  • 按一个给定的元素查找其索引
  • 按一个给定的索引删除一个元素
  • 按一个给定的索引插入一个元素
  • 从左至右顺序输出线性表元素

线性表的抽象类

template<class T>
class linearList
{
public:
	virtual ~linearList(){};

	//判断线性表是否为空
	virtual bool empty() const = 0;

	//计算线性表元素个数
	virtual int size() const = 0;

	//返回索引为theIndex的元素
	virtual T& get(int theIndex) const = 0;

	//返回元素theElement第一次出现时的索引
	virtual int indexOf(const T& theElement) const = 0;

	//删除索引为theIndex的元素
	virtual void erase(int theIndex) = 0;

	//把元素theElement插入到索引为theIndex的位置
	virtual void insert(const T& theElement,int theIndex) = 0;

	//把线性表插入输出流out
	virtual void output(ostream out) const = 0;
}

数组描述

要创建一个数组类。以实现抽象数据类型linearList,必须首先选择数组element的类型和数组长度。
解决第一个问题可以通过使用模板类。
解决第二个问题可以使用动态数组。首先估计一个初始数组长度,然后在数组空间不足的情况下,动态的增加数组长度。
当数组满而需要增大数组长度时,数组长度常常是要加倍的。这个过程称为数组倍增。(array doubling)。数组倍增的时间,从渐进意义上考量,不会大于元素插入的总时间。

//变长数组实现
template<class T>
void changeLength1D(T*& a,int oldLength,int newLength)
{
	if(newLength<0)
		cout<<"the length should > 0"<<endl;

	T* temp = new T[newLength];
	int number = min(oldLength,newLength);//需要复制的元素个数
	copy(a,a+number,temp);
	delete [] a;//释放老数组的内存空间
	a = temp;
}

.定义一个C++抽象类linearList的派生类arrayList。arrayList是一个具体的类,实现了抽象类linearList的所有方法,并且还有arrayList中没有的方法,比如capacity()和checkindex()。

//具体类arrayList的实现
template<class T>
class arrayList:public linearList<T>//尖括号中的类型规定了linearList只能
									//保存T类型的数据
{
public:
	arrayList(int initialCapacity = 10);//构造函数
	arrayList(const arrayList<T>&);//复制构造函数
	~arrayList(){delete [] element;}//析构函数

	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;
	//若索引theIndex无效,则抛出异常
	T* element;//存储线性表元素的一维数组
	int arrayLength;//一维数组的容量
	int listSize;//线性表的元素个数
}

下面是具体类中函数的具体实现:

//arrayList的构造函数
template<class T>
arrayList<T>::arrayList(int initialCapacity)
{
	if(initialCapacity < 1) 
		cout<<"数组为空"<<endl;
	arrayLength = initialCapacity;
	element = new T[arrayLength];
	listSize = 0;
}

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

//erase()函数的实现
template<class T>
void arrayList::erase(int theIndex)
{
	checkIndex(theIndex);//先判断元素是否存在

	//移动索引theIndex之后的所有元素
	copy(element+theIndex+1,element+listSize,element+theIndex);
	element[--listSize].~T();//调用析构函数
}

//在索引为theIndex的位置插入元素theElement
template<class T>
void arrayList::insert(int theIndex,T& theElement)
{
	if(theIndex < 0 || theIndex > listSize)
		cout<<"元素索引不在合理范围内!"<<endl;

	//索引有效,确定数组是否已满
	if(listSize ==arrayLength)
		changeLength1D(element,arrayLength,2*arrayLength);
		arrayLength *= 2;

	copy_backward(element+theIndex,element+theList,element+listSize+1);
	element(theIndex) = theElement;
	listSize++;
}

//checkIndex()方法实现
template<class T>
void arrayList<T>::checkIndex(int theIndex) const
{
	if(theIndex < 0 || theIndex >= listSize)
		cout<<"提供的索引不在合理范围内!"<<endl;
}

//get()方法实现
template<class T>
T& arrayList<T>::get(int theIndex) const
{
	checkIndex(theIndex);
	return element[theIndex];
}

//indexOf()函数实现
template<class T> 
int arrayList<T>::indexOf(const T& theElement) const
{
	//查找元素theElement
	int theIndex = (int)(find(element,element+listSize,theElement)-element);

	//确定元素theElement是否找到
	if(theIndex == listSize)
		return -1;
	else
		return theIndex;
}

//erase()函数的实现
template<class T>
void arrayList::erase(int indexOf)
{
	checkIndex(theIndex);

	copy(element+theIndex+1,element+listSize,element+theIndex);
	element[--listSize].~T();
}

//insert()函数的实现
void arrayLength::insert(int theIndex,const T& theElement)
{
	if(theIndex < 0 || theIndex >= listSize)
		cout<<"索引范围不合法"<<endl;
	 if(listSize == arrayLength)
	 {
	 	changeLength1D(element,arrayLength,2*arrayLength);
	 	arrayLength*=2;
	 }

	 copy_backward(element+theIndex,element+listSize,element+listSize+1);
	 element[theIndex] = theElement;
	 listSize++;
}

以下是可以在Qt5.1中成功运行的完整代码(windows平台):
在Mac平台报错:linker command line with exit code 1(use -v to see invocation)
Mac中的这种报错,网上有很多教程,我试了几种,都没有用。by the way,我在Mac上的使用clang编译。先放着吧,这问题以后再解决:

#include<iostream>
#include<stdlib.h>
#include<algorithm>
using namespace std;


//改变一个一维数组的长度
template<class T>
void changeLength1D(T*& a,int oldLength,int newLength)
{
    if(newLength >= 0)
    {
        T* temp = new T[newLength];
        int number = min(oldLength,newLength);//需要复制的元素个数
        copy(a,a+number,temp);
        delete [] a;//释放老数组的内存空间
        a = temp;
    }
}

int min(int a,int b)
{
    if(a >= b)
        return b;
    else
        return a;
}

/*
 * 一个线性表的抽象类
*/
template<class T>
class linearList
{
public:
    virtual ~linearList(){};
    virtual bool empty() const = 0;
    virtual int size() 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(ostream& out) const = 0;
};

/*
 * 线性表具体类的定义
 * 类名:arrayList
*/
template<class T>
class arrayList : public linearList<T>
{
public:
    //构造函数
    arrayList(int initialCapacity = 10);
    //复制构造函数
    arrayList(const arrayList<T>&);
    //析构函数
    ~arrayList();

    //具体函数声明
    bool empty() const;
    int size() const;
    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;
protected:
    bool checkIndex(int theIndex) const;
    T* element;
    int listSize;
    int arrayLength;
};

/*
 * 具体类中的函数具体实现
*/
//构造函数
template<class T>
arrayList<T>::arrayList(int initiaCapacity)
{
    if(checkIndex(initiaCapacity))
    {
        arrayLength = initiaCapacity;
        element = new T[arrayLength];
        listSize = 0;
    }
}

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

//析构函数
template<class T>
arrayList<T>::~arrayList()
{
    delete [] element;
}


//bool empty()
template<class T>
bool arrayList<T>::empty()const
{
    return listSize == 0;
}

//int size()
template<class T>
int arrayList<T>::size() const
{
    return listSize;
}

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

//int indexOf()
template<class T>
int arrayList<T>::indexOf(const T &theElement) const
{
    int theIndex = (int)(find(element,element+listSize,theElement)-element);
    if(theIndex == listSize)
        return -1;
    else
        return theIndex;
}

//void erase()
template<class T>
void arrayList<T>::erase(int theIndex)
{
    if(checkIndex(theIndex))
    {
        copy(element+theIndex+1,element+listSize,element+theIndex);
        element[--listSize].~T();//调用析构函数
    }
}

//void insert()
template<class T>
void arrayList<T>::insert(int theIndex, const T &theElement)
{
    if(checkIndex(theIndex))
    {
        if(listSize == arrayLength)
        {
            //数组空间已满,数组长度倍增
            changeLength1D(element,arrayLength,2*arrayLength);
            arrayLength *= 2;
        }
        //把数组向右移动一个位置
        copy_backward(element+theIndex,element+listSize,element+listSize+1);
        element[theIndex] = theElement;
        listSize++;
    }
}

//核对元素索引是否合法
template<class T>
bool arrayList<T>::checkIndex(int theIndex) const
{
    if(theIndex<0 || theIndex >= listSize)
        return false;
    else
        return true;
}

//output(ostream& out)
template<class T>
void arrayList<T>::output(ostream &out) const
{
    for(int i = 0;i<listSize;i++)
        out<<element[i]<<" ";
}
//重载<<
template<class T>
ostream& operator<<(ostream& out,const arrayList<T>& x)
{
    x.output(out);
    return out;
}

//int capacity() const;
template<class T>
int arrayList<T>::capacity()const
{
   return arrayLength;
}
int main(void)
{
    // test constructor
       linearList<double> *x = new arrayList<double>(20);
       arrayList<int> y(2), z;

       // test capacity
       cout << "Capacity of x, y and z = "
            << ((arrayList<double>*) x)->capacity() << ", "
            << y.capacity() << ", "
            << z.capacity() << endl;


       // test size
       cout << "Initial size of x, y, and z = "
            << x->size() << ", "
            << y.size() << ", "
            << z.size() << endl;

       // test empty
       if (x->empty()) cout << "x is empty" << endl;
       else cout << "x is not empty" << endl;
       if (y.empty()) cout << "y is empty" << endl;
       else cout << "y is not empty" << endl;

       // test insert
       y.insert(0, 2);
       y.insert(1, 6);
       y.insert(0, 1);
       y.insert(2, 4);
       y.insert(3, 5);
       y.insert(2, 3);
       cout << "Inserted 6 integers, list y should be 1 2 3 4 5 6" << endl;
       cout << "Size of y = " << y.size() << endl;
       cout << "Capacity of y = " << y.capacity() << endl;
       if (y.empty()) cout << "y is empty" << endl;
       else cout << "y is not empty" << endl;
       y.output(cout);
       cout << endl << "Testing overloaded <<" << endl;
       cout << y << endl;

       // test indexOf
       int index = y.indexOf(4);
       if (index < 0) cout << "4 not found" << endl;
       else cout << "The index of 4 is " << index << endl;

       index = y.indexOf(7);
       if (index < 0) cout << "7 not found" << endl;
       else cout << "The index of 7 is " << index << endl;

       // test get
       cout << "Element with index 0 is " << y.get(0) << endl;
       cout << "Element with index 3 is " << y.get(3) << endl;

       // test erase
       y.erase(1);
       cout << "Element 1 erased" << endl;
       cout << "The list is "  << y << endl;
       y.erase(2);
       cout << "Element 2 erased" << endl;
       cout << "The list is "  << y << endl;

       cout << "Size of y = " << y.size() << endl;
       cout << "Capacity of y = " << y.capacity() << endl;
       if (y.empty()) cout << "y is empty" << endl;
       else cout << "y is not empty" << endl;



       // test copy constructor
       arrayList<int> w(y);
       y.erase(0);
       y.erase(0);
       cout << "w should be old y, new y has first 2 elements removed" << endl;
       cout << "w is " << w << endl;
       cout << "y is " << y << endl;

       // a few more inserts, just for fun
       y.insert(0,4);
       y.insert(0,5);
       y.insert(0,6);
       y.insert(0,7);
       cout << "y is " << y << endl;
    cout<<"Hello World!"<<endl;
    return 0;
}

转载于:https://my.oschina.net/u/1771419/blog/1631423

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值