單鏈表模板類


#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;
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM