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