C++ 数据结构学习 ---- 列表

这篇博客深入探讨了C++中数据结构列表的实现,包括列表类的设计、初始化、打印输出、析构函数、清空、删除、重载运算符、查找、插入、去重、逆序对判断等操作。文章还涵盖了排序算法如插入排序、选择排序、归并排序,并讨论了有序列表的特殊操作。通过主函数展示了实际应用,并附有运行结果截图。
摘要由CSDN通过智能技术生成

目录

1.头文件

1.1列表头文件

1.2列表节点头文件

2.列表类

2.1列表类

2.2初始化

2.3打印输出

2.4析构函数

2.5清空

2.6删除

2.7重载[ ]

2.8查找(无序)

2.9插入

2.10去重

2.11逆序对判断

2.12复制方法

2.13遍历

2.14排序

2.15查找(有序)

2.16插入排序

2.17最大值

2.18交换

2.19选择排序

2.20归并排序

2.21去重(有序)

2.22递增减半

3.主函数

4.运行结果截图


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>c
  • 1
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值