#pragma once
/*
向量中的秩同时对应于逻辑和物理次序,而列表中的位置仅对应于逻辑次序。
注意思考:
为什么在编写方法时,返回值为什么要是那个类型?函数参数为什么要那么多个?分别又为什么要是那些类型?
如果换做是你,你怎么编写这些接口?
*/
typedef int Rank;
#define ListNodePosi ListNode<T>*
//List的节点ADT
template <typename T>
struct ListNode
{
T data;
ListNode<T> *pre;
ListNode<T> *next;
ListNode() {}
//创建一个节点,可分别指定其前驱和后继
ListNode(T e, ListNodePosi p = NULL, ListNodePosi n = NULL) :data(e), pre(p), next(n) {}
//将元素e插入到指定节点的前/后
ListNodePosi insertAsPred(T const &e);
ListNodePosi insertAsNext(T const &e);
};
template <typename T>
ListNodePosi ListNode<T>::insertAsPred(T const &e)
{
//pre = this->pre;代表当前节点的前驱
ListNodePosi x = new ListNode(e,pre,this);
pre->next = x;pre = x;
return x;
}
template <typename T>
ListNodePosi ListNode<T>::insertAsNext(T const &e)
{
//next=this->next;代表当前节点的后继
ListNodePosi x = new ListNode(e, this,next);
next->pre = x; next = x;
return x;
}
//List的模板类
template <typename T>
class List
{
public:
//构造函数
List() { init(); }//默认
List(List<T> const &L);//整体复制列表L
List(List<T> const &L, Rank r,int n);//复制列表L中自第r项起的n项
List(ListNodePosi p,int n);//复制列表中自位置p起的n项
virtual ~List();//释放包含头、尾哨兵在内的所有节点
//只读访问接口
Rank size() const { return _size; }//规模
bool empty() const { return _size <= 0; }//判空
T &operator[](Rank r)const;//重载,支持循秩访问(效率低)
ListNodePosi first()const { return header->next; }//首节点位置
ListNodePosi last()const { return trailer->pre; }//末节点位置
bool valid(ListNodePosi p);//判断位置p是否对外合法
int disordered()const;//返回列表中逆序相邻元素对的总数
ListNodePosi find(T const & e)const { return find(e, _size, trailer); }
ListNodePosi find(T const &e, int n, ListNodePosi p)const;//在无序列表内节点p的n个前驱中,找到等于e的最后者
ListNodePosi search(T const & e)const { return search(e, _size, trailer); }
ListNodePosi search(T const &e, int _size, ListNodePosi p)const;//在有序列表内节点p的n个前驱中,找到<=e的最后者
ListNodePosi selectMax()const { return selectMax(header->next, _size); }//整体最大
ListNodePosi selectMax(ListNodePosi p,int n)const;//在p及n-1个后继中选出最大者
//可写访问接口
ListNodePosi insertAsFirst(T const &e);//将e当作首节点插入
ListNodePosi insertAsLast(T const &e);//将e当作末节点插入
ListNodePosi insertBefore(ListNodePosi p, T const &e);//将e当作p的前驱插入
ListNodePosi insertAfter(ListNodePosi p, T const &e);//将e当作p的后继插入
T remove(ListNodePosi p);//删除合法位置p处的节点,返回被删除的节点
void merge(List<T>& L);//全列表归并
void sort() { sort(first(), _size); }//整体排序
void sort(ListNodePosi p, int n);//区间排序
int deduplicate();//无序重
int uniquify();//有序去重
void reverse();//前后倒置
//遍历
void traverse(void(*)(T&));//遍历
template <typename VST>//操作器
void traverse(VST&);
friend ostream& operator<<(ostream &os, const List<T> &V);
protected:
void init();//列表创建时的初始化
int clear();//清除所有节点
Rank rank(ListNodePosi);//返回指定指针处的顺序索引值,从0开始。
ListNodePosi rank(Rank r);//返回指定顺序索引值处的指针,从0开始。
void copyNodes(ListNodePosi, int);//复制列表中自位置p起的n项,这个接口只能用来作为构造函数的内部接口,不能外调。
void merge(ListNodePosi &,int,List<T> &, ListNodePosi &, int);//有序列表区间归并
void mergeSort(ListNodePosi &,int);//对从p开始连续的n个节点归并排序
void selectionSort(ListNodePosi, int);//对从p开始连续的n个节点选择排序
void insertionSort(ListNodePosi, int);//对从p开始连续的n个节点插入排序
private:
int _size;
ListNodePosi header;//头、尾两个哨兵节点,对外不可见。引入的新节点都插入于这对哨兵节点之间。
ListNodePosi trailer;//设置头尾节点的目的:尾-->查找方便 头-->对空、非空、首节点统一处理
};
template <typename T>
void List<T>::init()
{
header = new ListNode<T>();
trailer = new ListNode<T>();
header->pre = trailer->next = NULL;
header->next = trailer;
trailer->pre = header;
_size = 0;
}
template <typename T>
int List<T>::clear()
{
int oldSize = _size;
while (_size)remove(header->next);
return oldSize;
}
template <typename T>
Rank List<T>::rank(ListNodePosi p)
{
assert(p != NULL);
Rank index = 0;
ListNodePosi r = NULL;
for (r = first(); r != p; r = r->next, index++);
return r == trailer ? -1:index;
}
template <typename T>
ListNodePosi List<T>::rank(Rank r)
{
assert(r <= _size);
Rank index = 0;
ListNodePosi p = first();
for (Rank index = 0; r != index; index++, p=p->next);
return p;
}
template <typename T>
void List<T>::copyNodes(ListNodePosi p, int n)
{
init();
while (n--) {
insertAsLast(p->data); p = p->next;
}
}
template <typename T>//有序列表的归并:当前列表中自p起的n个元素,与列表L中自q起的m个元素归并
void List<T>::merge(ListNodePosi &p, int n, List<T> &L, ListNodePosi &q, int m)
{
//assert:valid(p) && rank(p)+n<=_size && sorted(p,n) && L.valid(q) && rank(q)+m<=L._size && L.sorted(q,m)
//注意:在归并排序之类的场合,有可能this == L && rank(p)+n = rank(q)
ListNodePosi pp = p->pre;
while (0 < m)//在q尚未移出区间之前
{
if ((0 < n) && (p->data <= q->data))//若p仍在区间,且v(p)<=v(q)
{
if (q == (p = p->next))break; n--;//将p替换为其直接后继(等效于将p归入合并的列表)
}
else//若p已超出右界或v(q)<v(p)
{
insertBefore(p, L.remove((q = q->next)->pre)); m--;//将q移至p之前
}
}
p = pp->next;//确定归并后的新起点
}
template <typename T>//列表的归并排序算法:对起始于p位置的n个元素排序
void List<T>::mergeSort(ListNodePosi &p, int n)
{
int m = n >> 1;
ListNodePosi q = p;
for (int i = 0; i < m; i++)q = q->next;
mergeSort(p, m); mergeSort(q, n-m);
merge(p,m,*this,q,n-m);//排序后p依然指向归并区间后的新起点
}
template <typename T>//列表的选择排序算法:对起始于位置p的那个元素排序
void List<T>::selectionSort(ListNodePosi p, int n)
{
assert(n <= _size);
ListNodePosi q = p->next;
T t;
for (Rank i = 0; i < n-1; i++) {
for (Rank k = i; k < n-1; k++, q = q->next) {
if (q->data < p->data) {
t = q->data;
q->data = p->data;
p->data = t;
}
}
p = p->next;
q = p;
}
}
template <typename T>
void List<T>::insertionSort(ListNodePosi p, int n)
{
//始终将整个序列视作两部分:有序的前缀,无序的后缀,通过迭代,反复的将后缀的首元素移至前缀中
cout << "n:" << n << "\trank:" << rank(p) << endl;
assert(valid(p) == true && n + rank(p) <= _size);
for (int r = 0; r < n+1; r++) {
insertAfter(search(p->data, r, p), p->data);
p = p->next; remove(p->pre);
}
}
template <typename T>
List<T>::List(List<T> const &L)
{
copyNodes(L.first(), L.size());
}
template <typename T>
List<T>::List(List<T> const &L, Rank r, int n)
{
assert(r + n < _size);
ListNodePosi p = L.first();
while (r--) p = p->next;
copyNodes(p, n);
}
template <typename T>
List<T>::List(ListNodePosi p, int n)
{
copyNodes(p,n);
}
template <typename T>
List<T>::~List()
{
clear(); delete header; delete trailer;
}
template <typename T>
bool List<T>::valid(ListNodePosi p)
{
return p == NULL ? false : true;
}
template <typename T>
int List<T>::disordered()const
{
if (_size < 2)return 0;
ListNodePosi p = header->next;
ListNodePosi q = p->next;
int n = 0;
for (; q! = trailer; p = q, q = q->next)
p->data > q->data ? n++ : n;
return n;
}
template<typename T>
ListNodePosi List<T>::find(T const &e, int n, ListNodePosi p)const
{
while (n--) {
if (p->pre->data == e)return p;
}
return NULL;
}
template <typename T>
ListNodePosi List<T>::search(T const &e, int n, ListNodePosi p)const
{
while (n--) {
if ((p = p->pre)->data <= e)break;
}
return p;
}
template <typename T>
ListNodePosi List<T>::selectMax(ListNodePosi p, int n)const
{
assert(n <= _size);
ListNodePosi max = p;
for (ListNodePosi cur = p; 1 < n; n--) {
if (!lt((cur = cur->next)->data, max->data))
max = cur;
}
return max;
}
template<typename T>
T& List<T>::operator[](Rank r)const
{
assert(r < _size);
ListNodePosi p = first();
while (r--) {
p = p->next;
}
return p->data;
}
template<typename T>
ListNodePosi List<T>::insertAsFirst(T const &e)
{
_size++; return header->insertAsNext(e);
}
template<typename T>
ListNodePosi List<T>::insertAsLast(T const &e)
{
_size++; return trailer->insertAsPred(e);
}
template<typename T>
ListNodePosi List<T>::insertBefore(ListNodePosi p,T const &e)
{
assert(p != NULL);
_size++; return p->insertAsPred(e);
}
template<typename T>
ListNodePosi List<T>::insertAfter(ListNodePosi p, T const &e)
{
assert(p != NULL);
_size++; return p->insertAsNext(e);
}
template<typename T>
T List<T>::remove(ListNodePosi p)
{
assert(p != NULL);
T e = p->data;
p->pre->next = p->next;
p->next->pre = p->pre;
p->pre = NULL;
p->next = NULL;
delete p; _size--; p = NULL;
return e;
}
template<typename T>
void List<T>::merge(List<T>& L)
{
mergeSort(L.first(), L.size());
}
template<typename T>
void List<T>::sort(ListNodePosi p, int n)
{
switch (rand() % 3)
{
case 1:insertionSort(p, n); break;
case 2:selectionSort(p,n); break;
default:mergeSort(p, n); break;
}
}
template<typename T>
int List<T>::deduplicate()
{
ListNodePosi h = header;
ListNodePosi p = NULL;
int oldSize = _size;
Rank r = 0;
while ((h=h->next) != trailer) {
p = find(h->data,r, h);
p ? remove(p) : r++;
}
return oldSize - _size;
}
template<typename T>
int List<T>::uniquify()
{
int oldSize = _size;
ListNodePosi p = NULL;
ListNodePosi q = NULL;
for (p = header,q = p->next; p != trailer; p = q,q = q->next)
{
if (p->data == q->data) {
remove(q); q = p;
}
}
return oldSize - _size;
}
template<typename T>
void List<T>::reverse()
{
int n = _size;
ListNodePosi p = first();
ListNodePosi q = last();
p->pre = NULL; q->next = NULL;
header->next = trailer;
trailer->pre = header;
_size = 0;
while (n--)
{
insertAsFirst(p->data);
q = p->next; p->next = NULL;
p->pre = NULL; delete p; p = q;
}
}
template<typename T>
void List<T>::traverse(void(*visit)(T&))
{
ListNodePosi p = first();
while (p != trailer) {
visit(p->data);
p->next;
}
}
template<typename T>
template <typename VST>
void List<T>::traverse(VST&)
{
}
template<typename T>
ostream &operator<<(ostream &os, List<T> &V)
{
os << "V[";
for (int i = 0; i < V.size(); i++)
os << V[i] << ",";
os << "]";
return os;
}
数据结构2—列表
最新推荐文章于 2022-08-08 00:23:29 发布