1. 程式人生 > >C++中實現一個簡單的單向連結串列

C++中實現一個簡單的單向連結串列

最近在linux了一個簡單的單向連結串列,直接上程式碼

連結串列標頭檔案   list.h

#ifndef _LIST_H_
#define _LIST_H_

typedef int T;

template<typename T>
class List
{
private:
    struct Node
    {
        T      data;
        Node*  next;
        Node(const T& d=T()):data(d),next(NULL){} //零初始化
    };
    Node* head;//頭指標,用來儲存頭節點的地址
    int len;
public:
    List():head(NULL),len(0){}
    List(const List& l);
    void operator=(const List& l);
    ~List();
    T getElementAtIndex(int index)const;//取得連結串列中指定位置的元素值
    List<T>& push_front(const T& d);//前插
    List<T>& push_back(const T& d); //尾插
    int size()const;//獲取連結串列中節點個數
    Node*& getptr(int pos); //在連結串列中找指向指定位置的指標
    List<T>& insert(const T& d,int pos); //在任意位置插入
    void travel()const; //遍歷
    void clear(); //清空連結串列
    void erase(int pos); //刪除連結串列中指定位置的元素
    int find(const T& d)const; //查詢指定數值的元素在連結串列中出現的位置
    void remove(const T& d); //刪除連結串列中指定的元素
    void set(int pos,const T& d);
    bool empty()const;
    const T& front()const;
    const T& back()const;
    void reverse();//連結串列元素倒置
};

#endif

連結串列實現檔案 list.cpp

#include <iostream>
#include <string>
#include "list.h"

using namespace std;

template<typename T>
List<T>::List(const List<T>& l)
{
    len = l.len;
    Node* items[len];
    for(int i=0;i<len;i++)
    {
        items[i] = new Node(l.getElementAtIndex(i));
    }
    for(int i=0;i<len-1;i++)
    {
        items[i]->next = items[i+1];
    }
    head = items[0];
}

template<typename T>
void List<T>::operator=(const List<T>& l)
{
    clear();    
    len = l.len;
    Node* items[len];
    for(int i=0;i<len;i++)
    {
        items[i] = new Node(l.getElementAtIndex(i));
    }
    for(int i=0;i<len-1;i++)
    {
        items[i]->next = items[i+1];
    }
    head = items[0];
}

template<typename T>
List<T>::~List()
{
    clear();
}

//取得連結串列中指定位置的元素值
template<typename T>
T List<T>::getElementAtIndex(int index)const  
{
    if(index < 0 || index >= len) throw "索引位置越界";
    if(index == 0) return head->data;
    Node* p = head;
    for(int i=1;i<index;i++)
    {
        p = p->next;
    }
    return p->next->data;
}

//前插
template<typename T>
List<T>& List<T>::push_front(const T& d)
{
    insert(d,0);
    return *this;
}

//後插
template<typename T>
List<T>& List<T>::push_back(const T& d)
{
    insert(d,len);
    return *this;
}

//獲取連結串列中節點個數
template<typename T>
int List<T>::size()const
{
    return len;
}
    
//在連結串列中找指向指定位置的指標
template<typename T>
typename List<T>::Node*& List<T>::getptr(int pos)
{
    if(pos < 0 || pos > len) pos = 0;
    if(pos == 0) return head;
    Node* p = head;
    for(int i=1;i<pos;i++)
    {
        p = p->next;
    }
    return p->next;
}

//在任意位置插入節點
template<typename T>
List<T>& List<T>::insert(const T& d,int pos)
{
    Node*& pn = getptr(pos);
    Node* p = new Node(d);
    p->next = pn;
    pn = p;
    ++len;
    return *this;
}

//遍歷
template<typename T>
void List<T>::travel()const
{
    Node* p = head;
    while(p)
    {
        cout << p->data << ' ';
        p = p->next;
    }
    cout << endl;
}

//清空連結串列
template<typename T>
void List<T>::clear()
{
    while(head)
    {
        Node* p = head->next;
        delete head;
        head = p;
    }
    len = 0;
}
    
//刪除連結串列中指定位置的節點
template<typename T>
void List<T>::erase(int pos)
{
    if(pos < 0 || pos >= len) return;//有效位置為0~len-1
    Node*& pn = getptr(pos);
    Node* p = pn;
    pn = pn->next;
    delete p;
    --len;
}

//查詢指定數值的節點在連結串列中出現的位置
template<typename T>
int List<T>::find(const T& d)const
{
    Node* p = head;
    int pos = 0;
    while(p)
    {
        if(p->data == d)
          return pos;
        else
          p = p->next;
        ++pos;
    }
    return -1;
}
    
//刪除連結串列中指定數值的節點
template<typename T>
void List<T>::remove(const T& d)
{
    int pos;
    while((pos = find(d))!= -1)
    {
        erase(pos);
    }
}

//修改指定位置的節點資料
template<typename T>
void List<T>::set(int pos,const T& d)
{
    if(pos < 0 || pos >= len) return;
    getptr(pos)->data = d;
}

//判斷連結串列是否為空
template<typename T>
bool List<T>::empty()const
{
    return head == NULL;
}

//取得連結串列中第一個節點資料
template<typename T>
const T& List<T>::front()const
{
    if(empty()) throw "空";
    return head->data;
}

//取得連結串列中最後一個節點資料
template<typename T>
const T& List<T>::back()const
{
    if(empty()) throw "空";
    Node* p = head;
    while(p->next)
    {
        p = p->next;
    }
    return p->data;
}

//將連結串列中的元素倒置
template<typename T>
void List<T>::reverse()
{
    if(head == NULL) return;
    Node *pre,*cur,*next;
    pre = head;
    cur = head->next;
    while(cur)
    {
        next = cur->next;
         cur->next = pre;
         pre = cur;
         cur = next;
     }
     head->next = NULL;
     head = pre;
}


template class List<T>; // 顯式例項化

連結串列測試檔案 listTest.cpp

#include <iostream>
#include "list.h"

//typedef int T;
using namespace std;

int main()
{
    List<T> l;
    List<T> m;
    l.push_front(5); //5
    l.push_front(8); //8 5
    l.push_front(20);// 20 8 5
    l.insert(9,2); // 20 8 9 5
    l.insert(8,100); //6 20 8 9 5
    l.insert(11,-10);//11 6 20 8 9 5
    l.insert(9,2);//11 6 1 20 8 9 5
    l.push_back(10).push_back(19);//11 8 9 20 8 9 5 10 19
    l.travel();
    l.reverse();
    l.travel();

    l.remove(8);
    l.remove(9);
    l.set(1,33);
    l.set(l.find(19),-8);

//    cout << l.front() << "      " << l.back() << endl;
    l.travel();  // 11 33 5 10 -8

//    while(!l.empty()) l.erase(0);
 //   cout << l.size() << endl;
    
 //   cout << l.getElementAtIndex(0) << endl;
    m.insert(-9,0);
    m.insert(13,1);
    m.push_front(-5);
    m.push_back(2);
    cout << "========m連結串列原始值======" << endl;
    m.travel();// -5 -9 13 2

    m = l;
    cout <<"==========將連結串列m中元素倒置==========" << endl;
    m.reverse();
    m.travel();
    cout <<"===========程式結束======" << endl;

    return 0;
}