单链表——C++模板实现

用模板技术实现链表可适用不同类型的数据类型

单链表:每个结点只包含该结点存储的数据以及直接后继的地址信息

头结点:头结点不存储数据但是存储下一个结点的地址,只是用来方便遍历链表

这里的头结点,需要单独来处理,因为当泛指类型为类类型时,若由于研发人员定义的类有问题,然后存储在链表里,那么抛异常就会抛到链表类这里来了,所以头结点的value用占位数组char reserved[sizeof(T)]来实现,而非直接定义一个泛指类型T value。在内存排布上需要跟普通结点一样。

插入结点:

删除结点:

 

#ifndef __LINKLIST_H
#define __LINKLIST_H

template <typename T>
class LinkList
{
private:
    struct Node
    {
        T value;
        Node* next;
    };
    //若T为类类型,若创建对象时,泛指类型抛出了异常,就会出问题,为了程序的健壮性,头节点单独定义,定义一个同样大小空间的数组占位,这样可避免这种情况发生。
    mutable struct
    {
        char reserved[sizeof(T)];
        Node* next;
    }m_header;

    int m_length;

    //返回i位置对应的节点,因为操作会经常用到,单独做成一个函数调用会更简洁
    Node* position(int i) const
    {
        Node* ret = reinterpret_cast<Node*>(&m_header);

        for(int p=0; p<i; p++)
        {
            ret = ret->next;
        }

        return ret;
    }

public:
    LinkList()
    {
        m_header.next = NULL;
        m_length = 0;
    }

    bool insert(int i, const T& e)
    {
        bool ret = (0 <= i) && (i <= m_length);

        if(ret)
        {
            Node* node = new Node();

            if(node)
            {
                Node* current = position(i);

                node->value = e;
                node->next =  current->next;
                current->next = node;

                m_length++;
            }
            else
            {
                cout << "No memory to insert new element..." << endl;
            }
        }

        return ret;
    }

    //在尾部插入
    bool insert(const T& e)
    {
        return insert(m_length, e);
    }

    bool remove(int i)
    {
        bool ret = (0 <= i) && (i < m_length);

        if(ret)
        {
            Node* toDel = position(i)->next;
            position(i)->next = toDel->next;

            m_length--;

            delete toDel;
        }

        return ret;
    }

    bool set(int i, const T& e)
    {
        bool ret = (0 <= i) && (i < m_length);

        if(ret)
        {
            position(i)->next->value = e;
        }

        return ret;
    }

    bool get(int i, T& e) const
    {
        bool ret = (0 <= i) && (i < m_length);

        if(ret)
        {
            e = position(i)->next->value;
        }

        return ret;
    }

    T get(int i) const
    {
        T ret;

        if( !get(i, ret) )
        {
            cout << "Invalid Parameter i to get element..." << endl;
        }

        return ret;
    }

    int find(const T& e) const
    {
        int ret = -1;
        int i = 0;

        Node* node = m_header.next;

        while(node)
        {
            if(node->value == e)
            {
                ret = i;
                break;
            }
            else
            {
                node = node->next;
                i++;
            }
        }

        return ret;
    }

    int length() const
    {
        return m_length;
    }

    void clear()
    {
        while(m_header.next)
        {
            Node* toDel = m_header.next;
            m_header.next = toDel->next;

            m_length--;

            delete toDel;
        }
    }

    ~LinkList()
    {
        clear();
    }
};

#endif
#include<iostream>
#include "LinkList.h"

using namespace std;

int main()
{
    LinkList<int> list;

    for(int i = 0; i < 5; i++)
    {
        list.insert(0, i);
        list.set(0, i*i);
    }

    for(int i = 0; i < list.length(); i++)
    {
        cout << list.get(i) << " ";
    }

    cout << endl;

    list.remove(2);

    for(int i = 0; i < list.length(); i++)
    {
        cout << list.get(i) << " ";
    }

    list.clear();

    for(int i = 0; i < list.length(); i++)
    {
        cout << list.get(i) << " ";
    }


    return 0;
}
发布了21 篇原创文章 · 获赞 5 · 访问量 2257

猜你喜欢

转载自blog.csdn.net/PTA123/article/details/105349161