无序列表
创建列表类模板
template <typename T> class List
{
private:
int _size; Posi(T) header; Posi(T) trailer;//规模、头节点、尾节点
protected:
void init();//列表创建时初始化
int clear(); //清除所有节点
。。。一系列函数
public:
Posi(T) first() const {return header -> succ;} //返回首节点位置
Posi(T) first() const {return trailer -> pred;}//返回末节点位置
。。。。。一系列函数
下面是列表初始化函数
template <typename T> void List<T>::init()
{
header = new Posi(T); //创建头节点(头哨兵节点)
trailer = new Posi(T); //创建尾节点(尾哨兵节点)
header -> succ = trailer; header -> pred = NULL;
trailer -> pred = header; trailer -> succ = NULL;
_size = 0; //记录规模
无序列表的查找
template <typename T> Posi(T) List<T>::find(T const& e, int n, Posi(T) p) const
{
//在无序列表内节点p(可能是trailer)的n个(真)前驱中找到等于e的最后者
while(0 < n--) //对于p的n个前驱,从右向左一一进行比对
if(e == (p = p -> pred) -> data)
return p;
return NULL; //p越出左届意味着区间内不含e,查找失败
}
复杂度: O(n)
插入
无序列表的插入可以分成四种情况:e插入当作首节点、e插入当作末节点、e当作p的前驱插入、e当作p的后继插入。根据这四种情况,实现了不同的接口:
template <typename T> Posi(T) List<T>::insertAsFirst(T const& e)
{
_size++;
return header -> insertAsSucc(e);
} //e当作首节点插入
template <typename T> Posi(T) List<T>::insertAsLast(T const& e)
{
_size++;
return trailer -> insertAsPred(e);
} //e当作末节点插入
template <typename T> Posi(T) List<T>::insertAfter(Posi p, T const& e)
{
_size++;
return p -> insertAsSucc(e);
} //e当作p后继插入
template <typename T> Posi(T) List<T>::insertBefore(Posi p, T const& e)
{
_size++;
return p -> insertAsPred(e);
} //e当作p前驱插入
由上述接口可见,最终的插入都可归结为insertAfter()
与insertBefore()
两个函数。即这些接口的实现都可转化为列表节点对象的前插入后者是后插入。
前插入
template <typename T> Posi(T) ListNide<T>::insertAsPred(T const& e) //将e仅靠当前节点之前插入于当前节点之前列表
{
Posi(T) x = new ListNode(e, pred, this); //创建新节点
pred -> succ = x; pred = x; //设置正向链接
return x; // 返回新节点位置
注意:要先让x称为当前节点的前驱节点的后继,再使x成为当前节点的前驱,这个顺序是不能颠倒的。
复杂度:O(1)
后插入
template <typename T> Posi(T) ListNide<T>::insertAsSucc(T const& e) //将e仅靠当前节点之后插入于当前节点之前列表
{
Posi(T) x = new ListNode(e, this, succ); //创建新节点
succ -> pred = x; succ = x; //设置逆向链接
return x; // 返回新节点位置
同样的,要先让x成为当前节点的后继节点的前驱,再让x成为当前节点的后继,顺序不能颠倒。