目录
1.头文件
1.1列表头文件
#include "ListNode.h"//引入节点头文件
#include <ctime>
template <typename T> class List { //列表模板类
private:
int _size; ListNodePosi<T> header, 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
int disordered() const;
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> insert(ListNodePosi<T> p, T const& e); //将e当作p的后继插入
ListNodePosi<T> insert(T const& e, ListNodePosi<T> p); //将e当作p的前驱插入
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 Print(); //打印列表的节点值
// 遍历
void traverse(void (*) (T&)); //遍历,依次实施visit操作(函数指针,只读或局部性修改)
template <typename VST> //操作器
void traverse(VST&); //遍历,依次实施visit操作(函数对象,可全局性修改)
}; //List
//初始化函数
template <typename T> void List<T>::init() { //列表初始化,在创建列表对象时统一调用
header = new ListNode<T>; //创建头哨兵节点
trailer = new ListNode<T>; //创建尾哨兵节点
header->succ = trailer; header->pred = NULL;
trailer->pred = header; trailer->succ = NULL;
_size = 0; //记录规模
}
//打印节点的值
template <typename T> void List<T>::Print() {
ListNodePosi<T> p = header->succ;
while (p != trailer) {//因为存在尾哨兵,所以安全
std::cout << p->data << " ";//输出节点的值
p = p->succ;//向后移动
}
std::cout<<std::endl;//换行
}
//析构函数 所有销毁节点
template <typename T> List<T>::~List() //列表析构器
{
clear(); delete header; delete trailer;
} //清空列表,释放头、尾哨兵节点
//清空列表函数 只销毁可见节点 无法销毁头尾部哨兵
template <typename T> int List<T>::clear() { //清空列表
int oldSize = _size;
while (0 < _size) remove(header->succ); //反复删除首节点,直至列表变空
return oldSize;
}
//删除节点函数
template <typename T> 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; //返回备份的数值
}
//重载下标“ [ ] ”
template<typename T>
T& List<T>::operator[] (Rank r) const {
ListNodePosi<T> p=first();
while (0 < r--)p = p->succ;
return p->data;
}
//无序寻找
template <typename T> //在无序列表内节点p(可能是trailer)的n个(真)前驱中,找到等于e的最后者
ListNodePosi<T> List<T>::find(T const& e, int n, ListNodePosi<T> p) const {
while (0 < n--) //(0 <= n <= rank(p) < _size)对于p的最近的n个前驱,从右向左
if (e == (p = p->pred)->data) return p; //逐个比对,直至命中或范围越界
return NULL; //p越出左边界意味着区间内不含e,查找失败
} //失败时,返回NULL
//插入
//头插入
template<typename T> ListNodePosi<T> List<T>::insertAsFirst(T const& e) {
_size++;
return header->insertAsSucc(e);
}
//尾插入
template<typename T> ListNodePosi<T> List<T>::insertAsLast(T const& e) {
_size++;
return trailer->insertAsPred(e);
}
//前驱插入
template<typename T> ListNodePosi<T> List<T>::insert(T const& e, ListNodePosi<T> p) {
_size++;
return p->insertAsPred(e);
}
//后继插入
template<typename T> ListNodePosi<T> List<T>::insert(ListNodePosi<T> p, T const& e) {
_size++;
return p->insertAsSucc(e);
}
//无序 唯一化
template<typename T> int List<T>::deduplicate() {
if (_size < 2) return 0;
int oldSize = _size;
ListNodePosi<T> p = header;// ListNodePosi<T> p = first();
Rank r = 0;
while (trailer != (p = p->succ)) {//O(n)
ListNodePosi<T> q = find(p->data, r, p);//此时q与p雷同,但删除前者更为简明
q ? remove(q) : r++;//r为无重前缀的长度
}
return oldSize - _size;//删除元素总数
}
//是否逆序
template <typename T> int List<T>::disordered() const{
ListNodePosi<T> h = first();
int a = -1;
while (h!=trailer)
{
if (h->data > h->succ->data)
a++;
h = h->succ;
}
std::cout << "存在逆序对:" << a<<std::endl;
return a;
}
//复制方法
template <typename T> //列表内部方法:复制列表中自位置p起的n项
void List<T>::copyNodes(ListNodePosi<T> p, int n) { //p合法,且至少有n-1个真后继节点
init(); //创建头、尾哨兵节点并做初始化
while (n--) { insertAsLast(p->data); p = p->succ; } //将起自p的n项依次作为末节点插入
}
template <typename T> //复制列表中自位置p起的n项
List<T>::List(ListNodePosi<T> p, int n) {
copyNodes(p,n);
}
template <typename T> //整体复制列表L
List<T>::List(List<T>const & L ) {
copyNodes(L.first(), L._size);
}
template <typename T> //复制L中第r项起的项 r+n <= L._size
List<T>::List(List<T>const& L,int r,int n) {
copyNodes(L[r],n);
}
//遍历函数
template<typename T> void List<T>::traverse( void(*visit) (T&) ) {//借助函数指针机制遍历
ListNodePosi<T> p = first();
while (p!=trailer){
//for (ListNodePosi<T> p = header->succ; p != trailer; p = p->succ) visit(p->data);
visit(p->data);
p = p->succ;
}
}
template<typename T> template<typename VST> //元素类型、操作器
void List<T>::traverse(VST& visit) {//借助函数对象机制遍历
ListNodePosi<T> p = first();
while (p != trailer) {
visit(p->data);
p = p->succ;
}
}
//排序接口
template <typename T> void List<T>::sort(ListNodePosi<T> p, int n) {
srand((int)time(NULL));//随机数种子
switch (rand()%3)
{
case 0:
std::cout << "调用插入排序后前:";
std::cout << std::endl;
Print(); disordered();
std::cout << "调用插入排序后:";
insertionSort(p, n);
std::cout << std::endl;
Print(); disordered();
break;
case 1:
std::cout << "调用选择排序前:";
std::cout << std::endl;
Print(); disordered();
std::cout << "调用选择排序后:";
selectionSort(p, n);
std::cout << std::endl;
Print(); disordered();
break;
default :
std::cout << "调用归并排序前:";
std::cout << std::endl;
Print(); disordered();
std::cout << "调用归并排序后:";
mergeSort(p, n);
std::cout << std::endl;
Print(); disordered();
break;
}
}
//有序向量查找
template <typename T> //在有序列表内节点p(可能是trailer)的n个(真)前驱中,找到不大于e的最后者
ListNodePosi<T> List<T>::search( T const& e,int n,ListNodePosi<T> p)const {
//0 <= n <= Rank(p) < _size
while (-1 < n--) {//对于p的n个前驱,从左往右进行比较
if ( (p = p->pred)->data <= e) break;//直到命中元素,数值越界或范围越界
}
return p;//失败时,返回区间左边界的前驱(可能是header)——调用者可通过valid()判断成功与否
}
//插入排序
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++) { //逐一为各节点
insert(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
while ( 0 < n--) {//从首节点p出发,将后续节点逐一与max比较
if (max->data <= p->data) max = p;//更新最大元素位置记录
p = p->succ;//向后移动指针
}
return max; //返回最大节点位置
}
template <class T> void swap(T& x, T& y)
{
T tmp = x;
x = y;
y = tmp;
}
//选择排序
template <typename T> //对列表中起始于位置p、宽度为n的区间做选择排序
void List<T>::selectionSort(ListNodePosi<T> p, int n) { //valid(p) && rank(p) + n <= size
ListNodePosi<T> head = header, tail = trailer; //待排序区间为(head, tail)
while (1 < n) { //在至少还剩两个节点之前,在待排序区间内
ListNodePosi<T> max = selectMax(head->succ, n); //找出最大者(歧义时后者优先)
//这里要特别注意,因为有可能存在节点会插入到头哨兵节点之后形成新的首节点,导致
//p的指针出现问题,所以不能在原始的区间上继续找最大节点,此处使用哨兵的后继指针,
//用来保证指针的正确性
//将其移至无序区间末尾(作为有序区间新的首元素)
if(tail->pred != max)
swap(tail->pred->data,max->data);// insert(remove(max), tail);
//插入与删除中存在new 和 delete 这些操作比一般的操作多出两个数量级
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依然指向归并后区间的(新)起点
//归并函数
template <typename T> //有序列表的归并:当前列表中自p起的n个元素,与列表L中自q起的m个元素归并
ListNodePosi<T> List<T>::merge(ListNodePosi<T> &p, int n, List<T>& L, ListNodePosi<T>& q, int m) {
// assert: this.valid(p) && rank(p) + n <= size && this.sorted(p, n)
// L.valid(q) && rank(q) + m <= L._size && L.sorted(q, m)
// 注意:在被mergeSort()调用时,this == &L && rank(p) + n = rank(q)
ListNodePosi<T> pp = p->pred; //归并之后p可能不再指向首节点,故需先记忆,以便在返回前更新
while ((0 < m) && (q != p)) //q尚未出界(或在mergeSort()中,p亦尚未出界)之前
if ((0 < n) && (p->data <= q->data)) //若p尚未出界且v(p) <= v(q),则
{
p = p->succ; n--;
} //p直接后移,即完成归入
else //否则,将q转移至p之前,以完成归入
{
q = q->succ;
insert(remove(q ->pred),p);
m--;
}
return pp->succ; //更新的首节点
}
template<typename T> int List<T>::uniquify() {
if (_size < 2) return 0;//就一个节点
int oldSize = _size;//记录原规模
ListNodePosi<T> p = header; ListNodePosi<T> q;//p为起点,q为p的后继
while (trailer != (q=p->succ))
{
if (p->data != q->data) p = q;//若互异,转入下一节点
else remove(q);//删除雷同的后者
}
return oldSize - _size;//被删的元素总数
}
//递增类对象
template<typename T> struct Increase{
virtual void operator ()(T& e) { e++; }//T可直接递增或已经重载了++
};
//递增函数
template<typename T> void increase(List<T>& L) {
L.traverse(Increase<T>());//遍历递增
}
//减半类对象
template<typename T> struct Half {
virtual void operator ()(T& e) { e >>= 1; }
};
//减半函数
template<typename T> void half(List<T>& L) {
L.traverse(Half<T>());//遍历减半
}
1.2列表节点头文件
//定义节点
using Rank = int; //秩
template <typename T> struct ListNode;
template <typename T> using ListNodePosi = 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); //紧随当前节点之后插入新节点
};
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; //返回新节点的位置
}
2.列表类
2.1列表类
template <typename T> class List { //列表模板类
private:
int _size; ListNodePosi<T> header, 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
int disordered() const;
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> insert(ListNodePosi<T> p, T const& e); //将e当作p的后继插入
ListNodePosi<T> insert(T const& e, ListNodePosi<T> p); //将e当作p的前驱插入
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 Print(); //打印列表的节点值
// 遍历
void traverse(void (*) (T&)); //遍历,依次实施visit操作(函数指针,只读或局部性修改)
template <typename VST> //操作器
void traverse(VST&); //遍历,依次实施visit操作(函数对象,可全局性修改)
}; //List
2.2初始化
//初始化函数
template <typename T> void List<T>::init() { //列表初始化,在创建列表对象时统一调用
header = new ListNode<T>; //创建头哨兵节点
trailer = new ListNode<T>; //创建尾哨兵节点
header->succ = trailer; header->pred = NULL;
trailer->pred = header; trailer->succ = NULL;
_size = 0; //记录规模
}
2.3打印输出
//打印节点的值
template <typename T> void List<T>::Print() {
ListNodePosi<T> p = header->succ;
while (p != trailer) {//因为存在尾哨兵,所以安全
std::cout << p->data << " ";//输出节点的值
p = p->succ;//向后移动
}
std::cout<<std::endl;//换行
}
2.4析构函数
//析构函数 所有销毁节点
template <typename T> List<T>::~List() //列表析构器
{
clear(); delete header; delete trailer;
} //清空列表,释放头、尾哨兵节点
2.5清空
//清空列表函数 只销毁可见节点 无法销毁头尾部哨兵
template <typename T> int List<T>::clear() { //清空列表
int oldSize = _size;
while (0 < _size) remove(header->succ); //反复删除首节点,直至列表变空
return oldSize;
}
2.6删除
//删除节点函数
template <typename T> 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; //返回备份的数值
}
2.7重载[ ]
//重载下标“ [ ] ”
template<typename T>
T& List<T>::operator[] (Rank r) const {
ListNodePosi<T> p=first();
while (0 < r--)p = p->succ;
return p->data;
}
2.8查找(无序)
//无序寻找
template <typename T> //在无序列表内节点p(可能是trailer)的n个(真)前驱中,找到等于e的最后者
ListNodePosi<T> List<T>::find(T const& e, int n, ListNodePosi<T> p) const {
while (0 < n--) //(0 <= n <= rank(p) < _size)对于p的最近的n个前驱,从右向左
if (e == (p = p->pred)->data) return p; //逐个比对,直至命中或范围越界
return NULL; //p越出左边界意味着区间内不含e,查找失败
} //失败时,返回NULL
2.9插入
//插入
//头插入
template<typename T> ListNodePosi<T> List<T>::insertAsFirst(T const& e) {
_size++;
return header->insertAsSucc(e);
}
//尾插入
template<typename T> ListNodePosi<T> List<T>::insertAsLast(T const& e) {
_size++;
return trailer->insertAsPred(e);
}
//前驱插入
template<typename T> ListNodePosi<T> List<T>::insert(T const& e, ListNodePosi<T> p) {
_size++;
return p->insertAsPred(e);
}
//后继插入
template<typename T> ListNodePosi<T> List<T>::insert(ListNodePosi<T> p, T const& e) {
_size++;
return p->insertAsSucc(e);
}
2.10去重
//无序 唯一化
template<typename T> int List<T>::deduplicate() {
if (_size < 2) return 0;
int oldSize = _size;
ListNodePosi<T> p = header;// ListNodePosi<T> p = first();
Rank r = 0;
while (trailer != (p = p->succ)) {//O(n)
ListNodePosi<T> q = find(p->data, r, p);//此时q与p雷同,但删除前者更为简明
q ? remove(q) : r++;//r为无重前缀的长度
}
return oldSize - _size;//删除元素总数
}
2.11逆序对判断
//是否逆序
template <typename T> int List<T>::disordered() const{
ListNodePosi<T> h = first();
int a = -1;
while (h!=trailer)
{
if (h->data > h->succ->data)
a++;
h = h->succ;
}
std::cout << "存在逆序对:" << a<<std::endl;
return a;
}
2.12复制方法
//复制方法
template <typename T> //列表内部方法:复制列表中自位置p起的n项
void List<T>::copyNodes(ListNodePosi<T> p, int n) { //p合法,且至少有n-1个真后继节点
init(); //创建头、尾哨兵节点并做初始化
while (n--) { insertAsLast(p->data); p = p->succ; } //将起自p的n项依次作为末节点插入
}
template <typename T> //复制列表中自位置p起的n项
List<T>::List(ListNodePosi<T> p, int n) {
copyNodes(p,n);
}
template <typename T> //整体复制列表L
List<T>::List(List<T>const & L ) {
copyNodes(L.first(), L._size);
}
template <typename T> //复制L中第r项起的项 r+n <= L._size
List<T>::List(List<T>const& L,int r,int n) {
copyNodes(L[r],n);
}
2.13遍历
//遍历函数
template<typename T> void List<T>::traverse( void(*visit) (T&) ) {//借助函数指针机制遍历
ListNodePosi<T> p = first();
while (p!=trailer){
//for (ListNodePosi<T> p = header->succ; p != trailer; p = p->succ) visit(p->data);
visit(p->data);
p = p->succ;
}
}
template<typename T> template<typename VST> //元素类型、操作器
void List<T>::traverse(VST& visit) {//借助函数对象机制遍历
ListNodePosi<T> p = first();
while (p != trailer) {
visit(p->data);
p = p->succ;
}
}
2.14排序
//排序接口
template <typename T> void List<T>::sort(ListNodePosi<T> p, int n) {
srand((int)time(NULL));//随机数种子
switch (rand()%3)
{
case 0:
std::cout << "调用插入排序后前:";
std::cout << std::endl;
Print(); disordered();
std::cout << "调用插入排序后:";
insertionSort(p, n);
std::cout << std::endl;
Print(); disordered();
break;
case 1:
std::cout << "调用选择排序前:";
std::cout << std::endl;
Print(); disordered();
std::cout << "调用选择排序后:";
selectionSort(p, n);
std::cout << std::endl;
Print(); disordered();
break;
default :
std::cout << "调用归并排序前:";
std::cout << std::endl;
Print(); disordered();
std::cout << "调用归并排序后:";
mergeSort(p, n);
std::cout << std::endl;
Print(); disordered();
break;
}
}
2.15查找(有序)
//有序向量查找
template <typename T> //在有序列表内节点p(可能是trailer)的n个(真)前驱中,找到不大于e的最后者
ListNodePosi<T> List<T>::search( T const& e,int n,ListNodePosi<T> p)const {
//0 <= n <= Rank(p) < _size
while (-1 < n--) {//对于p的n个前驱,从左往右进行比较
if ( (p = p->pred)->data <= e) break;//直到命中元素,数值越界或范围越界
}
return p;//失败时,返回区间左边界的前驱(可能是header)——调用者可通过valid()判断成功与否
}
2.16插入排序
//插入排序
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++) { //逐一为各节点
insert(search(p->data, r, p), p->data); //查找适当的位置并插入
p = p->succ; remove(p->pred); //转向下一节点
}
}
2.17最大值
//找出在列表中的最大值
template <typename T> //从起始于位置p的n个元素中选出最大者
ListNodePosi<T> List<T>::selectMax(ListNodePosi<T> p, int n) {
ListNodePosi<T> max = p; //最大者暂定为首节点p
while ( 0 < n--) {//从首节点p出发,将后续节点逐一与max比较
if (max->data <= p->data) max = p;//更新最大元素位置记录
p = p->succ;//向后移动指针
}
return max; //返回最大节点位置
}
2.18交换
template <class T> void swap(T& x, T& y)
{
T tmp = x;
x = y;
y = tmp;
}
2.19选择排序
//选择排序
template <typename T> //对列表中起始于位置p、宽度为n的区间做选择排序
void List<T>::selectionSort(ListNodePosi<T> p, int n) { //valid(p) && rank(p) + n <= size
ListNodePosi<T> head = header, tail = trailer; //待排序区间为(head, tail)
while (1 < n) { //在至少还剩两个节点之前,在待排序区间内
ListNodePosi<T> max = selectMax(head->succ, n); //找出最大者(歧义时后者优先)
//这里要特别注意,因为有可能存在节点会插入到头哨兵节点之后形成新的首节点,导致
//p的指针出现问题,所以不能在原始的区间上继续找最大节点,此处使用哨兵的后继指针,
//用来保证指针的正确性
//将其移至无序区间末尾(作为有序区间新的首元素)
if(tail->pred != max)
swap(tail->pred->data,max->data);// insert(remove(max), tail);
//插入与删除中存在new 和 delete 这些操作比一般的操作多出两个数量级
tail = tail->pred; n--;
}
}
2.20归并排序
//归并排序
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依然指向归并后区间的(新)起点
//归并函数
template <typename T> //有序列表的归并:当前列表中自p起的n个元素,与列表L中自q起的m个元素归并
ListNodePosi<T> List<T>::merge(ListNodePosi<T> &p, int n, List<T>& L, ListNodePosi<T>& q, int m) {
// assert: this.valid(p) && rank(p) + n <= size && this.sorted(p, n)
// L.valid(q) && rank(q) + m <= L._size && L.sorted(q, m)
// 注意:在被mergeSort()调用时,this == &L && rank(p) + n = rank(q)
ListNodePosi<T> pp = p->pred; //归并之后p可能不再指向首节点,故需先记忆,以便在返回前更新
while ((0 < m) && (q != p)) //q尚未出界(或在mergeSort()中,p亦尚未出界)之前
if ((0 < n) && (p->data <= q->data)) //若p尚未出界且v(p) <= v(q),则
{
p = p->succ; n--;
} //p直接后移,即完成归入
else //否则,将q转移至p之前,以完成归入
{
q = q->succ;
insert(remove(q ->pred),p);
m--;
}
return pp->succ; //更新的首节点
}
2.21去重(有序)
template<typename T> int List<T>::uniquify() {
if (_size < 2) return 0;//就一个节点
int oldSize = _size;//记录原规模
ListNodePosi<T> p = header; ListNodePosi<T> q;//p为起点,q为p的后继
while (trailer != (q=p->succ))
{
if (p->data != q->data) p = q;//若互异,转入下一节点
else remove(q);//删除雷同的后者
}
return oldSize - _size;//被删的元素总数
}
2.22递增减半
//递增类对象
template<typename T> struct Increase{
virtual void operator ()(T& e) { e++; }//T可直接递增或已经重载了++
};
//递增函数
template<typename T> void increase(List<T>& L) {
L.traverse(Increase<T>());//遍历递增
}
//减半类对象
template<typename T> struct Half {
virtual void operator ()(T& e) { e >>= 1; }
};
//减半函数
template<typename T> void half(List<T>& L) {
L.traverse(Half<T>());//遍历减半
}
3.主函数
#include<iostream>
#include "List.h"
using namespace std;
using T = int;
int main() {
List<T> L;
L.insertAsFirst(3);//头插法
//L.Print();//打印列表
L.disordered();
L.insertAsLast(2);//尾插入
L.Print();//打印列表
ListNodePosi<T> p=L.find(3);
L.insert(0,p);
L.Print();//打印列表
L.insert(p, 5);
L.Print();
ListNodePosi<T> q = p->succ;
L.insert(q, 5);
L.insert(p, 4);
L.insert(p, 4);
L.insert(p, 6);
L.Print();//打印列表
cout << "删除节点p:" << endl;
L.remove(p);//删除p
L.Print();//打印列表
L.insert(q, 5);//在q之后插入5
L.insert(8, q);//在q之前插入8
L.insert(4, q);//在q之前插入4
L.Print();//打印列表
cout << "去重后:" << endl;
L.deduplicate();//唯一化,去重
L.Print();
L.disordered();//逆序对
ListNodePosi<T> w = L.first();
L.insert(4, w);//在q之前插入4
L.insert(w, 9);//在w之后插入9
L.insert(w,0);//在w之前插入0
L.Print();
L.disordered();
ListNodePosi<T> h= L.first();
cout << endl;
L.sort(h,L.size());
L.uniquify();
L.Print();
system("pause");
return 0;
}
4.运行结果截图
以上所有代码参考邓俊辉老师的《c++语言版数据结构》,邓老师的数据结构真的太好了!