相比起数组列表,单向链表更便于插入和删除(时间杂度更小),而且其内存位置较为灵活,在逻辑上(logic)是相连的,但是在物理上(phisical)却是不联通的。
链表的curr与数组列表略有所不同。链表的remove和assert动作,都是对curr指针后的一个数据/位置做出的变化。为了简化分类讨论,我们规定头结点head指针为空,里面不放任何元素数据,其实就是把它当作一个普通的结点。但要注意,tail的改变还是要分情况讨论的。tail与其他指针的不同之处在于,tail的next指向空。
List是储存数据的结构,node是组成list的部分,node需要另外定义成一个类。注意这里写了两个node的构造函数,是为了应对尾部结点和其他结点的两种情况。
今天整理耗时比之前都久一些,以下是我的代码:
#include <iostream>
using namespace std;
template <typename E> class node {
public:
E num;
node *next;
node(node *ptr = NULL){next = ptr;}
//根据实际情况,这里需要两种构造函数
node(E element, node* ptr = NULL ){
num = element;
next = ptr;}
~node(){}
};
template <typename E> class List{
private:
node<E> *head; //head代表了一个链表
node<E> *curr; //方便进行增删动作
node<E> *tail;
int length;
void define(){
//作为私有成员方便后面的成员函数调用,避免代码重复
head = curr = tail = new node<E>();
length = 0;
}
void clear()
{
while(head!=NULL)
{
curr = head;
head = head->next;
delete curr;
}
}
public:
List(){ define(); }
~List(){clear();}
void insert(const E it){
node<E> *temp = new node<E>(it, curr->next);
curr->next = temp;
if(curr == tail) tail = curr->next;
//讨论curr为尾节点的情况
length++;
}
void append(const E &it){
//引用不占用内存
node<E> temp = new node<E>(it,NULL);
tail->next = &temp;
tail = &temp;
length++;
//课本上这段代码只写了两行,感觉编者技巧特别娴熟
//代码如下:
//tail = tail->next = new node<E>(it,NULL);
//length++;
}
E remove(){
node<E> *temp = curr->next;
E renum = temp->num;
if(temp == tail) tail = curr;
//重新设置尾部结点(if needed)
curr->next = temp->next;
//delete temp;
length--;
return renum;
}
const int Aggregate(){ return length;}
const E getValue(){
return curr->next->num;
}
void moveptr(int dest){
//简略了书上的MoveToStart等调整curr指针的函数
curr = head;
if(dest>=0&&dest<=length)
for(int i = 0;i < dest; i++)
curr = curr->next;
}
};
int main() {
//测试代码:
List<int> mylist;
mylist.insert(1);mylist.insert(2);mylist.insert(3);mylist.insert(4);
mylist.append(5);
//mylist.moveptr(1);
int RemoveNum,Get,Length;
Get = mylist.getValue();
RemoveNum= mylist.remove();
Length = mylist.Aggregate();
cout<<Get<<" "<<RemoveNum<<" "<<Length<<endl;
}
这段代码部分借鉴了我的课本(后附),课本中的写法其实更为精炼,我代码中的很多三、四句,课本都一句话就写完了。我感觉有以下几个原因:
1.为了节省空间,不设定多余变量,能省就省。
e.g:我代码中的temp等可以不设置出来,因为它是个中间量(intermediary),可有可无,缩写代码无非是省掉一个等式。
2.常用代码重用,重载/函数。
e.g:将define()和clear()写到私有类型中,在公有函数成员中反复调用,可以使代码整洁。
老师说注释最好也用英文写,下一次博客开始我尽量。。
reference:Data Structure and Algorithm Analysis