ああ魏は最近、いくつかの時間のために落ち、そして今目覚めた、魏は、ブログを書くことを遵守する必要があります!
QAQのデータ構造を学ぶためにゼロからスタートする混同学ぶために最近のデータ構造、ああ魏
まず、ADTのテーブル直線(抽象)
(カテゴリ用テンプレートここ)
template <class T>
class linearList
{
public:
virtual ~linearList(){};
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;
virtual void insert(int theIndex,const T& theElement)=0;
virtual void output(ostream& out) const=0;//把线性表插入输出流out
};
次の構造によって定義されたノードのリンクされたリストであります
template <class T>
struct chainNode
{
T element;
chainNode<T> *next;
chainNode(){}
chainNode(const T& element)
{
this->element=element;
}
chainNode(const T& element,chainNode<T>* next)
{
this->element=element;
this->next=next;
}
};
次は、リンクリストの定義です
template <class T>
class chain:public linearList<T>
{
public:
chain(int initialCapacity=10);//构造函数
chain(const chain<T>&);//复制构造函数
~chain();//析构函数
//ADT方法
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;
protected:
void checkIndex(int theIndex) const;//如果索引无效,抛出异常
chainNode<T>* firstNode;//指向链表第一个结点的指针,注意并不是头结点
int listSize;//线性表的元素个数
};
1. checkIndex機能を達成するために:
template<class T>
void chain<T>::checkIndex(int theIndex)const
{//确定索引在0和listSize-1之间
if(theIndex<0||theIndex>=listSize)
{
ostringstream s;
s<<"index="<<theIndex<<"size= "<<listSize;
throw illegalIndex(s.str());
}
}
2.リストコンストラクタ(時間複雑度 θ(1) )
template<class T>
chain<T>::chain(int initialCapacity)
{
if(initialCapacity<1)
{
ostringstream s;
s<<"Initial capacity = "<<initialCapacity<<"Must be > 0";
throw illegalParameterValue(s.str());
}
firstNode=NULL;
listSize=0;
}
コピーコンストラクタ(時間複雑* O(MAX {LISTSIZE、theList.listSize}))の3 Aリスト
template<class T>
chain<T>::chain(const chain<T>& theList)
{
listSize=theList.listSize;
if(listSize==0)//链表theList为空
{
firstNode=NULL;
return;
}
//若不为空
chainNode<T>* sourceNode=theList.firstNode;//复制链表theList的节点
firstNode=new chainNode<T>(sourceNode->element);//复制链表theList的首元素
sourceNode=sourceNode->next;
chainNode<T>* targetNode=firstNode;//当前链表的最后一个节点
//复制剩余元素
while(sourceNode!=NULL)
{
targetNode->next=new chainNode<T>(sourceNode->element);
targetNode=targetNode->next;
sourceNode=sourceNode->next;
}
targetNode->next=NULL;//链表结束
}
コピーコンストラクタは、説明するの:
4.リストデストラクタ(時間複雑度O(LISTSIZE))
デストラクタは、すべてのノードを削除することであり、この方法は、削除するヘッドノードから始まります
template<class T>
chain<T>::~chain()//删除链表的所有节点
{
while(firstNode!=NULL)//删除首节点
{
chainNode<T>* nextNode=firstNode->next;
delete firstNode;
firstNode=nextNode;
}
}
実装(時間計算量O(theIndex))5. get関数
この関数は、指定したインデックスの要素を見つけることです
template<class T>
T& chain<T>::get(int theIndex)const
{
checkIndex(theIndex);//如果索引不存在,则抛出异常
chainNode<T>* currentNode=firstNode;
//移向所需要的节点
for(int i=0;i<theIndex;i++)
currentNode=currentNode->next;
return currentNode->element;
}
実装は、(時間は、複雑さO(LISTSIZE))6のindexOf関数
この関数は、要素theElementの最初の発生を見つけるためのインデックスである
見つけるために見つからない場合、-1を返し、戻り率を
template<class T>
int chain<T>::indexOf(const T& theElement)const
{
chainNode<T>* currentNode=firstNode;
int index=0;
//退出循环的条件:①没有找到,找到了最后,currentNode为空;②找到了
while(currentNode!=NULL&¤tNode->element!=theElement)
{
currentNode=currentNode->next;
index++;
}
//如果是由于没有找到退出的循环
if(currentNode==NULL)
return -1;
//否则
return index;
}
実装(時間複雑性O(theIndex))7.消去機能をれる
3つのケースに分け:
①:theIndex.setdefault <0またはtheIndex> = LISTSIZE。この操作で有効ではありません
②:削除非空のテーブルの0番目の要素ノード(第1要素)
③:削除他の要素ノード
template<class T>
void chain<T>::erase(int theIndex)
{
checkIndex(theIndex);
if(theIndex==0)//如果要删除首节点
{
firstNode=firstNode->next;
}
else
{
chainNode<T>* currentNode=firstNode;
for(int i=0;i<theIndex-1;i++)//找到要删除的节点的前驱节点
{
currentNode=currentNode->next;
}
currentNode->next=currentNode->next->next;
}
listSize--;//将链表的个数减一
}
実現(時間計算量O(theIndex))8の機能、挿入
機能と同様の挿入・削除機能
(自分の皿Iの叫びによって書かれた教科書を参照)魏は、コードを書いているの下に
template<class T>
void chain<T>::insert(int theIndex,const T& theElement)
{
chainNode<T>* tmpNode=new chainNode<T>(theElement);
if(theIndex==0)
{
tmpNode->next=firstNode;
firstNode=tmpNode;
}
else
{
chainNode<T>* p=firstNode;
for(int i=0;i<theIndex-1;i++)
{
p=p->next;
}
tmpNode->next=p->next;
p->next=tmpNode;//这两行代码位置不能换,因为如果先将p指向tmpNode,那之前p的后继就找不到了
}
listSize++;
}
教科書コードをお楽しみください。
template<class T>
void chain<T>::insert(int theIndex,const T& theElement)
{
if(theIndex<0||theIndex>listSize)
{
ostringstream s;
s<<"index="<<theIndex<<"size="<<listSize;
throw illegalIndex(s.str());
}
if(theIndex==0)
firstNode=new chainNode<T>(theElement,firstNode);
else
{
chainNode<T>* p=firstNode;
for(int i=0;i<theIndex-1;i++)
p=p->next;
p->next=new chainNode<T>(theElement,p->next);//太强了!
}
listSize++;
}
フォーム線形9.拡張抽象クラス
線膨張ADTテーブルの必要は、透明なクリアテーブル、テール一backにテーブル要素のような他の操作の数を含んでいます
template<class T>
class extendedLinearList::linearList<T>
{
public:
virtual ~extendedLinearList(){}
virtual void clear()=0;//清表
virtual void push_back(const T& theElement)=0;//将元素theElement插到表尾
};
10.クリア機能の実現
lastNodeを高めるために説明extendedLinearListチェーン抽象ショートカット由来リストチェーンによって開発されたクラス、およびテールポインタはノードとして私たちは、クラスextendedChainを開発する必要があります
ここで明確な機能ですが
template<class T>
void extendedChain<T>::clear()
{
//从首节点开始删除
while(firstNode!=NULL)
{
chainNode<T>* nextNode=firstNode->next;
delete firstNode;
firstNode=nextNode;
}
listSize=0;
}
11.一back機能が達成するために
template<class T>
void extendedChain<T>::push_back(const T& theElement)
{
chainNode<T>* newNode=new chainNode<T>(theElement,NULL);
if(firstNode==NULL)
firstNode=lastNode=newNode;//extendedChain中声明了尾结点lastNode
else
{
lastNode->next=newNode;
lastNode=newNode;
}
listSize++;
}