C++模板实现链表

来源:互联网 发布:ubuntu 17.10 samba 编辑:程序博客网 时间:2024/06/14 15:39

单链表是一种非常基本的数据结构. 虽然C++ STL中已经存在功能强大的List,但我们通过自己实现单链表,对于锻炼C++的基本功,加深对编程的理解与认识还是很有益的. 另外,自己的代码,在使用过程中更容易和敢于修改,更容易灵活定制自己的需求.
在实现单链表的过程中,选用模板,可以使得链表得到极大的灵活性.代码的可复用性大大增强.
核心代码分析解读:
1. 定义存放单个节点的数据结构: T可以在调用过程中灵活变换数据类型(基本数据类型,该程序的T不能支持对象数据类型). data为存放的数据, next为指向的下一个节点.
template struct LinkNode
{
T data;
LinkNode* next;
};
2.在添加节点时,我们只传入值.在函数内部构造节点.注意用new来分配内存.之后先将新节点的next指向node后面的节点(假定在node后面插入节点),然后将node的next指向新生成的节点.顺序很重要.
LinkNode *linkNode = new LinkNode();
linkNode->data = data;
linkNode->next = node->next;
node->next = linkNode;
3. 在删除时,需要准备要删除的前驱节点进行记录.是前驱节点指向后继节点.之后可以删除当前节点.注意释放内存,避免内存泄露.之后将指针指向NULL,避免野指针.
preNode->next = needRemoveNode->next;
delete needRemoveNode;
needRemoveNode = NULL;
4. 在对象释放的时候,C++会自动调用析构函数.在析构函数中,要记得释放内存,与将指针置NULL.
LinkNode *iter = head;
LinkNode *preIter = iter;
while (NULL != preIter->next)
{
iter = preIter->next;
preIter->next = iter->next;
cout << iter->data << ” will be deleted in destruct function.” << endl;
delete iter;
iter = NULL;
}
5. C++使用模板时,要注意在调用时,同时要包含.h与.cpp文件.或者将模板函数实现也写在.h文件中(双刃剑). 与通常只包含.h文件不同. 另外,要注意代码改动后,有时候需要进行进行全部重新编译,这个是因为模板在实例化时会产生二次编译,仅使用增量编译有时会产生错误.

程序运行结果如下图:

C++头文件如下:

#ifndef _LINK_LIST_H_#define _LINK_LIST_H_#include "Constant.h"template<typename T> struct LinkNode{    T data;    LinkNode* next;};template<typename T, const unsigned int capacity> class LinkList{public:    LinkList();    ~LinkList();    bool isEmpty();    bool isFull();    bool insertFromHead(T data);    bool insertAtLocation(T data, unsigned int n);    bool deleteFromHead();    bool deleteFromHead(T& data);    bool deleteAtLocation(unsigned int n);    bool deleteViaData(T data);    bool getFirst(T& data);    unsigned int getSize();    void print();private:    unsigned int linkNodeNum;    LinkNode<T> *head = NULL;};#endif // !_LINK_LIST_H_

C++源文件如下:

