数据结构 之 链表

在介绍链表之前,先简单介绍一下缓存机制的三种策略:1、先进先出策略(FIFO),2、最少使用策略(LFU),3、最近最少使用策略(LRU)。单链表、循环链表、双向链表是我们最为常见的三种链表结构,一个链表是由多个链表节点连接而成,在单链表中,每个节点包含两个域:用来存储数据的数据域以及用来连接下一个节点的指针域(next),而在双向链表中指针域上不仅包含连接下一个节点的指针(next),还包含连接上一个节点的指针(pre)。另外,每个链表都会有个头指针,用来指向链表的第一个节点也就是链表的基地址,而在循环链表中最后一个节点的next指针指向的不是NULL,而是链表头指针,且双向循环链表中的头指针的prev指针指向的链表的最后一个节点。链表的插入和删除只需要考虑相邻节点指针的改变即可,所以时间复杂度为O(1),效率十分高,但是链表的随机访问的效率相对要低很多,因为链表无法像数组一样,通过首地址和下标,利用寻址公式直接计算得出对应的内存地址,而是需要指针一个节点一个节点的依次遍历,直到找到相应的节点为止,所以链表的随机访问时间复杂度为O(n),这里需要注意的是,双向链表如果要插入或删除指定节点时比单链表要高效多,虽然此时双向链表的时间复杂度为O(1)。链表相对于数组的优点是删除和插入相对高效,内存分配没有连续空间的要求,但缺点也很明显,节点中包含指针域,浪费内存,还有就是频繁的申请释放内存,容易产生内存碎片。结构如图所示:
数据结构 之 链表_第1张图片
不多说,直接上代码:

#include 
#include 

template 
class Node
{
public:
    T data;
    Node(T& item);
    Node* next;
    Node* pre;
};

template
class LinkList
{
public:
    LinkList();
    ~LinkList();
    int getSize(void);
    bool IsEmpty(void);
    int gotoNext(void);
    int setPostion(int pos);
    int getPostion(void);
    int InsertNodeBefore(T& data);
    int InsertNodeAfter(T& data);
    void DeleteNode(void);
    void getCurrNodeData(T& data);
    void setCurrNodeData(T& data);
    void clear();
    void print();

private:
    Node* head;
    Node* currNode;
    int size;
    int position;
    void freeNode(Node* p);
};

#endif
// LinkedList.cpp : 定义控制台应用程序的入口点。

#include "stdafx.h"
#include "LinkedList.h"

/* 链表节点构造函数 */
template 
Node::Node(T& item)
{
    data = item;
    next = NULL;
    pre = NULL;
}

/* 链表构造函数 */
template 
LinkList::LinkList()
{
    head = NULL;
    currNode = NULL;
    size = 0;
    position = -1;
}

/* 链表析构函数 */
template 
LinkList::~LinkList()
{
    clear();
}

/* 获取链表长度 */
template 
int LinkList::getSize(void)
{
    return size;
}

/* 判断链表是否为空 */
template 
bool LinkList::IsEmpty(void)
{
    return size==0?true:false;
}

/* 移动到下个节点,返回下个节点的位置值 */
template 
int LinkList::gotoNext(void)
{
    if(NULL == head)
    {
        return -1;
    }

    if(NULL == currNode)
    {
        return -1;
    }
    else
    {
        currNode = currNode->next;
        position = (position+1+1)%(size);
    }

    return position;
}

/* 将当前节点移动到指定节点值 */
template 
int LinkList::setPostion(int pos)
{
    if(pos >= size||pos < 0)
    {
        return -1;
    }

    position = 0;
    currNode = head;

    for(int i = 0; i < pos;i++)
    {
        position++;
        currNode = currNode->next;
    }

    return position;
}

/* 获取当前节点的位置 */
template 
int LinkList::getPostion(void)
{
    return position;
}

/* 在当前节点前插入新节点 */
template 
int LinkList::InsertNodeBefore(T& data)
{
    Node* p = new Node(data);

    if(0 == size)
    {
        head = p;
        head->next = head;
        head->pre = head;
        currNode = head;
        position++;
    }
    else
    {
        currNode->pre->next = p;
        currNode->pre = p;
        p->next = currNode;
        p->pre = currNode->pre->next; 

        if(head == currNode)
        {
            head = p;
        }
        currNode = p;
    }

    size++;

    return size;
}

/* 在当前节点后插入新节点 */
template 
int LinkList::InsertNodeAfter(T& data)
{
    Node* p = new Node(data);

    if(0 == size)
    {
        head = p;
        head->next = head;
        head->pre = head;   
        currNode = p;
    }
    else
    {
        currNode->next->pre = p; 
        p->next = currNode->next ;
        currNode->next = p;
        p->pre = currNode; 
        currNode = p;
    }

    size++;
    position++;
    return size;
}

/* 删除当前节点 */
template 
void LinkList::DeleteNode(void)
{
    if(0 == size)
    {
        return;
    }

    Node* p = currNode;

    currNode->pre->next = currNode->next;
    currNode->next->pre = currNode->pre;
    if(head == currNode)
    {
        head = currNode->next;
    }

    currNode = currNode->next;
    freeNode(p);
    size--;

    return ;
}

/* 释放指定节点的内存 */
template 
void LinkList::freeNode(Node* p)
{
    if(!p)
    {
        delete p;
    }

    return;
}

