189 8069 5689

数据结构(七)——双向链表-创新互联

数据结构(七)——双向链表

一、双向链表简介

1、单链表的缺陷

单链表只能从头结点开始访问链表中的数据元素,如果需要逆序访问单链表中的数据元素将极其低效。

10年积累的网站设计制作、成都网站制作经验,可以快速应对客户对网站的新想法和需求。提供各种问题对应的解决方案。让选择我们的客户得到更好、更有力的网络服务。我虽然不认识你,你也不认识我。但先网站设计后付款的网站建设流程,更有石拐免费网站建设让你可以放心的选择与我们合作。

2、双向链表的结构

双链表是链表的一种,由节点组成,每个数据结点中都有两个指针,分别指向直接后继和直接前驱。
数据结构(七)——双向链表

3、双向链表类的基本结构

template 
class DualLinkedList:public List
{
protected:
  struct Node:public Object
  {
    T value;//数据域
    Node* next;//后继指针域
    Node* pre;//前驱
  };
  mutable struct:public Object
  {
    char reserved[sizeof(T)];//占位空间
    Node* next;
    Node* pre;
  }m_header;
  int m_length;
  int m_step;
  Node* m_current;
}

二、双向链表的操作

1、双向链表的插入操作

数据结构(七)——双向链表

bool insert(int index, const T& value)
    {
      //判断目标位置是否合法
      bool ret = (0 <= index) && (index <= m_length);
      if(ret)
      {
          //创建新的结点
          Node* node = createNode();
          if(node != NULL)
          {
              //当前结点定位到目标位置
              Node* current = position(index);
              //当前结点的下一个结点
              Node* next = current->next;
              //修改插入结点的值
              node->value = value;
              //将当前位置的下一个结点作为插入结点的下一个结点
              node->next = next;
              //将要插入结点作为当前结点的下一个结点
              current->next = node;
              if(current != reinterpret_cast(&m_header))
              {
                  node->pre = current;
              }
              else
              {
                  node->pre = NULL;
              }
              if(next != NULL)
              {
                  next->pre = node;
              }
              m_length++;//链表结点长度加1
          }
          else
          {
              THROW_EXCEPTION(NoEnoughMemoryException, "No enough memmory...");
          }
      }
      else
      {
          THROW_EXCEPTION(IndexOutOfBoudsException, "Parameter index is invalid...");
      }
      return ret;
    }
    bool insert(const T& value)
    {
      return insert(m_length, value);
    }

2、双向链表的删除操作

数据结构(七)——双向链表

bool remove(int index)
    {
      //判断目标位置是否合法
      bool ret = (0 <= index) && (index < m_length);
      if(ret)
      {
        //当前结点指向头结点
        Node* current = position(index);

        //使用toDel指向要删除的结点
        Node* toDel = current->next;
        Node* next = toDel->next;
        if(m_current == toDel)
        {
            m_current = next;
        }
        //将当前结点的下一个结点指向要删除结点的下一个结点
        current->next = next;
        if(next != NULL)
            next->pre = current;
        m_length--;//链表结点长度减1
        destroy(toDel);//释放要删除的结点的堆空间
      }
      else
      {
          THROW_EXCEPTION(IndexOutOfBoudsException, "Parameter inde is invalid...");
      }
      return ret;

    }

三、双向链表的实现

