Deux ensembles de structures physiques de tables linéaires - structure de stockage séquentiel et structure de stockage en chaîne
La structure de stockage séquentiel de la table linéaire: utilisez un segment de membres de stockage d'adresses consécutifs pour stocker les éléments de données de la table linéaire à leur tour (la table linéaire stockée par le tableau est la table séquentielle)
#一个线性表的抽象类
#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的位置
}
Modifier la longueur d'un tableau à une dimension
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;//线性表元素个数
}
Constructeur et constructeur de copie de la classe 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);
}
La méthode de base de 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;
}
Recherche d'algorithme générique:
Dans un conteneur de type non-chaîne, vous pouvez trouver directement l'élément correspondant. La
fonction de recherche nécessite plusieurs paramètres: itérateur, valeur de l'indice et l'élément que vous recherchez
vecteur <int> a;
find (a .begin (), a.end (), 1);
Cette phrase signifie que du début de a à la fin, trouvez le premier élément avec une valeur de 1 et renvoyez un itérateur à cet élément.
Recherche a une large
gamme d'utilisations dans le conteneur de chaîne: find_first_of, find_last_of, find_not_first_of, find_not_last_of, etc.
Dans le type de chaîne, les paramètres requis comprennent également itérateurs, les indices et la chaîne à trouver Notez qu'il est une chaîne et ne peut pas. être recherché pour un seul caractère.
string a;
find (a.begin (), a.end (), "asd")
Cette phrase signifie que la première adresse de la chaîne avec la même sous-chaîne de "asd" se trouve dans a. Renvoie un itérateur pointant vers la première adresse de la chaîne.
find_last_of consiste à trouver le dernier,
find_not_first_of consiste à trouver la première adresse de la première chaîne qui n'est pas égale à "asd"
L'algorithme copy_backward est similaire à la copie en termes de comportement, sauf que son processus de copie s'exécute contre la copie. Le processus de copie commence à partir du dernier élément jusqu'à ce que le premier élément soit copié. En d'autres termes, l'opération de copie commence du dernier-1 jusqu'à la fin du premier. Ces éléments sont également copiés de l'arrière vers l'avant vers le conteneur cible, à partir de result-1, et copient toujours les derniers éléments.
Pour donner un exemple simple: étant donné le vecteur {0, 1, 2, 3, 4, 5}, nous devons maintenant copier les trois derniers éléments (3, 4, 5) dans les trois premiers (0, 1, 2) In la position, alors nous pouvons la définir comme ceci: mettre d'abord à la position 3, dernier à la position suivante de 5, et le résultat à la position de 3. De cette façon, la valeur de 5 sera copiée à la position de 2, puis 4 est copié à la position 1, et les 3 derniers sont copiés à la position 0. Nous pouvons être curieux de connaître les avantages de copy_backward () par rapport à l'algorithme copy () ordinaire qui commence à copier à partir du premier élément .
Une réponse est que lorsque la séquence se chevauche, vous pouvez utiliser copy () pour copier l'élément vers la position restante de la séquence de destination qui se chevauche, c'est-à-dire la position avant le premier élément de la séquence de destination. Si vous essayez d'utiliser l'algorithme copy () pour copier des éléments à droite de la même séquence, cette opération échouera, car les éléments copiés seront écrasés avant d'être copiés. Si vous voulez les copier vers la droite, vous pouvez utiliser copy_backward (), tant que l'itérateur de fin de la séquence de destination est à droite de l'itérateur de fin de la séquence source. La figure 2 illustre la différence entre les deux algorithmes lors de la copie d'éléments à droite de la séquence de chevauchement.