/* 获取当前节点的数据 */
template 
void LinkList::getCurrNodeData(T& data)
{
    if(currNode)
    {
        data = currNode->data;
    }

    return ;
}

/* 修改当前节点的数据 */
template 
void LinkList::setCurrNodeData(T& data)
{
    if(currNode)
    {
        currNode->data = data;
    }

    return ;
}

/* 清空链表 */
template 
void LinkList::clear()
{
    Node* p = currNode;

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

    head = NULL;
    currNode = NULL;
    size = 0;
    position = -1;

    return;
}

template 
void LinkList::print()
{
    Node* p = head;

    for(int i = 0;i < size;i++)
    {
        std::cout<<"data = "<data<next;
    }

    std::cout<<"====================================== "< linklist;
    
    linklist.InsertNodeAfter(a);
    linklist.InsertNodeAfter(b);
    linklist.InsertNodeAfter(c);
    linklist.InsertNodeAfter(d);
    linklist.InsertNodeAfter(e);
    linklist.print();

    std::cin.get();
	return 0;
}

运行结果如下图:
数据结构 之 链表_第2张图片

另外附上单向不循环链表的代码,供读者对比区别使用:

// 单链表.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include 
#include 

template 
class Node
{
public:
    T data;
    Node(T& item);
    Node* next;
};

template
class LinkList
{
public:
    LinkList();
    ~LinkList();
    int getSize(void);
    bool IsEmpty(void);
    int gotoNext(void);
    int getPostion(void);
    int InsertNode(T& data);
    int DeleteNode(void);
    void getCurrNodeData(T& data);
    void setCurrNodeData(T& data);
    void clear();
    void print();

private:
    Node* head;
    Node* currNode;
    int size;
    int position;
    void freeNode(Node* p);
};

/* 链表节点构造函数 */
template 
Node::Node(T& item)
{
    data = item;
    next = NULL;
}

/* 链表构造函数 */
template 
LinkList::LinkList()
{
    head = NULL;
    currNode = NULL;
    size = 0;
    position = -1;
}

/* 链表析构函数 */
template 
LinkList::~LinkList()
{
    clear();
}

/* 获取链表长度 */
template 
int LinkList::getSize(void)
{
    return size;
}

/* 判断链表是否为空 */
template 
bool LinkList::IsEmpty(void)
{
    return size==0?true:false;
}

/* 移动到下个节点,返回下个节点的位置值 */
template 
int LinkList::gotoNext(void)
{
    if(NULL == head)
    {
        return -1;
    }

    if(NULL == currNode)
    {
        return -1;
    }
    else
    {
        currNode = currNode->next;
        position++
    }

    return position;
}

/* 获取当前节点的位置 */
template 
int LinkList::getPostion(void)
{
    return position;
}

/* 在当前节点前插入新节点 */
template 
int LinkList::InsertNode(T& data)
{
    Node* p = new Node(data);

    if(0 == size)
    {
        head = p;
        head->next = NULL;
        currNode = p;
        
    }
    else
    {
        p->next = currNode->next;
        currNode->next = p;
        currNode = p;
    }

    size++;
    position++;
    return size;
}


/* 删除当前节点 */
template 
int LinkList::DeleteNode(void)
{
    if(0 == size)
    {
        return -1;
    }
    
    Node* p = head;
    Node* tmp;
    for(int i = 0;i < size;i++)
    {
        if(NULL == p)
        {
            return -1;
        }

        if(p->next == currNode)
        {
            p->next = currNode->next;
            break;
        }

        p = p->next;
    }

    tmp = currNode;

    if(currNode == head)
    {
        head = currNode->next;
    }

    if(NULL == currNode->next)
    {
        position--;
        currNode = p;
    }
    else
    {
        currNode = currNode->next;
    }
    

    freeNode(p);
    size--;
    if(0 == size)
    {
       position = -1;
    }

    return 0;
}

/* 释放指定节点的内存 */
template 
void LinkList::freeNode(Node* p)
{
    if(!p)
    {
        delete p;
    }

    return;
}

/* 获取当前节点的数据 */
template 
void LinkList::getCurrNodeData(T& data)
{
    if(currNode)
    {
        data = currNode->data;
    }

    return ;
}

/* 修改当前节点的数据 */
template 
void LinkList::setCurrNodeData(T& data)
{
    if(currNode)
    {
        currNode->data = data;
    }

    return ;
}

/* 清空链表 */
template 
void LinkList::clear()
{
    if(0 == size)
    {
        return;
    }

    Node* p = head;
    Node* tmp = head->next;
    while(p)
    {
        freeNode(p);
        p = tmp;
        if(tmp)
        {
            tmp = tmp->next;
        }
    }

    head = NULL;
    currNode = NULL;
    size = 0;
    position = -1;

    return;
}

template 
void LinkList::print()
{
    if(0 == size)
    {
        return;
    }

    Node* p = head;
    Node* tmp = head->next;
    while(p)
    {
        std::cout<data<next;
        }
    }

    return;
}

int main(int argc, _TCHAR* argv[])
{
    int a = 10,b=20,c=30,d=40,e=50;
    LinkList list;
    list.InsertNode(a);
    list.InsertNode(b);
    list.InsertNode(c);
    list.DeleteNode();
    list.InsertNode(d);
    list.InsertNode(e);
    list.print();
    std::cin.get();
	return 0;
}

你可能感兴趣的:(数据结构)