template 
  class DualLinkedList:public List
  {
  protected:
    struct Node:public Object
    {
      T value;//数据域
      Node* next;//后继指针域
      Node* pre;//前驱
    };
    mutable struct:public Object
    {
      char reserved[sizeof(T)];//占位空间
      Node* next;
      Node* pre;
    }m_header;
    int m_length;
    int m_step;
    Node* m_current;
  protected:
    Node* position(int index)const
    {
      //指针指向头结点
      Node* ret = reinterpret_cast(&m_header);
      //遍历到目标位置
      for(int i = 0; i < index; i++)
      {
          ret = ret->next;
      }
      return ret;
    }
  public:
    DualLinkedList()
    {
      m_header.next = NULL;
      m_header.pre = NULL;
      m_length = 0;
      m_step = 1;
      m_current = NULL;
    }
    virtual ~DualLinkedList()
    {
      clear();
    }
    bool insert(int index, const T& value)
    {
      //判断目标位置是否合法
      bool ret = (0 <= index) && (index <= m_length);
      if(ret)
      {
          //创建新的结点
          Node* node = createNode();
          if(node != NULL)
          {
              //当前结点定位到目标位置
              Node* current = position(index);
              //当前结点的下一个结点
              Node* next = current->next;
              //修改插入结点的值
              node->value = value;
              //将当前位置的下一个结点作为插入结点的下一个结点
              node->next = next;
              //将要插入结点作为当前结点的下一个结点
              current->next = node;
              if(current != reinterpret_cast(&m_header))
              {
                  node->pre = current;
              }
              else
              {
                  node->pre = NULL;
              }
              if(next != NULL)
              {
                  next->pre = node;
              }
              m_length++;//链表结点长度加1
          }
          else
          {
              THROW_EXCEPTION(NoEnoughMemoryException, "No enough memmory...");
          }
      }
      else
      {
          THROW_EXCEPTION(IndexOutOfBoudsException, "Parameter index is invalid...");
      }
      return ret;
    }
    bool insert(const T& value)
    {
      return insert(m_length, value);
    }
    bool remove(int index)
    {
      //判断目标位置是否合法
      bool ret = (0 <= index) && (index < m_length);
      if(ret)
      {
        //当前结点指向头结点
        Node* current = position(index);

        //使用toDel指向要删除的结点
        Node* toDel = current->next;
        Node* next = toDel->next;
        if(m_current == toDel)
        {
            m_current = next;
        }
        //将当前结点的下一个结点指向要删除结点的下一个结点
        current->next = next;
        if(next != NULL)
            next->pre = current;
        m_length--;//链表结点长度减1
        destroy(toDel);//释放要删除的结点的堆空间
      }
      else
      {
          THROW_EXCEPTION(IndexOutOfBoudsException, "Parameter inde is invalid...");
      }
      return ret;

    }
    bool set(int index, const T& value)
    {
      //判断目标位置是否合法
      bool ret = (0 <= index) && (index < m_length);
      if(ret)
      {
          //将当前结点指向头结点
          Node* current = position(index);

          //修改目标结点的数据域的值
          current->next->value = value;
      }
      else
      {
          THROW_EXCEPTION(IndexOutOfBoudsException, "Parameter inde is invalid...");
      }
      return ret;
    }
    bool get(int index, T& value)const
    {
      //判断目标位置是否合法
      bool ret = (0 <= index) && (index < m_length);
      if(ret)
      {
          //当前结点指向头结点
          Node* current = position(index);
          //遍历到目标位置

          //获取目标结点的数据域的值
          value = current->next->value;
      }
      else
      {
          THROW_EXCEPTION(IndexOutOfBoudsException, "Parameter inde is invalid...");
      }
      return ret;
    }
    //重载版本
    T get(int index)const
    {
      T ret;
      if(get(index, ret))
        return ret;
    }
    int length()const
    {
      return m_length;
    }

    int find(const T& value)const
    {
        int ret = -1;
        //指向头结点
        Node* node = m_header.next;
        int i = 0;
       while(node)
        {
            //找到元素,退出循环
            if(node->value == value)
            {
                ret = i;
                break;
            }
            else
            {
                node = node->next;
                 i++;
            }
        }
        return ret;
    }
    void clear()
    {
      //遍历删除结点
     while(m_header.next)
      {
          //要删除的结点为头结点的下一个结点
          Node* toDel = m_header.next;
          //将头结点的下一个结点指向删除结点的下一个结点
          m_header.next = toDel->next;
          m_length--;
          destroy(toDel);//释放要删除结点
      }

    }

    virtual bool move(int pos, int step = 1)
    {
      bool ret = (0 <= pos) && (pos < m_length) && (0 < step);
      if(ret)
      {
           m_current = position(pos)->next;
           m_step = step;
      }
      return ret;
    }
    virtual bool end()
    {
        return m_current == NULL;
    }
    virtual T current()
    {
        if(!end())
        {
            return m_current->value;
        }
        else
        {
            THROW_EXCEPTION(InvalidOperationException, "Invalid Operation...");
        }
    }
    virtual bool next()
    {
        int i = 0;
       while((i < m_step) && (!end()))
        {
            m_current = m_current->next;
            i++;
        }
        return (i == m_step);
    }
    virtual bool pre()
    {
        int i = 0;
       while((i < m_step) && (!end()))
        {
            m_current = m_current->pre;
            i++;
        }
        return (i == m_step);
    }
    virtual Node* createNode()
    {
        return new Node();
    }
    virtual void destroy(Node* node)
    {
        delete node;
    }
  };

另外有需要云服务器可以了解下创新互联scvps.cn,海内外云服务器15元起步,三天无理由+7*72小时售后在线,公司持有idc许可证,提供“云服务器、裸金属服务器、高防服务器、香港服务器、美国服务器、虚拟主机、免备案服务器”等云主机租用服务以及企业上云的综合解决方案,具有“安全稳定、简单易用、服务可用性高、性价比高”等特点与优势,专为企业上云打造定制,能够满足用户丰富、多元化的应用场景需求。


分享文章:数据结构(七)——双向链表-创新互联
分享网址:http://jkwzsj.com/article/dgsoco.html

其他资讯