#include<iostream> #include<cstdio> using namespace std; template <class T> //模板類 class Link //單鏈表結點類 { public: T data; //結點數據域 Link<T> *next; //指向下一結點的指針 Link(const T info,Link<T> *nextValue=NULL) //帶有元素內容和下一結點指針的構造函數,下一結點的指針為默認參數,若不輸入默認為空 { data=info; next=nextValue; } Link(const Link<T> *nextValue) //帶有下一結點指針的構造函數 { next=nextValue; } Link() //無參數的構造函數 { next=NULL; } //上述三個函數為Link的構造函數及其重載 }; template <class T> class InkList //單鏈表類 { private: Link<T> *head,*tail; //頭指針和尾指針,其中頭指針不儲存元素 int curLen; //單鏈表當前元素數 Link<T> * setPos(const int i); //返回下標為i的元素地址,函數類型為Link<T>的指針類型 public: InkList() //單鏈表的無參數構造函數構造函數 { head=tail=new Link<T>; curLen=0; } ~InkList() //單鏈表的析構函數 { Link<T> *tmp; while(head!=NULL) //從頭結點開始逐個刪除結點 { tmp=head; head=head->next; delete tmp; } } bool isEmpty(); //若鏈表為空,返回true void clear(); //清空鏈表,保留頭結點 int length(); //返回鏈表存儲元素個數 bool insFirst(const T value); //將value插入鏈表頭結點之后 bool append(const T value); //將value插入鏈表尾節點之后 bool delFirst(); //刪除頭結點之后的第一個元素 bool delEnd(); //刪除尾節點所指向的元素 void returnEnd(T &value); //用變量value返回尾結點的元素值 bool insert(const int p,const T value); //在下標為p的位置插入value bool deleteElem(const int p); //刪除下標為p位置的元素 bool getValue(const int p,T &value); //用變量value返回下標為p的元素 bool setValue(const int p,const T value); //設置下標為p的元素值為value bool getPos(int &p,const T value); //用變量p返回第一個元素值為value的元素下標 void display(); //輸出鏈表的元素個數和每個元素的值 }; template <class T> Link<T> * InkList<T>::setPos(const int i) //返回下標為i的元素地址 { //在類的外部實現類的函數時,要用 函數類型 類名::函數名(參數) 的方式實現 int coun=-1; //計數器初始化為-1,若i為-1,直接返回頭結點 Link<T> *p; p=head; while(p!=NULL&&coun<i) //從頭節點開始逐個訪問直到無結點可訪問或找到i結點 { p=p->next; coun++; } if(coun==i) //若找到i結點,返回它的指針 return p; else //沒找到返回NULL return NULL; } template <class T> bool InkList<T>::isEmpty() //若鏈表為空,返回true { if((head->next)==NULL) //頭尾節點相同,表示沒有元素,返回true return true; else return false; //還有其他種實現方法,如curLen為0返回true } template <class T> void InkList<T>::clear() //清空鏈表,保留頭結點 { Link<T> *p,*q; //p指向要刪除的結點的下一結點,q指向要刪除的結點 p=head->next; //頭結點不要刪除,p首先指向第一個元素 head->next=NULL; tail=head; curLen=0; while(p!=NULL) { q=p; //先將p的地址賦給q,在讓p指向下一結點,最后刪除q指向的元素 p=p->next; delete q; } } template <class T> int InkList<T>::length() //返回鏈表存儲元素個數 { return curLen; } template <class T> bool InkList<T>::insFirst(const T value) //將value插入鏈表頭結點之后 { if((head->next)==NULL) //鏈表為空時,插入元素后要修改尾指針 { Link<T> *p=new Link<T>(value); //p指向一個新建的Link對象,它的值為value head->next=p; tail=p; } else //鏈表不空時,插入元素的next指針要指向當前第一個元素 { Link<T> *p=new Link<T>(value,head->next); head->next=p; } curLen++; //鏈表長度+1 return true; } template <class T> bool InkList<T>::append(const T value) //將value插入鏈表尾節點之后 { Link<T> *p=new Link<T>(value); tail->next=p; tail=p; curLen++; return true; } template <class T> bool InkList<T>::delFirst() //刪除頭結點之后的第一個元素 { if(head->next!=NULL) { Link<T> *p; p=head->next; if(tail==p) tail=head; head->next=p->next; delete p; curLen--; return true; } else { cout << "The link is empty" <<endl; return false; } } template <class T> bool InkList<T>::delEnd() //刪除尾節點所指向的元素 { if(tail==head) { cout << "The link is empty" <<endl; return false; } else { Link<T> *p,*q; //p指向最后一個結點,q指向它的前驅 p=head; while(p->next!=NULL) { q=p; p=p->next; } //另一種實現方法 //p=tail; //q=setPos(curLen-2); delete p; tail=q; //尾節點元素被刪除,q成為新的尾節點 q->next=NULL; //將q的next置空 curLen--; return true; } } template <class T> void InkList<T>::returnEnd(T &value) //用變量value返回尾結點的元素值 { if(tail==head) { cout << "The List is empty" <<endl; return; } else { value=tail->data; } } template <class T> bool InkList<T>::insert(const int i,const T value) //在下標為p的位置插入value { if(i<0||i>curLen-1) //判斷位置是否合法 { cout << "Illegal insert position" <<endl; return false; } Link<T> *p,*q; //q為新插入結點,p為它的前驅 p=setPos(i-1); q=new Link<T>(value,p->next);//先將q的next指向p的next,再修改p的next p->next=q; if(p==tail) tail=q; curLen++; return true; } template <class T> bool InkList<T>::deleteElem(const int i) //刪除下標為p位置的元素 { Link<T> *p,*q; //q為要刪除的結點,p為它的前驅 if((p=setPos(i-1))==NULL||p==tail) { cout << "Illegal delete position" <<endl; return false; } else { q=p->next; if(q==tail) //若刪除的為尾節點,修改尾指針 tail=p; p->next=q->next; //先將p的next修改為q的next,再刪除q delete q; curLen--; return true; } } template <class T> bool InkList<T>::getValue(const int i,T &value) //用變量value返回下標為p的元素 { Link<T> *p; if((p=setPos(i))!=NULL) { value = p->data; return true; } else { cout << "Illegal inquire position" <<endl; return false; } } template <class T> bool InkList<T>::setValue(const int i,const T value) //設置下標為p的元素值為value { Link<T> *p; if((p=setPos(i))!=NULL) { p->data=value; return true; } else { cout << "Illegal modify position" << endl; return false; } } template <class T> bool InkList<T>::getPos(int &i,const T value) //用變量p返回第一個元素值為value的元素下標 { if(head->next==NULL) { cout << "The list is empty" <<endl; return false; } Link<T> *p; p=head->next; int coun=0; while(p->next!=NULL&&(p->data)!=value) { p=p->next; coun++; } if((p->data)==value) { i=coun; return true; } else { cout << "non-existed" <<endl; return false; } } template <class T> void InkList<T>::display() //輸出鏈表的元素個數和每個元素的值 { Link<T> *p; p=head; int coun=0; cout << "length:" << curLen <<endl; while(p->next!=NULL) { p=p->next; cout << coun++ <<":" <<p->data <<endl; } cout << "tail:" << tail->data <<endl; } /* 設基本操作為 清空鏈表(clear)、返回鏈表長度(length)、判斷鏈表是否為空(isEmpty) 1.限制單鏈表除基本操作外只能夠使用 頭插法(insFirst)/push、刪除第一個元素(delFirst)/pop、 返回首個元素的值(getValue(0,T &value))/top 則單鏈表變為棧 2.限制單鏈表除基本操作外只能夠使用 尾插法(insEnd)/push、刪除第一個元素(delFirst)/pop、 返回首個元素的值(getValue(0,T &value))/front、返回末尾元素的值(returnEnd) 則鏈表變為隊列 */ int main() { InkList<int> l; int a; for(int i=0;i<20;i++) { l.append(i); } l.display(); l.delEnd(); l.display(); l.clear(); l.display(); for(int i=0;i<20;i++)l.insFirst(i); l.display(); l.delFirst(); l.display(); l.returnEnd(a); cout << a <<endl; l.insert(0,233); l.insert(19,244); l.insert(20,255); l.insert(22,555); l.display(); l.deleteElem(0); l.deleteElem(20); l.display(); l.getValue(0,a);cout << a <<endl; l.getValue(19,a);cout << a <<endl; l.setValue(19,999); l.display(); l.getPos(a,999);cout << a <<endl; l.getPos(a,18);cout << a <<endl; return 0; }
