什么是列表
与数组不同,数组在内存中顺序存放,物理层面就具有逻辑性
列表不一定是顺序存放,也不一定在同一个空间
通过指针彼此相连,来构成线性序列
列表的一些有关量
节点 node :
相邻节点彼此称为前驱或后驱
没有前驱的唯一节点称为 首
没有后驱的唯一节点称为 末
节点属性
每一个节点都需要 : 数值 , 前驱 , 后驱
header trailer 不可见,维持稳定
header -1 ; first 0 ; last n -1 ; trailer n ;
(1)元素查找
在 p 的 n 个前驱中查找等于 e 的最后一个元素
template<typename T>
Posi(T) List<T>::find(T const&e,int n,Posi(T) p) const{
while(n-- > 0){
if(e == (p = p->pred)->date)
return p;
}
return NULL;
}
(2)元素插入
template <typename T>
Posi(T) Listnode<T>::insert_pred(T const&e){
Posi(T) x = new Listnode(e,pred,this); //b
pred->succ = x; //c d
pred = x;
return x;
}
b :是给要插入的 x 在 pred(前驱) 和 this(后驱)中
新分配一个空间
c :把前驱的后驱指向变成 x ,再把前驱(相对 this 来说)变成 x
?:这个前后指向的写法不太明白,为什么有用->的,也有不用的?
我硬是没找到 new 的函数
(3)列表复制
从 p 开始连续的 n 个节点
template <typename T>
void Listnode<T>::copynode(Posi(T) p ,int n){
init();
while(0 < n--){
insert_last(p->data);
p = p->succ;
}
return 0;
}
//init():创建头尾列表,header,tailer,并初始化
//insert_before (trailor)
(4)节点删除
template <typename T>
T List<T>::remove(Posi(T) p){
T e = p->data;
p->pred->succ = p->succ;
p->succ->pred = p->pred;
delete p;
_size--;
return e;
}
这个过程代码看上去有点乱,但是从图很好理解
常数级的复杂度
(5)列表析构
template<typename T>
int List<T>::clear(){
int oldsize = _size;
while(_size > 0)
remove(header->succ);
return oldsize;
}
//在 remove 操作中会把 _size 减一
//持续删掉首节点,(后面的会替补上来)
(6)唯一化
template <typename T>
int List<T>::deduplicate(){
if(_size < 2)
return ;
int oldsize = _size;
Rank r = 1;
Posi(T) p = first();
while(trailer != (p = p-> succ)){
Posi(T) q = find(p->data,r,p)
if( q ){ //如果存在相同的元素
remove(q);
r += 1;
}
}
return oldsize - _size ;
}
//在 p 的 r 个前驱中,查找等于 p 的最后一个元素
//查找范围不断增大的过程,复杂度 O(n²)
// r 从 1 开始,因为 0 号元素不用对比
// remove(q)而不是 p ,因为后面还要对比...小心呀
复杂度是比较高,但是对于无序列表也就只能这样了,莫得办法