• 【Weiss】【第03章】双链表例程


    双链表因为多了个前向指针,需要考虑的特殊因素多了一倍

    所以中间插入(这儿没写)和中间删除会比较复杂。

    其它倒没什么特别的,代码如下。

    测试代码

     1 #include <iostream>
     2 #include "double_linklist.h"
     3 using namespace std;
     4 using namespace doublelinklist;
     5 template class DList<int>;
     6 int main(void)
     7 {
     8     DList<int> number;
     9 
    10     //测试插入
    11     cout << "/*additem()*/" << endl;
    12     number.additem(2);
    13     number.additem(3);
    14     number.additem(5);
    15     number.additem(7);
    16     number.additem(11);
    17     number.additem(13);
    18     number.additem(17);
    19     number.traverse();
    20     cout << "
    " << flush;
    21     number.reverse();
    22     cout << "
    /*end*/
    
    " << flush;
    23 
    24     //测试获取长度
    25     cout << "/*length()*/" << endl;
    26     cout << number.size() << endl;
    27     cout << "/*end*/
    
    " << flush;
    28 
    29     //测试获得头元素
    30     cout << "/*getfirst()*/" << endl;
    31     cout << number.getfirst() << endl;
    32     cout << "/*end*/
    
    " << flush;
    33 
    34     //测试删除存在的元素(头尾及中间元素各一)
    35     cout << "/*remove()*/" << endl;
    36     number.remove(2);
    37     number.remove(5);
    38     number.remove(17);
    39     number.traverse();
    40     cout << "
    " << flush;;
    41     number.reverse();
    42     cout << "
    /*end*/
    
    " << flush;
    43 
    44     //测试删除不存在的元素
    45     cout << "/*remove()*/" << endl;
    46     number.remove(19);
    47     cout << "/*end*/
    
    " << flush;
    48 
    49     //测试清空,并测试从空表中删除元素
    50     cout << "/*clear(),remove()*/" << endl;
    51     number.clear();
    52     number.remove(2);
    53     cout << "/*end*/
    
    " << flush;
    54 
    55     system("pause");
    56 }
    57 
    58 double_linklist_driver
    View Code

    实现代码

      1 #ifndef DOUBLELINKLIST
      2 #define DOUBLELINKLIST
      3 #include <iostream>  4 using namespace std;
      5 
      6 namespace doublelinklist
      7 {
      8 
      9 //链表节点模板
     10 template <typename T> struct Node
     11 {
     12     Node<T>() : next(nullptr),prev(nullptr){}
     13     Node<T>(const T &item, Node<T>* ptrn = nullptr, Node<T>* ptrp = nullptr) : data(item), next(ptrn), prev(ptrp){}
     14     T data;
     15     Node<T>* next;
     16     Node<T>* prev;
     17 };
     18 //头节点及链表主体操作
     19 template <typename T> class DList
     20 {
     21 //构造函数
     22 public:
     23     DList<T>() : length(0), front(nullptr){}
     24 //接口
     25 public:
     26     //返回长度
     27     unsigned int size()const{ return length; }
     28     //返回头指针
     29     Node<T>* begin()const{ return front; }
     30     //判断是否为空
     31     bool empty()const{ return length == 0; }
     32     //获得头元素
     33     T getfirst()const{ return front->data; }
     34     //获得尾元素
     35     T getlast()const{ return rear->data; }
     36     //#查找元素所在地址
     37     Node<T>* find(const T &item)const;
     38     //#尾部加入新元素
     39     bool additem(const T &item);
     40     //#删除指定元素
     41     bool remove(const T &item);
     42     //#遍历顺序输出链表元素
     43     void traverse()const;
     44     //#遍历倒序输出链表元素
     45     void reverse()const;
     46     //清空链表
     47     void clear();
     48 
     49 //辅助函数
     50 private:
     51     //#查找元素前驱
     52     Node<T>* find_prev(const T& item)const;
     53 //数据
     54 private:
     55     unsigned int length;
     56     Node<T>* front;
     57     Node<T>* rear;
     58 };
     59 
     60 //如果元素为头元素或元素不存在则返回nullptr,否则返回前驱
     61 template <typename T> Node<T>* DList<T>::find_prev(const T& item)const
     62 {
     63     if (length == 0)
     64         return nullptr;
     65     if (front->data == item)
     66         return nullptr;
     67     for (Node<T>* iter = front; iter->next != nullptr; iter = iter->next)
     68     {
     69         if (iter->next->data == item)
     70             return iter;
     71     }
     72     return nullptr;
     73 }
     74 //调用find_prev,如果元素存在则返回地址,不存在则返回nullptr
     75 template <typename T> Node<T>* DList<T>::find(const T &item)const
     76 {
     77     Node<T>* iter = find_prev(item);
     78     if (length == 0)
     79         return nullptr;
     80     if (front->data == item)
     81         return front;
     82     return iter->next;
     83 }
     84 template <typename T> bool DList<T>::additem(const T &item)
     85 {
     86     Node<T>* pnew = new Node<T>(item);
     87     //原链表无元素
     88     //头尾指针均指向新节点,且新节点前后指针默认为nullptr
     89     if (length == 0)
     90         front = rear = pnew;
     91     else
     92     {
     93         rear->next = pnew;
     94         pnew->prev = rear;
     95         rear = pnew;
     96     }
     97     ++length;
     98     return true;
     99 }
    100 //删除操作相对复杂
    101 template <typename T> bool DList<T>::remove(const T &item)
    102 {
    103     //先判断链表是否空避免front->data未定义
    104     if (length == 0)                    
    105     {
    106         cout << "No data!" << endl;
    107         return false;
    108     }
    109     Node<T>* iter = find_prev(item);
    110     //find_prev返回nullptr,且首元素不等,说明链表中无此元素
    111     if (iter == nullptr && front->data != item)    
    112     {
    113         cout << "Can not find!" << endl;
    114         return false;
    115     }
    116     Node<T>* save;
    117     //如果元素是首元素
    118     //则仅需将save后继(如果存在)的前向指针改为nullptr
    119     //如果save无后继,说明链表删除后为空,将rear置空
    120     if (front->data == item)
    121     {
    122         save = front;
    123         front = front->next;
    124         if (save != rear)
    125             save->next->prev = nullptr;
    126         else
    127             rear = nullptr;
    128     }
    129     //如果元素不是首元素
    130     //则save的前驱iter的后向指针需改指向save后继
    131     //同时,save后继(如果存在)的前向指针改为指向save的前驱iter
    132     //如果save无后继,则rear要指向新的尾节点
    133     else
    134     {
    135         save = iter->next;
    136         iter->next = save->next;
    137         if (save != rear)
    138             save->next->prev = iter;
    139         else
    140             rear = iter;
    141     }
    142     delete save;
    143     --length;
    144     return true;
    145 }
    146 template <typename T> void DList<T>::traverse()const
    147 {
    148     if (length != 0)
    149     {
    150         for (Node<T>* iter = front; iter != nullptr; iter = iter->next)
    151             cout << iter->data << ends;
    152     }
    153 }
    154 template <typename T> void DList<T>::reverse()const
    155 {
    156     if (length != 0)
    157     {
    158         for (Node<T>* iter = rear; iter != nullptr; iter = iter->prev)
    159             cout << iter->data << ends;
    160     }
    161 }
    162 template <typename T> void DList<T>::clear()
    163 {
    164     Node<T>* iter;
    165     while (front != nullptr)
    166     {
    167         iter = front;
    168         front = front->next;
    169         delete iter;
    170     }
    171     front = rear = nullptr;
    172     length = 0;
    173 }
    174 }
    175 #endif
  • 相关阅读:
    js语法
    页面格式与布局
    css样式标签
    框架
    css样式表选择器
    最大值(东方化改题+老师给的题解)
    数字(东方化改题+老师给的正解)
    测试一下这个编辑器
    请让本题永远沉睡于此(东方化改题+给的标程)
    贪吃的yjj(东方化改题+给的标程)
  • 原文地址:https://www.cnblogs.com/catnip/p/4328897.html
Copyright © 2020-2023  润新知