• 数据结构之双向链表


      数据结构中的链表的特点是元素都是FIFO(First In First Out),其中链表又分单向链表与双向链表。

    单向链表中每个元素都有一个指向下一元素的指针,而双向链表在单向链表的基础上,增加了一个指向前一个元素的指针。

        这几天休假,我继续造轮子,重新实现了一下双向链表。

        首先是链表节点数据的定义,见如下代码:

    template <class T>
    class Node
    {
    public:
        Node
    <T>* next;
        Node
    <T>* prior;
        T data;

    public:
        Node(){};
        
    ~Node(){};
        Node
    <T>* GetNext();
        Node
    <T>* GetPrior();
        
    void GetData(T& data);
        
    void ChangeData(T data);
    };

    template
    <class T>
    void Node<T>::GetData(T& _data)
    {
        _data 
    = data;
    }

    template
    <class T>
    Node
    <T>* Node<T>::GetNext()
    {
        
    return next;
    }

    template
    <class T>
    Node
    <T>* Node<T>::GetPrior()
    {
        
    return prior;
    }

    template
    <class T>
    void Node<T>::ChangeData(T _data)
    {
        data 
    = _data;
    }

      Node结点类是一个模板类,具体最基本链表访问的方法。

      接下来,才是最重要链表类:

    链表声明
    template <class T>
    class DoubleLinkedList:public Node<T>
    {
    public:
        Node
    <T>* start;
        Node
    <T>* end;

    public:
        DoubleLinkedList();
        
    ~DoubleLinkedList();
        
    void ForwardList();
        
    void BackwardList();
        
    bool Remove(Node<T>* node);
        
    void Add(T data);
        Node
    <T>* Search(T data);
        Node
    <T>* GetStart();
    };


        链表声明类中有一个start 和 end结点,便于遍历链表, 我先写上增加链表结点的方法,

    添加结点
    template<class T>
    void DoubleLinkedList<T>::Add(T data)
    {
        Node
    <T>* node = new Node<T>();
        
    if(!node)
        {
            cout 
    << "assign memeory failure!"<<endl;
            exit(
    0);
        }
        node
    ->data = data;
        
    if(!start)       //add first node
        {
            start 
    = end = node;
            start
    ->prior = NULL;
        }
        
    else
        {
            node
    ->prior= end;
            end
    ->next = node;
            node
    ->next = NULL;
            end 
    = node;
        }
    }

       起始结点的上一个结果指针为NULL,同理最后一个结点的下一个结点的指针也为NULL。

    遍历链表
    template<class T>
    void DoubleLinkedList<T>::ForwardList()
    {
        Node
    <T>* p = start;
        
    if(!p)
        {
            cout 
    << "the double linked list is empty" << endl;
            
    return;
        }
        cout 
    << "forward double linked list:";
        
    while(p)
        {
            cout 
    << p->data << "  ";
            p 
    = p->GetNext();
        }
        cout 
    << endl;
    }

    template
    <class T>
    void DoubleLinkedList<T>::BackwardList()
    {
        Node
    <T>* p = end;
        
    if(!p)
        {
            cout 
    << "the double linked list is empty" << endl;
            
    return;
        }
        cout 
    << "backward double linked list:";
        
    while(p)
        {
            cout 
    << p->data << "  ";
            p 
    = p->prior;
        }
        cout 
    << endl;
    }

      我分别实现了从起始结点向后遍历以及从尾结点向前遍历的二种方法。其中就利用到链表中的start结点指针与end结点指针。

    移除结点
    template<class T>
    bool DoubleLinkedList<T>::Remove(Node<T>* node)
    {
        
    if(!node)
        {
            cout 
    << "the node wanted to deleted is null" << endl;
            
    return 0;
        }
        
    if(node->next)
        {
            
    if(node->prior)  //remove the middle node
            {
                node
    ->next->prior = node->prior;
                node
    ->prior->next = node->next;
            }
            
    else      //remove first node;
            {
                node
    ->next->prior = NULL;
                start 
    = node->next;
            }
        }
        
    else
        {
            
    if(node->prior)  //remove the last node
            {
                node
    ->prior->next = NULL;
                end 
    = node;
            }
            
    else        //remove the only node
            {
                start 
    = end = NULL;
            }
        }
    }

        移除结点稍微要麻烦点,要考虑要删除的结果是否为起始结点。

        到此差不多就完成了链表所功能,包括查询、添加、修改以及移除功能。

        最后只剩下测试程序了。

       

    测试程序
    #include "stdafx.h"
    #include 
    <iostream>
    #include 
    <string>
    #include 
    "DoubleLinkedList.h"
    using namespace std;


    int _tmain(int argc, _TCHAR* argv[])
    {
        
    //test double linked list
        
    //Node<int> a;
        DoubleLinkedList<int> list;
        
    for(int i=0;i<10;i++)
        {
           list.Add(i
    +1);
        }
        list.ForwardList();
        list.BackwardList();

        
    //add new node
        list.Add(12);
        list.ForwardList();

        
    //find the first node
        cout << "search node 3:" <<endl;
        Node
    <int>* midNode = list.Search(3);
        
    if(midNode)
        {
            
    //remove middle node
            cout << "remove middle node:"<<endl;
            list.Remove(midNode);
            list.ForwardList();
        }
        
    else
        {
            cout 
    << "can not find"<<endl;
        }

        Node
    <int>* firstNode = list.Search(1);
        
    if(midNode)
        {
            
    //remove middle node
            cout << "remove fist node:"<<endl;
            list.Remove(firstNode);
            list.ForwardList();
        }
        
    else
        {
            cout 
    << "can not find"<<endl;
        }


        Node
    <int>* lastNode = list.Search(12);
        
    if(midNode)
        {
            
    //remove middle node
            cout << "remove last node:"<<endl;
            list.Remove(lastNode);
            list.ForwardList();
        }
        
    else
        {
            cout 
    << "can not find"<<endl;
        }


        cout 
    << "chaged node data from 10 to 11:" <<endl;
        Node
    <int>* changedNode  = list.Search(10);
        
    if(changedNode)
        {
            changedNode
    ->ChangeData(11);
            list.ForwardList();
        }

        
        
    int wait;
        cin 
    >> wait;
        
    return 0;
    }

      在我本机上测试通过!
    顺便附上下载地址:下载

  • 相关阅读:
    ajax同步和异步
    vue组件
    type of的返回值有哪些
    git配置
    vue 获取时间戳对象转换为日期格式
    JavaScript运行机制
    单页面开发首屏加载慢,白屏如何解决
    单页面和多页面开发的优缺点
    【安全测试】sql注入
    【Python学习一】使用Python+selenium实现第一个自动化测试脚本
  • 原文地址:https://www.cnblogs.com/repository/p/1918972.html
Copyright © 2020-2023  润新知