您的位置:首页 > 理论基础 > 数据结构算法

课程笔记 08:数据结构(清华) 列表-读写接口

2015-07-23 20:13 211 查看
在介绍循位置访问、查找元素等只读操作以及插入、删除、去重等可写操作前,先讲讲初始化方法与复制构造函数的实现。

void List::init()

{

header = new ListNode<T>;

tailor = new ListNode<T>;

header.succ = tailor; header.pred = NULL;

tailor.pred = header; tailor.succ = NULL;

_size = 0;

}

而复制函数的实现如下:

void List<T>::copyNodes(ListNodePosi(T) p, int n) //p合法,且至少有n-1个真后继节点

{

init(); //创建头、尾哨兵节点并做初始化

while ( n -- ) //将起自p起的n项依次作为末节点插入

{

insertAsLast(p.data);

p = p.succ;

}

}

以下是基于复制方法的初始化:

List<T>::List(ListNodePosi(T) p, int n)

{ copyNodes(p, n); } //复制列表中自位置p起的n项

List<T>::List(List<T> const& L)

{ copyNodes(L.first(), L._size); } //整体复制列表L

List<T>::List(List<T> const& L, int r, int n)

{ copyNodes(L[r], n); }

为了延续向量中循秩访问的形式,我们需要重载[]操作符。

T & List::operator[](Rank r)

{

ListNodePosi(T) p = first();

while (-- r) p = p.succ;

return p.data;

}

针对无序列表的查找功能实现如下:

ListNodePosi(T) find (T const &e, int n, ListNodePosi(T) p) const

{

while (0 < n--) //对于p最近的n个前驱,从右向左

if (e == (p = p->pred)->data)

return p; //逐个比对,直至命中或范围越界

return NULL; //p越出左边界意味着区间内不含e,查找失败

};

列表的插入分为以下几种。

ListNodePosi(T) List<T>::insertAsFirst(T const& e) //e当作首节点插入

{ _size++; return header->insertAsSucc(e); }

ListNodePosi(T) List<T>::insertAsLast(T const& e)

{ _size++; return trailer->insertAsPred(e); } //e当作末节点插入

ListNodePosi(T) List<T>::insertBefore(ListNodePosi(T) p, T const& e)

{ _size++; return p->insertAsPred(e); } //e当作p的前驱插入

ListNodePosi(T) List<T>::insertAfter(ListNodePosi(T) p, T const& e)

{ _size++; return p->insertAsSucc(e); } //e当作p的后继插入

删除算法的实现如下:

T List<T>::remove(ListNodePosi(T) p) //删除除合法位置p处节点,返回回其数值

{

T e = p->data; //备份待删除节点的数值(假定T类型可直接赋值)

p->pred->succ = p->succ; p->succ->pred = p->pred; //后继、前驱

delete p; _size--; //释放节点,更新规模

return e; //返回备份的数值

}

以下是无序列表的去重操作:

int List<T>::deduplicate() //剔除无序列表中的重复节点

{

if (_size < 2) return 0; //平凡列表自然无重复

int oldSize = _size; //记录原规模

ListNodePosi(T) p = header; Rank r = 0; //p从首节点开始

while (trailer != (p = p->succ)) { //依次直到末节点

ListNodePosi(T) q = find(p->data, r, p); //在p的r个(真)前驱中查找雷同者

q ? remove(q) : r++; //若的确存在,则初除之;否则秩加一

} //assert: 循环过程中的任意时刻,p的所有前驱互不相等

return oldSize - _size; //列表规模变化量,即被删除元素总数

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: