数据结构2—列表

#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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值