前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >线性表-数组描述

线性表-数组描述

作者头像
青木
发布2018-05-28 15:45:43
7180
发布2018-05-28 15:45:43
举报

线性表的数据结构

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

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

线性表的抽象类

代码语言:javascript
复制
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)。数组倍增的时间,从渐进意义上考量,不会大于元素插入的总时间。

代码语言:javascript
复制
//变长数组实现
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()。

代码语言:javascript
复制
//具体类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;//线性表的元素个数
}

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

代码语言:javascript
复制
//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编译。先放着吧,这问题以后再解决:

代码语言:javascript
复制
#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;
}
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 线性表的数据结构
  • 线性表的抽象类
  • 数组描述
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档