zoukankan      html  css  js  c++  java
  • 单项链表的实现

    实现基于单向链表的list类。

    struct node {

         int x;

         int y;

         node(int xx, int yy) {

             x = xx;

             y = yy;

            }

    }

     1.构造函数时先设置一个head结点,其指向空。如下:

            

    2.插入结点:

    当position为0时,本来应该是这样的: 

                                                                                                       

    但是,这个函数在这里插入结点时,如果count=0,则将图中position位置看成NULL,那么下面的插入方法仍然成立不受影响。所以这就是设置头结点的优点是所在了,在position=0时插入结点就不需要通过条件判断了(这种判断很容易忘记漏写,导致苦逼的debug),在这里只要通过current找到插入的位置position前的结点,然后将新的结点插在current后面,新结点的next为current->next即可完成insert的工作。

     

    3.remove结点:

     如图所示的方法删除position位置的结点,同样是利用head来减少判断步骤。

     

    附代码及注释:

      1 #include <iostream>
      2 using namespace std;
      3 enum Error_code {
      4          success,
      5          underflow,
      6          overflow
      7 };
      8 template <class List_entry>
      9 struct Node {
     10          List_entry entry;
     11          Node<List_entry> *next;
     12 };
     13 template <class List_entry>
     14 class MyList {
     15 public:
     16          MyList() {
     17              head = new Node<List_entry>;//设置一个头结点
     18              head->entry = 0;
     19              head->next = NULL;
     20              count = 0;//当前链表为空(头部之后的结点才是我们存进去的,count指的是我们存进去的结点数)
     21              curPosition = -1;//头部的位置为-1
     22              current = head;//当前位置指向链表的头部
     23          }
     24          /*设置头部的作用主要体现在insert(int position, const List_entry &entry),remove(...), retrieve(...),
     25          replay(...)这些函数里面,详见相关函数*/
     26          ~MyList() {
     27              current = NULL;
     28              curPosition = -1;
     29              Node<List_entry> *temp = head, *a;
     30              while (head != NULL) {
     31                  head = temp->next;
     32                  a = temp;
     33                  delete a;
     34                  temp = head;
     35              }
     36              count = 0;
     37          }
     38          // 拷贝构造函数和赋值运算符重载,注意深拷贝与浅拷贝的差异
     39          MyList(const MyList<List_entry> &copy) {
     40              head = new Node<List_entry>;//this start...
     41              head->entry = 0;
     42              head->next = NULL;
     43              count = 0;
     44              curPosition = -1;
     45              current = head;//this end...拷贝构造函数,相当于构造一个MyList()之后将copy这个链表的内容复制进去
     46              if (copy.count != 0) {//拷贝链表内容
     47                  count = copy.count;
     48                  Node<List_entry> *a, *b;
     49                  a = copy.head->next;
     50                  b = head;
     51                  for (int i = 0; i < copy.count; i++) {
     52                      b->next = new Node<List_entry>;
     53                      b = b->next;
     54                      b->entry = a->entry;
     55                      b->next = NULL;
     56                      a = a->next;
     57                  }
     58              }
     59          }
     60          //跟拷贝构造函数不一样,这个函数实现的前提是已经MyList()例如MyList a,然后将copy复制到a
     61          void operator =(const MyList<List_entry> &copy) {
     62              if (!empty()) clear();//清空
     63              if (copy.count != 0) {//同上拷贝链表内容
     64                  count = copy.count;
     65                  Node<List_entry> *a, *b;
     66                  a = copy.head->next;
     67                  b = head;
     68                  for (int i = 0; i < copy.count; i++) {
     69                      b->next = new Node<List_entry>;
     70                      b = b->next;
     71                      b->entry = a->entry;
     72                      b->next = NULL;
     73                      a = a->next;
     74                  }
     75              }
     76          }
     77          // 清空list,清空时候保留头结点,数据恢复到原始状态
     78          void clear() {
     79              if (!empty()) {
     80                  Node<List_entry> *temp = head->next, *a;
     81                  while (temp != NULL) {
     82                      head->next = temp->next;
     83                      a = temp;
     84                      temp = head->next;
     85                      delete a;
     86                      count--;
     87                  }
     88                  current = head;
     89                  curPosition = -1;
     90              }
     91          }
     92          // 判断list是否为空
     93          bool empty() const {
     94              if (count != 0) return false;
     95              return true;
     96          }
     97          // 判断list是否已满
     98          bool full() const {
     99              return false;
    100          }
    101          // 获取list的元素数量
    102          int size() const {
    103              return count;
    104          }
    105          // 在第position个位置插入值为entry的元素,如果position为0则插入在head(head的position为-1)后面,依次类推
    106          // 若position < 0 或者 position > count,则返回underflow
    107          Error_code insert(int position, const List_entry &entry) {
    108              if (position < 0 || position > count) return underflow;
    109              Node<List_entry> *new_node, *pre, *follow;
    110              //new一个新的结点
    111              new_node = new Node<List_entry>;
    112              new_node->entry = entry;
    113              //setPosition的作用是设置当前的位置current指向position-1这个位置,在position-1后面插入new_node
    114              //当position==0时,应该插在头部后面的位置,pre指向头部。若没有head,则需要讨论当position == 0时候的情况,容易漏判断
    115              setPosition(position - 1);
    116              pre = current;
    117              follow = current->next;
    118              //新结点指向follow,pre前一个结点指向新结点new_node
    119              new_node->next = follow;
    120              pre->next = new_node;
    121              count++;
    122              return success;
    123          }
    124          // 删除第position个位置的元素,并将该元素的值保存在entry中
    125          // 若position < 0 或者 position >= count,则返回underflow
    126          Error_code remove(int position, List_entry &entry) {
    127              if (position < 0 || position >= count) return underflow;
    128              Node<List_entry> *pre, *now, *follow;
    129              //去掉position位置的结点,应该让pre指向该位置的前一个,所以应该先找出position-1位置的结点
    130              setPosition(position - 1);
    131              pre = current;
    132              now = current->next;
    133              entry = now->entry;
    134              follow = now->next;
    135              pre->next = follow;
    136              delete now;//删掉position的结点
    137              count--;
    138              return success;
    139          }
    140          // 获取第position个位置的元素,保存在entry中
    141          // 若position < 0 或者 position >= count,则返回underflow
    142          Error_code retrieve(int position, List_entry &entry) const {
    143              if (position < 0 || position >= count) return underflow;
    144              setPosition(position);
    145              entry = current->entry;
    146              return success;
    147          }
    148          // 将第position个位置的元素替换为entry
    149          // 若position < 0 或者 position >= count,则返回underflow
    150          Error_code replace(int position, const List_entry &entry) {
    151              if (position < 0 || position >= count) return underflow;
    152              setPosition(position);
    153              current->entry = entry;
    154              return success;
    155          }
    156          // 用visit函数遍历list内所有的元素
    157          void traverse(void (*visit)(List_entry &)) {
    158              Node<List_entry> *a = head->next;
    159              for (int i = 0; i < count; i++) {
    160                  (*visit)(a->entry);
    161                  a = a->next;
    162              }
    163          }
    164 protected:
    165          int count;                                                                          // 记录list内元素数量
    166          Node<List_entry> *head;                                         // 链表头指针
    167          mutable int curPosition;                                   // current指针的位置编号
    168          mutable Node<List_entry> *current;                 // current指针
    169         // 设置current指针的位置,指向第position个位置
    170         void setPosition(int position) const {
    171              if (position < curPosition) {
    172                  curPosition = -1;
    173                  current = head;
    174              }
    175              for (; curPosition < position; curPosition++) {
    176                  current = current->next;
    177              }
    178          }
    179 };

      

  • 相关阅读:
    期末考试冬眠
    题解 P1457 【城堡 The Castle】
    题解 P1052 【过河】
    题解 P5663 【加工零件【民间数据】】
    与 macOS 10.12 兼容的OpenCV版本
    summarise() regrouping output 警告
    binary_crossentropy和BinaryCrossentropy的区别
    损失函数BinaryCrossentropy例子说明
    理解功能强大的sed替换命令
    理解GAN对抗神经网络的损失函数和训练过程
  • 原文地址:https://www.cnblogs.com/zhengwin7/p/4070347.html
Copyright © 2011-2022 走看看