ListNode
列表节点 ADT 支持的操作接口
操作接口 | 功能 |
---|---|
data() | 当前节点所存数据对象 |
pred() | 当前节点前驱节点的位置 |
succ() | 当前节点后继节点的位置 |
insertAsPred(e) | 插入前驱节点,存入被引用对象 e,返回新节点位置 |
insertAsSucc(e) | 插入后继节点,存入被引用对象 e,返回新节点的位置 |
列表 ADT 支持的操作接口
操作接口 | 功能 | 适用对象 |
---|---|---|
size() | 返回节点总数 | 列表 |
first()、last() | 返回首、末节点的位置 | 列表 |
insertAsFirst(e)、insertAsLast(e) | 将 e 当做首、末节点插入 | 列表 |
insertA(p, e)、insertB(p, e) | 将 e 当做节点 p 的直接后继、前驱插入 | 列表 |
remove( p ) | 删除位置 p 处的节点,返回其数值 | 列表 |
disordered() | 判断所有节点是否已按非降序排列 | 列表 |
sort() | 调整各节点的位置,使之升序 | 列表 |
find(e) | 查找目标元素 e,失败返回 NULL | 列表 |
search(e) | 查找目标元素 e,返回不大于 e 且秩最大的节点的位置 | 有序列表 |
deduplicate() | 删除重复节点 | 列表 |
uniquify() | 删除重复节点 | 有序列表 |
traverse() | 遍历并统一处理所有节点,处理方法由函数对象指定 | 列表 |
ListNode 模板类
// listNode.h
typedef int Rank; //秩
#define ListNodePosi(T) ListNode<T>* //列表节点位置
template <typename T> struct ListNode {
//列表节点模板类(以双向链表形式实现)
// 成员
T data; ListNodePosi(T) pred; ListNodePosi(T) succ; //数值、前驱、后继
// 构造函数
ListNode() {
} //针对header和trailer的构造
ListNode ( T e, ListNodePosi(T) p = NULL, ListNodePosi(T) s = NULL )
: data ( e ), pred ( p ), succ ( s ) {
} //默认构造器
// 操作接口
ListNodePosi(T) insertAsPred ( T const& e ); //紧靠当前节点之前插入新节点
ListNodePosi(T) insertAsSucc ( T const& e ); //紧随当前节点之后插入新节点
};
List 模板类
#include "listNode.h" //引入列表节点类
template <typename T> class List {
//列表模板类
private:
int _size; ListNodePosi(T) header; ListNodePosi(T) trailer; //规模、头哨兵、尾哨兵
protected:
void init(); //列表创建时的初始化
int clear(); //清除所有节点
void copyNodes ( ListNodePosi(T), int ); //复制列表中自位置p起的n项
ListNodePosi(T) merge ( ListNodePosi(T), int, List<T> &, ListNodePosi(T), int ); //归并
void mergeSort ( ListNodePosi(T)&, int ); //对从p开始连续的n个节点归并排序
void selectionSort ( ListNodePosi(T), int ); //对从p开始连续的n个节点选择排序
void insertionSort ( ListNodePosi(T), int ); //对从p开始连续的n个节点插入排序
void radixSort(ListNodePosi(T), int); //对从p开始连续的n个节点基数排序
public:
// 构造函数
List() {
init(); } //默认
List ( List<T> const& L ); //整体复制列表L
List ( List<T> const& L, Rank r, int n ); //复制列表L中自第r项起的n项
List ( ListNodePosi(T) p, int n ); //复制列表中自位置p起的n项
// 析构函数
~List(); //释放(包含头、尾哨兵在内的)所有节点
// 只读访问接口
Rank size() const {
return _size; } //规模
bool empty() const {
return _size <= 0; } //判空
T& operator[] ( Rank r ) const; //重载,支持循秩访问(效率低)
ListNodePosi(T) first() const {
return header->succ; } //首节点位置
ListNodePosi(T) last() const {
return trailer->pred; } //末节点位置
bool valid ( ListNodePosi(T) p ) //判断位置p是否对外合法
{
return p && ( trailer != p ) && ( header != p ); } //将头、尾节点等同于NULL
ListNodePosi(T) find ( T const& e ) const //无序列表查找
{
return find ( e, _size, trailer ); }
ListNodePosi(T) find ( T const& e, int n, ListNodePosi(T) p ) const; //无序区间查找
ListNodePosi(T) search ( T const& e ) const //有序列表查找
{
return search ( e, _size, trailer ); }
ListNodePosi(T) search ( T const& e, int n, ListNodePosi(T) p ) const; //有序区间查找
ListNodePosi(T) selectMax ( ListNodePosi(T) p, int n ); //在p及其n-1个后继中选出最大者
ListNodePosi(T) selectMax() {
return selectMax ( header->succ, _size ); } //整体最大者
// 可写访问接口
ListNodePosi(T) insertAsFirst ( T const& e ); //将e当作首节点插入
ListNodePosi(T) insertAsLast ( T const& e ); //将e当作末节点插入
ListNodePosi(T) insertA ( ListNodePosi(T) p, T const& e ); //将e当作p的后继插入(After)
ListNodePosi(T) insertB ( ListNodePosi(T) p, T const& e ); //将e当作p的前驱插入(Before)
T remove ( ListNodePosi(T) p ); //删除合法位置p处的节点,返回被删除节点
void merge ( List<T> & L ) {
merge ( header->succ, _size, L, L.header->succ, L._size ); } //全列表归并
void sort ( ListNodePosi(T) p, int n ); //列表区间排序
void sort() {
sort ( first(), _size ); } //列表整体排序
int deduplicate(); //无序去重
int uniquify(); //有序去重
void reverse(); //前后倒置(习题)
// 遍历
void traverse ( void (* ) ( T& ) ); //遍历,依次实施visit操作(函数指针,只读或局部性修改)
template <typename VST> //操作器
void traverse ( VST& ); //遍历,依次实施visit操作(函数对象,可全局性修改)
}; //List
前插入
详解 insertAsPred(e)
代码:
template <typename T> // 将 e 紧靠当前节点之前插入于当前节点所属列表(设有哨兵头节点header)
ListNodePosi(T) ListNode<T>::insertAsPred ( T const& e ) {
ListNodePosi(T) x = new ListNode ( e, pred, this ); // 创建新节点
pred->succ = x; pred = x; // 设置正向链接, 顺序不能反
return x; // 返回新节点的位置
}
后插入
template <typename T> //将e紧随当前节点之后插入于当前节点所属列表(设有哨兵尾节点trailer)
ListNodePosi(T) ListNode<T>::insertAsSucc ( T const& e ) {
ListNodePosi(T) x = new ListNode ( e, this, succ ); //创建新节点
succ->pred = x; succ = x; //设置逆向链接
return x; //返回新节点的位置
}
- 插入排序
始终将整个序列视作并切分为两个部分:有序的前缀,无序的后缀;通过迭代,反复地将后缀的首元素转移至前缀中。
template <typename T> //对列表中起始于位置p、宽度为n的区间做插入排序
void List<T>::insertionSort ( ListNodePosi(T) p, int n ) {
//valid(p) && rank(p) + n <= size
for ( int r = 0; r < n; r++ ) {
//逐一为各节点
insertA ( search ( p->data, r, p ), p->data ); //查找适当的位置并插入
p = p->succ; remove ( p->pred ); //转向下一节点
}
}
- 选择排序
将序列划分为两个部分:无序前缀和有序后缀;要求前缀不大于后缀,通过迭代,选出前缀中的最大者,作为最小元素转移至后缀中。
template <typename T> //从起始于位置p的n个元素中选出最大者
ListNodePosi(T) List<T>::selectMax ( ListNodePosi(T) p, int n ) {
ListNodePosi(T) max = p; //最大者暂定为首节点p
for ( ListNodePosi(T) cur = p; 1 < n; n-- ) //从首节点p出发,将后续节点逐一与max比较
if ( !lt ( ( cur = cur->succ )->data, max->data ) ) //若当前元素不小于max,则
max = cur; //更新最大元素位置记录
return max; //返回最大节点位置
}
template <typename T> //对列表中起始于位置p、宽度为n的区间做选择排序
void List<T>::selectionSort ( ListNodePosi(T) p, int n ) {
//valid(p) && rank(p) + n <= size
ListNodePosi(T) head = p->pred; ListNodePosi(T) tail = p;
for ( int i = 0; i < n; i++ ) tail = tail->succ; //待排序区间为(head, tail)
while ( 1 < n ) {
//在至少还剩两个节点之前,在待排序区间内
ListNodePosi(T) max = selectMax ( head->succ, n ); //找出最大者(歧义时后者优先)
insertB ( tail, remove ( max ) ); //将其移至无序区间末尾(作为有序区间新的首元素)
tail = tail->pred; n--;
}
}
- 归并排序
二路归并,将两个有序序列合并为一个有序序列。
template <typename T> //列表的归并排序算法:对起始于位置p的n个元素排序
void List<T>::mergeSort ( ListNodePosi(T) & p, int n ) {
//valid(p) && rank(p) + n <= size
if ( n < 2 ) return; //若待排序范围已足够小,则直接返回;否则...
int m = n >> 1; //以中点为界
ListNodePosi(T) q = p; for (int i = 0; i < m; i++) q = q->succ; //找到后子列表起点
mergeSort(p, m); mergeSort(q, n - m); //前、后子列表各分别排序
p = merge ( p, m, *this, q, n - m ); //归并
} //注意:排序后,p依然指向归并后区间的(新)起点