课程笔记 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; //列表规模变化量,即被删除元素总数
}
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; //列表规模变化量,即被删除元素总数
}
相关文章推荐
- 数据结构——foodfill 八连块问题
- Windows画刷,图标等数据结构的原理
- 迷宫算法及数据结构分析(by WIzaRD_ssc)
- java数据结构和算法------图(最小生成树Kruskal)
- 【数据结构】散列表
- caffe的基本数据结构
- 数据结构与算法-函数的渐近增长
- 数据结构与算法-函数的渐近增长
- 南阳oj NYOJ 数据结构 题目93 汉若塔(三)
- 浅谈队列及栈的用法
- C++的标准模板库STL中实现的数据结构之链表std::list的分析与使用
- c/c++ 数据结构之位图(bitmap)详解
- 数据结构中的基本概念
- COJ 0986 WZJ的数据结构(负十四) 区间动态k大
- 数据结构(二):链表、链队列
- 如何实现循环队列
- 插入排序
- 删除链表中值相同的多余节点
- java数据结构和算法------图(最小生成树Prim)
- 南阳 oj NYoj 数据结构 最小数 题目1073