線形テーブルの2セットの物理構造-シーケンシャルストレージ構造とチェーンストレージ構造
線形テーブルの順次ストレージ構造:連続するアドレスストレージメンバーのセグメントを使用して、線形テーブルのデータ要素を順番に格納します(配列によって格納される線形テーブルは順次テーブルです)
#一个线性表的抽象类
#include<iostream>
class linerList{
public:
virtual ~linerList() {};
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的位置
}
1次元配列の長さを変更する
template<class T>
void changedLength1D(T* a, int oldLength, int newLength)
{
if (newLength<0)
throw illegalParameterValue("new length must be >=0");
T* temp=new T[newLength];
int number=min(oldLength,newLength);//#include <algorithm>
copy(a,a+number,temp);//将a复制到temp//#include <algorithm>
delete [] a;
a=temp;//指针被free或者delete后,没有置为NULL, free和delete只是把指针所指向的内存给释放掉,
//并没有把指针本身干掉,此时指针指向的是“垃圾”内存。释放后的指针应该被置为NULL.否则造成内存泄漏
}
#类arrayList是一个具体类,所以他必须实现抽象类linearList的所有方法,并且还包含基类没有的方法。capacity(给出数组长度)和checkIndex.
template<class T>
class arrayList : public linearList<T>
{
friend ostream& operator<<(ostream&, const arrayList<T>& x);
public:
//构造函数,复制构造函数和析构函数
arrayList(int initialCapicity = 10);
arrayList(const arrayList<T>&);
~arrayList() {delete [] element;}
//ADT方法
bool empty() const {return listSize == 0;}
int size() const {return listSize;}
T& get(int index)const ;
int indexOf(const T& theElement) const;
void erase(int theIndex);
void insert(int theIndex, const T& theElement );
//其他方法
int capacity()const {redturn arrayLength;}
projected:
void checkIndex(int theIndex) const;//若索引无效则抛出异常
T* element;//存储线性表元素的一维数组
int arrayLength;//一维数组的容量
int listSize;//线性表元素个数
}
クラスarrayListのコンストラクターとコピーコンストラクター
template<class T>
arrayList<T>::arraydList (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 )
{
arrayLength = theList.arrayLength;
listSize = theList.listSize;
element = new T[arrayLength];
copy(theList.element,theList.element + listSize,element);
}
arrayListの基本的なメソッド
template<class T>
void arrayList<T>::checkIndex(int theIndex) const
{//确定索引在0和listSize-1之间
if(theIndex < 0 || theIndex >= listSize)
{ostringstream s
s << "index=" << theIndex << "size=" << listSize;
throw illegalIndex(s.str());
}
}
template<class T>
T& arrayList<T>::get(int theIndex) const
{
checkIndex(theIndex);
return element[theIndex];
}
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;
}
template<class T>
void arrayList<T>::erase(int theIndex)
{
checkIndex(theIndex);
//有效索引,移动其索引大于theIndex的元素
copy(element+theIndex+1,element+listSize,element+theIndex);
element[--listSize].~T();//调用析构函数
}
template<class T>
void arrayList<T>::insert(int theIndex, const T& theElement )
{
if(theIndex < 0 || theIndex > listSize)
{//无效索引
ostringstream s;
s << "index=" << theIndex << "size=" << listSize;
throw illegalIndex(s.str());
}
//有效索引,确定数组是否已满
if(listSize == arrayLength)
{//数组空间已满,数组长度增倍
changeLength1D(element,arrayLength,arrayLength*2);
arrayLength *= 2;
}
//把元素向右移动一个位置
copy_backward(element+thedIndex,element+listSize,element+listSize+1);
element[theIndex] = theElement;
listSize++;
}
ostream& operator<<(ostream& s, const arrayList<T>& x)
{
copy(element,element+listSize,ostream_iterator<T>(s))
retrun s;
}
遺伝的アルゴリズムの検索:
非文字列型のコンテナーでは、対応する要素を直接検索できます。
検索関数には、イテレーター、添え字値、および探している要素のいくつかのパラメーターが必要です。vector
<int> a;
find(a .begin()、a.end()、1);
この文は、aの最初から最後まで、値が1の最初の要素を見つけて、その要素にイテレーターを返すことを意味します。
Findは、文字列コンテナでさまざま
な用途があります:find_first_of、find_last_of、find_not_first_of、find_not_last_ofなど。
文字列タイプでは、必要なパラメータには、イテレータ、添え字、および検索する文字列も含まれます。これは文字列であり、できないことに注意してください。 1文字を検索します。
string a;
find(a.begin()、a.end()、 "asd")
この文は、「asd」と同じ部分文字列を持つ文字列の最初のアドレスが。にあることを意味します。文字列の最初のアドレスを指すイテレータを返します。
find_last_ofは最後の
アドレスを検索し、find_not_first_ofは「asd」と等しくない最初の文字列の最初のアドレスを検索します。
copy_backwardアルゴリズムは、そのコピープロセスがコピーに対して逆に実行されることを除いて、動作の点でコピーに似ています。コピープロセスは、最後の要素から最初の要素がコピーされるまで開始されます。つまり、コピー操作はlast-1からfirstの終わりまで開始されます。これらの要素も、result-1から開始して、後ろから前にターゲットコンテナにコピーされ、常に最後から最初の要素をコピーします。
簡単な例を挙げると、ベクトル{0、1、2、3、4、5}が与えられた場合、最後の3つの要素(3、4、5)を最初の3つの要素(0、1、2)にコピーする必要があります。位置を設定すると、次のように設定できます。最初に3の位置に設定し、最後に5の位置に設定し、結果を3の位置に設定します。このようにして、5の値がの位置にコピーされます。 2、次に4が1の位置にコピーされ、最後の3が0の位置にコピーされます。最初からコピーを開始する通常のcopy()アルゴリズムと比較したcopy_backward()の利点について興味があるかもしれません。要素。
1つの答えは、シーケンスがオーバーラップする場合、copy()を使用して、オーバーラップする宛先シーケンスの残りの位置、つまり、宛先シーケンスの最初の要素の前の位置に要素をコピーできるということです。copy()アルゴリズムを使用して同じシーケンスの右側に要素をコピーしようとすると、コピーされた要素がコピーされる前に上書きされるため、この操作は成功しません。それらを右側にコピーする場合は、宛先シーケンスの終了イテレーターがソースシーケンスの終了イテレーターの右側にある限り、copy_backward()を使用できます。図2は、重複するシーケンスの右側に要素をコピーする場合の2つのアルゴリズムの違いを示しています。