#include "LinkList.h"#include <string>#include <iostream>using namespace std;template<typename T, const unsigned int capacity> LinkList<T, capacity>::LinkList(){    linkNodeNum = 0;    head = new LinkNode<T>;    head->next = NULL;    memset(head, 0, sizeof(head));}template<typename T, const unsigned int capacity> LinkList<T, capacity>::~LinkList(){    LinkNode<T> *iter = head;    LinkNode<T> *preIter = iter;    while (NULL != preIter->next)    {               iter = preIter->next;        preIter->next = iter->next;        cout << iter->data << " will be deleted in destruct function." << endl;        delete iter;        iter = NULL;    }}template<typename T, const unsigned int capacity> bool LinkList<T, capacity>::isEmpty(){    if (NULL == head->next)        return true;    return false;}template<typename T, const unsigned int capacity> bool LinkList<T, capacity>::isFull(){    if (capacity == linkNodeNum)        return true;    return false;}template<typename T, const unsigned int capacity> bool LinkList<T, capacity>::insertFromHead(T data){    if (NULL == head)    {        head = new LinkNode<T>;        head->next = NULL;    }    if (isFull())    {        return false;    }    LinkNode<T> *linkNode = new LinkNode<T>();    linkNode->data = data;    linkNode->next = NULL;    LinkNode<T> *afterNode = head->next;    head->next = linkNode;    linkNode->next = afterNode;    linkNodeNum++;    return true;}//Insert data after nth nodetemplate<typename T, const unsigned int capacity> bool LinkList<T, capacity>::insertAtLocation(T data, unsigned int n){    if (isFull())        return false;    if (linkNodeNum < n)    {        return false;    }    else    {        //Insert after n        LinkNode<T> *node = head;        //Insert at last        for (unsigned int i = 0; i < n; i++)        {            if (NULL != node->next)            {                node = node->next;            }            else            {                //need log the error                return false;            }        }        LinkNode<T> *linkNode = new LinkNode<T>();        linkNode->data = data;        linkNode->next = node->next;        node->next = linkNode;        linkNodeNum++;    }    return true;}template<typename T, const unsigned int capacity> bool LinkList<T, capacity>::deleteFromHead(){    bool rs = false;    if (isEmpty())    {        rs = false;    }    else    {        LinkNode<T> *needRemoveNode = head->next;        if (NULL == needRemoveNode)        {            rs = false;        }        else        {            LinkNode<T> *nextNode = needRemoveNode->next;            head->next = nextNode;            needRemoveNode->next = NULL;            delete needRemoveNode;            linkNodeNum--;            rs = true;        }    }    return rs;}template<typename T, const unsigned int capacity>bool LinkList<T, capacity>::deleteFromHead(T& data){    bool rs = false;    if (isEmpty())    {        rs = false;    }    else    {        LinkNode<T> *needRemoveNode = head->next;        if (NULL == needRemoveNode)        {            rs = false;        }        else        {            data = needRemoveNode->data;            LinkNode<T> *nextNode = needRemoveNode->next;            head->next = nextNode;            needRemoveNode->next = NULL;            delete needRemoveNode;            linkNodeNum--;            rs = true;        }    }    return rs;}template<typename T, const unsigned int capacity> bool LinkList<T, capacity>::deleteAtLocation(unsigned int n){    if (isEmpty())    {        return false;    }    if (n > linkNodeNum)    {        return false;    }    else    {        LinkNode<T> *needRemoveNode = head;        LinkNode<T> *preNode = NULL;        for (unsigned int i = 0; i < n; i++)        {            preNode = needRemoveNode;            needRemoveNode = needRemoveNode->next;            if (NULL == needRemoveNode)            {                return false;            }        }        preNode->next = needRemoveNode->next;        delete needRemoveNode;        needRemoveNode = NULL;        linkNodeNum--;    }    return true;}template<typename T, const unsigned int capacity> bool LinkList<T, capacity>::deleteViaData(T data){    if (isEmpty())    {        return false;    }    bool isFind = false;    LinkNode<T> *iter = head;    while(NULL != iter->next)    {        LinkNode<T> *preNode = iter;        iter = iter->next;        try        {            if (data == iter->data)            {                preNode->next = iter->next;                delete iter;                iter = NULL;                isFind = true;                linkNodeNum--;                break;            }        }        catch (exception e)        {            cout << e.what() << endl;            return false;        }    }    return isFind;}template <typename T, const unsigned int capacity>bool LinkList<T, capacity>::getFirst(T& data){    bool rs = false;    if (isEmpty())    {        rs = false;    }    else    {        if ((NULL == head) || (NULL == head->next))        {            rs = false;        }        else        {            data = head->next->data;            rs = true;        }    }    return rs;}template<typename T, const unsigned int capacity>unsigned int LinkList<T, capacity>::getSize(){    return linkNodeNum;}template<typename T, const unsigned int capacity> void LinkList<T, capacity>::print(){    LinkNode<T>* iter = head;    while (NULL != iter->next)    {        iter = iter->next;        cout << iter->data << "  ";    }    cout << endl;}

测试代码如下:

void testLinkList(){    LinkList<int,LINK_NODE_SIZE> *linkList = new LinkList<int, LINK_NODE_SIZE>();    linkList->insertFromHead(9);    linkList->print();    linkList->insertFromHead(7);    linkList->print();    linkList->insertAtLocation(8, 1);    linkList->print();    linkList->insertAtLocation(6, 8);    linkList->print();    linkList->insertAtLocation(5, 3);    linkList->print();    linkList->insertFromHead(4);    linkList->print();    linkList->insertFromHead(3);    linkList->print();    linkList->deleteFromHead();    linkList->print();    linkList->deleteViaData(7);    linkList->print();    linkList->deleteAtLocation(3);    linkList->print();    linkList->deleteAtLocation(14);    linkList->print();    linkList->deleteViaData(0);    linkList->print();    linkList->deleteViaData(1.2);    linkList->print();    delete linkList;    linkList = NULL;}void testLinkList2(){    LinkList<string, LINK_NODE_SIZE> *linkList = new LinkList<string, LINK_NODE_SIZE>();    linkList->insertFromHead("AA");    linkList->print();    linkList->insertFromHead("BB");    linkList->print();    linkList->insertAtLocation("CC", 1);    linkList->print();    linkList->insertAtLocation("DD", 8);    linkList->print();    linkList->insertAtLocation("EE", 3);    linkList->print();    linkList->insertFromHead("FF");    linkList->print();    linkList->insertFromHead("GG");    linkList->print();    linkList->deleteFromHead();    linkList->print();    linkList->deleteViaData("FF");    linkList->print();    linkList->deleteAtLocation(3);    linkList->print();    linkList->deleteAtLocation(14);    linkList->print();    linkList->deleteViaData("DDD");    linkList->print();    delete linkList;    linkList = NULL;}
0 0
原创粉丝点击