線性表-數組描述

線性表的數據結構

線性表應該實施下列操做:ios

  • 建立一個線性表
  • 撤銷一個線性表
  • 肯定線性表是否爲空
  • 肯定線性表的長度
  • 按一個給定的索引查找一個元素
  • 按一個給定的元素查找其索引
  • 按一個給定的索引刪除一個元素
  • 按一個給定的索引插入一個元素
  • 從左至右順序輸出線性表元素

線性表的抽象類

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)。數組倍增的時間,從漸進意義上考量,不會大於元素插入的總時間。windows

//變長數組實現
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;
}
相關文章
相關標籤/搜索