单项链表的实现

实现基于单向链表的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 };

  

原文地址:https://www.cnblogs.com/zhengwin7/p/4070347.html