C++ 手动实现双线链表(作业版)

news2024/11/27 16:50:51

双向链表,并实现增删查改等功能

首先定义节点类,类成员包含当前节点的值, 指向下一个节点的指针和指向上一个节点的指针

//节点定义
template <typename T>
class Node {
public:
    Node<T>* prior;
    T value;
    Node<T>* next;
    Node():value(0),prior(nullptr),next(nullptr) {}
    Node(T n):prior(nullptr),value(n),next(nullptr) {}
};

然后是链表类的定义,主要包含了增删查改等功能

//双向链表定义
template <typename T>
class LinkList_doubly {
public:
    Node<T>* firstNode;
    Node<T>* lastNode;

    LinkList_doubly();
    LinkList_doubly(int n, const T* arr);
    LinkList_doubly(const LinkList_doubly<T>& link);
    ~LinkList_doubly();
    LinkList_doubly<T>& push_back(T n);
    LinkList_doubly<T>& push_front(T n);
    LinkList_doubly<T>& insert(int pos, int n, T* arr);
    LinkList_doubly<T>& pop_front();
    LinkList_doubly<T>& pop_back();
    LinkList_doubly<T>& remove(int pos, int num);
    LinkList_doubly<T>& reverse();
    T& operator[](int n);
    T& at(int n);
    LinkList_doubly<T>& replace(int pos, int n, T* arr);
    int getLen() {return len;}
    void clear() {this->~LinkList_doubly();}
    void display();
private:
    int len = 0;
    Node<T>* getNode_next(int n);

};

各个函数解释:

LinkList_doubly();      默认构造函数

LinkList_doubly(const T* arr, int len);      一般构造函数

LinkList_doubly(const LinkList<T>& link)           拷贝构造函数

~LinkList_doubly();     析构函数

LinkList_doubly<T>& push_back(T n);    在尾部添加一个元素

LinkList_doubly<T>& push_front(T n);     在头部添加一个元素

LinkList_doubly<T>& insert(int pos, int n, T* arr);   在pos处插入n个元素

LinkList_doubly<T>& pop_front();    删除第一个节点

LinkList_doubly<T>& pop_back();    删除最后一个节点

LinkList_doubly<T>& remove(int pos, int num);     删除pos开始的num个元素

LinkList_doubly<T>& reverse();     反转链表

T& operator[](int n);     重载[ ]运算符,返回第n个节点的值

T& at(int n);                 与[ ]一样,只不过会检查索引是否越界

LinkList_doubly<T>& replace(int pos, int n, T* arr);    替换n个节点

int getLen() {return len;}     返回长度,因为len是private

void clear() {this->~LinkList();}    清除链表

void display();    显示链表所有元素

Node<T>* getNode_next(int n);     返回第n个节点的next指针

#include <iostream>
using namespace std;

template <typename T>
class Node {
public:
    Node<T>* prior;
    T value;
    Node<T>* next;
    Node():value(0),prior(nullptr),next(nullptr) {}
    Node(T n):prior(nullptr),value(n),next(nullptr) {}
};

template <typename T>
class LinkList_doubly {
public:
    Node<T>* firstNode;
    Node<T>* lastNode;

    LinkList_doubly();
    LinkList_doubly(int n, const T* arr);
    LinkList_doubly(const LinkList_doubly<T>& link);
    ~LinkList_doubly();
    LinkList_doubly<T>& push_back(T n);
    LinkList_doubly<T>& push_front(T n);
    LinkList_doubly<T>& insert(int pos, int n, T* arr);
    LinkList_doubly<T>& pop_front();
    LinkList_doubly<T>& pop_back();
    LinkList_doubly<T>& remove(int pos, int num);
    LinkList_doubly<T>& reverse();
    T& operator[](int n);
    T& at(int n);
    LinkList_doubly<T>& replace(int pos, int n, T* arr);
    int getLen() {return len;}
    void clear() {this->~LinkList_doubly();}
    void display();
private:
    int len = 0;
    Node<T>* getNode_next(int n);

};


//默认构造函数
template <typename T>
LinkList_doubly<T>::LinkList_doubly() {
    firstNode = nullptr;
    lastNode = nullptr;
    len = 0;
}

//一般构造函数,用数组进行初始化
template <typename T>
LinkList_doubly<T>::LinkList_doubly(int n, const T* arr) {
    Node<T>* temp1 = nullptr;
    Node<T>* temp2 = nullptr;
    for (int i = 0; i < n; i++) {
        temp1 = new Node<T> (arr[i]);
        if ( i == 0 )
            firstNode = temp1;
        if ( i == n-1 )
            lastNode = temp1;
        temp1->prior = temp2;
        if ( i > 0 )
            temp2->next  = temp1;
        temp2 = temp1;
    }
    this->len = n;
}

//拷贝构造函数
template <typename T>
LinkList_doubly<T>::LinkList_doubly(const LinkList_doubly<T>& link) {
    this->firstNode = link.firstNode;
    this->lastNode  = link.lastNode;
    this->len = link.getLen();
}

//析构函数
template <typename T>
LinkList_doubly<T>::~LinkList_doubly() {
    this->len = 0;
    Node<T>* temp = firstNode;
    lastNode = nullptr;
    while ( firstNode ) {
        temp = firstNode;
        firstNode = firstNode->next;
        delete temp;
        temp = nullptr;
    }
}

//在尾部添加一个元素
template <typename T>
LinkList_doubly<T>& LinkList_doubly<T>::push_back(T n) {
    Node<T>* newNode = new Node<T> (n);
    newNode->prior = lastNode;
    lastNode->next = newNode;
    lastNode = newNode;
    len++;
    return *this;
}

//在头部添加一个元素
template <typename T>
LinkList_doubly<T>& LinkList_doubly<T>::push_front(T n) {
    Node<T>* newNode = new Node<T> (n);
    newNode->next = firstNode;
    firstNode->prior = newNode;
    firstNode = newNode;
    len++;
    return *this;
}

//在position位置插入n个元素
template <typename T>
LinkList_doubly<T>& LinkList_doubly<T>::insert(int pos, int n, T* arr) {
    Node<T>* temp_end = getNode_next(pos);
    Node<T>* temp_front = getNode_next(pos-1);
    Node<T>* temp_new = nullptr;
    for ( int i = 0; i < n; i++ ) {
        temp_new = new Node<T> (arr[i]);
        temp_front->next = temp_new;
        temp_new->prior = temp_front;
        temp_front = temp_front->next;
    }
    temp_front->next = temp_end;
    temp_end->prior = temp_front;
    len += n;
    return *this;
}

//删除第一个元素
template <typename T>
LinkList_doubly<T>& LinkList_doubly<T>::pop_front() {
    firstNode = firstNode->next;
    firstNode->prior = nullptr;
    len--;
    return *this;
}

//删除最后一个元素
template <typename T>
LinkList_doubly<T>& LinkList_doubly<T>::pop_back() {
    lastNode = lastNode->prior;
    lastNode->next = nullptr;
    len--;
    return *this;
}

//删除position开始的num个元素
template <typename T>
LinkList_doubly<T>& LinkList_doubly<T>::remove(int pos, int num) {
    Node<T>* temp_front = getNode_next(pos-1);
    Node<T>* temp_end = getNode_next(pos+num);
    temp_front->next = temp_end;
    temp_end->prior = temp_front;
    len -= num;
    return *this;
}

//替换元素
template <typename T>
LinkList_doubly<T>& LinkList_doubly<T>::replace(int pos, int n, T* arr) {
    Node<T>* temp = getNode_next(pos);
    for ( int i = 0; i < n; i++ ) {
        temp->value = arr[i];
        temp = temp->next;
    }
    return *this;
}

//反转链表,终极偷懒写法,实在不想动脑子了
template <typename T>
LinkList_doubly<T>& LinkList_doubly<T>::reverse() {
    const int num = len;
    T arr[num];
    Node<T>* temp = firstNode;
    for ( int i = 0; i < this->len; i++ ) {
        arr[i] = temp->value;
        temp = temp->next;
    }
    temp = lastNode;
    for ( int i = 0; i < this->len; i++ ) {
        temp->value = arr[i];
        temp = temp->prior;
    }
    return *this;
}

//访问第n个元素
template <typename T>
T& LinkList_doubly<T>::operator[](int n){
    Node<T>* temp = nullptr;
    if ( n <= len/2 ) {
        temp = firstNode;
        for ( int i = 0; i < n; i++ ) {
            temp = temp->next;
        }
    } else {
        temp = lastNode;
        for ( int i = 0; i < len-1-n; i++ ) {
            temp = temp->prior;
        }
    }
    return temp->value;

}

//访问第n个元素,增加索引检查

template <typename T>
T& LinkList_doubly<T>::at(int n){
    if ( n < 0 || n > len-1 ) {
        cout << "[error]:index out of range" << endl;
        exit(0);
    }
    return (*this)[n];
}
//获取第n个Node的next指针
template <typename T>
Node<T>* LinkList_doubly<T>::getNode_next(int n) {
    if ( n > len-1 ) {
        cout << "[error]: illegal index" << endl;
    }
    Node<T>* temp = firstNode;
    for ( int i = 0; i < n; i++ ) {
        temp = temp->next;
    }
    return temp;
}

//显示链表所有元素,会对链表正反向一致性进行检查
template <typename T>
void LinkList_doubly<T>::display() {
    const int num = len;
    T arr1[num];
    T arr2[num];
    Node<T>* temp = firstNode;
    for ( int i = 0; i < this->len; i++ ) {
        arr1[i] = temp->value;
        temp = temp->next;
    }
    temp = lastNode;
    for ( int i = 0; i < this->len; i++ ) {
        arr2[i] = temp->value;
        temp = temp->prior;
    }
    for ( int i = 0; i < this->len; i++ ) {
        if ( arr1[i] != arr2[len-1-i] ) {
            cout << "第"<<i<<"个元素正反向结果不一致" <<  arr1[i] << " " << arr2[len-1-i] << endl;
            exit(0);
        }
    }

    temp = firstNode;
    for ( int i = 0; i < this->len; i++ ) {
        cout << temp->value << " ";
        temp = temp->next;
    }
    cout << endl;
}

int main() {
    int arr[] = {1,5,7,3,5,3,1};
    LinkList_doubly<int> link(sizeof(arr)/sizeof(int), arr);
    link.display();
    link.push_back(25);
    link.display();
    link.push_front(10);
    link.display();
    int arr2[] = {1,0,0,4};
    link.insert(2,sizeof(arr2)/sizeof(int), arr2);
    link.display();
    link.pop_front();
    link.display();
    link.pop_back();
    link.display();
    link.remove(2,2);
    link.display();
    int arr3[] = {2,3,5};
    link.replace(4, sizeof(arr3)/sizeof(int), arr3);
    link.display();
    link.reverse();
    link.display();
    cout << link[8] << " " << link.at(3) << endl;
    cout << link.getLen() << endl;
    link.~LinkList_doubly();
    cout << link.getLen() << endl;

}

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/27071.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Python对Excel的读取

在python自动化中&#xff0c;经常会遇到对数据文件的操作&#xff0c;比如添加多名员工&#xff0c;但是直接将员工数据写在python文件中&#xff0c;不但工作量大&#xff0c;要是以后再次遇到类似批量数据操作还会写在python文件中吗&#xff1f; 应对这一问题&#xff0c;可…

【OpenDDS开发指南V3.20】第七章:运行时配置

配置方式 OpenDDS 包括一个基于文件的配置框架,用于配置全局选项以及与特定发布者和订阅者相关的选项,例如发现和传输配置。 OpenDDS 还允许通过命令行对有限数量的选项和配置 API 进行配置。 本章总结了 OpenDDS 支持的配置选项。 OpenDDS 配置涉及三个主要领域: 通用配…

QT 实现简单的天气 哈哈

前 言 前段时间开始接触QT&#xff0c;想着没事学习一下QT&#xff0c;这个小列子主要是用到了QJSON 和QNetworkAccessManager 来实现&#xff0c;QJSON 主要是用来json格式文件的解析&#xff0c;QNetworkAccessManager 主要来实现网络请求。 界面展示 界面上看非常low&…

解决java: 程序包org.springframework.boot不存在的解决方法

问题描述 最近IDEA抽风了&#xff0c;不管是新建SpringBoot工程&#xff0c;还是导入项目。 IDEA代码里面都会飘红~ Build项目时&#xff0c;会提示错误&#xff1a;错误:(3, 32) java: 程序包org.springframework.boot不存在 后来找到一个靠谱的解决方案&#xff0c;建议使…

Java如何安装https证书

Java为什么需要证书&#xff1f; 出于安全的考虑&#xff0c;很多网站都使用https 协议&#xff0c;而要访问一个https 的站点则需要一个证书文件&#xff0c;这些证书文件由CA (Certificate Authority) 颁布&#xff0c; 各站点将这些认证过的证书放在各自的服务器上&#xf…

深度解析:为何在 SwiftUI 视图的 init 初始化器里无法更改 @State 的值?

问题现象 如下代码所示,我们希望用 “hopy” 初始化 ContentView 中的 secret 属性,但是最终 ContentView 显示时, secret 的值仍旧为默认值 “none” ! 为什么会出现这种情况呢? 其实答案就在 @State 包装器属性内部实现机制上,它比表面看起来要复杂那么一丢丢。 在本…

第十四届校模拟赛第一期(一)

“须知少时凌云志&#xff0c;自许人间第一流” 鄙人11月八号有幸参加学校校选拔赛&#xff0c;题型为5道填空题&#xff0c;5道编程题&#xff0c;总时间为4小时。奈何能力有限&#xff0c;只完成了5道填空和3道编程大题&#xff0c;现进行自省自纠&#xff0c;分享学习&#…

Unity | Cinemachine 2D 设置边界及错误记录

1 背景介绍 在使用大地图的项目中&#xff0c;通常需要摄像机跟随玩家移动&#xff0c;而且需要根据地图尺寸限制摄像机的边界 借助 Cinemachine 及其扩展组件 CinemachineConfiner 可以很方便的实现该功能&#xff0c;但这次遇见一个问题&#xff1a;运行时&#xff0c;当摄…

世界杯今日胜负预测(阿根廷VS沙特阿拉伯,丹麦VS突尼斯)

首先是今天开局的两场 阿根廷VS沙特阿拉伯————阿根廷胜 理由&#xff1a; 1、国家队世界男足排名第三 2、在今年阿根廷的近期战绩 3、经常关注世界杯的粉丝观点 4、抖音平台预测数据&#xff0c;截止时间14:46 丹麦VS突尼斯————丹麦胜 理由&#xff1a; 1、丹麦国…

CPT-CY3/CY5/CY7/CY7.5/花菁染料CY3/Y5/CY7/CY7.5/抗Trop-2 IgG抗体偶联顺铂的制备

小编今天给大家分享了CPT-CY3/CY5/CY7/CY7.5/花菁染料CY3/Y5/CY7/CY7.5/抗Trop-2 IgG抗体偶联顺铂的制备方法&#xff0c;一起来看看。 抗Trop-2 IgG抗体偶联顺铂的制备&#xff1a; 转染Trop-2质粒至293F细胞,利用Protein A亲和柱纯化,获得人源抗Trop-2 IgG抗体.酶联免疫吸附…

Qt Quick-PySide2使用qrc文件

Qt Quick中PySide2使用qrc文件、Controls2设置全局样式、VSCode任务。 使用步骤 创建一个 resource.qrc 文件 <RCC><qresource prefix"/"><file>qtquickcontrols2.conf</file><file>images/images.png</file></qresource&…

反射、类的加载时机、类加载过程的详细流程图

目录 一、反射 1、静态加载 2、动态加载 二、类加载的时机 三、类加载的流程图 四、类加载的三个阶段的详细解释 1.1 加载 1.2 连接 1、验证 2、准备 3、解析 1.3 初始化 一、反射 反射机制是java实现动态语言的关键&#xff0c;也就是哦天哪故宫反射实现类动态加载…

Linux安装Oracle19c(极简版)

Oracle下载oracle-database-preinstall-19c-1.0-1.el7.x86_64.rpmoracle-database-ee-19c-1.0-1.x86_64.rpmOracle安装 cd /opt yum -y localinstall oracle-database-preinstall-19c-1.0-1.el7.x86_64.rpm yum -y localinstall oracle-database-ee-19c-1.0-1.x86_64.rpm 环境变…

RHCE学习 --- 第八次作业(ansible)

RHCE学习 — 第八次作业&#xff08;ansible&#xff09; \ 一、基础环境&#xff1a; 采用一台centos7的主机为控制节点master&#xff0c;两台centos8的主机为受控节点&#xff08;node01&#xff0c;node02&#xff09; 三台主机均安装ansible并可以使用 三台主机有IP地…

My Sixty-seventh Page - 0-1背包问题理论 - By Nicolas

小尼在这里跟大家说明一下0-1背包问题的理论&#xff0c;首先我们需要认识一下什么是背包问题。小尼在这里拉一下代码随想录的代码&#xff0c;有兴趣的小伙伴也想把背包问题学好&#xff0c;可以去代码随想录看一看背包问题的讲解&#xff0c;也可以去B站看一看代码随想录对背…

java项目-第158期ssm仓库智能仓储系统_java毕业设计_计算机毕业设计

java项目-第158期ssm仓库智能仓储系统_java毕业设计_计算机毕业设计 今天分享的项目是《ssm仓库智能仓储系统》 该项目分为3个角色&#xff0c;管理员、员工、供应商。 员工角色登录后台&#xff0c;主要负责流水线工作&#xff0c;比如&#xff1a;查看供应商、 货物采购管理…

【计算机视觉OpenCV基础】实验一 图像预处理

实验一 图像预处理 计算机视觉OpenCV基础实验合辑&#xff08;实验1234扩展&#xff09; 资源下载地址&#xff1a; https://download.csdn.net/download/weixin_53403301 合辑&#xff1a;&#xff08;加在下载地址后面&#xff09; /87113581 讲义&#xff08;包括理论、图例…

MCE | 分子伴侣介导的自噬

自噬是细胞在外界环境因素的影响下&#xff0c;利用溶酶体&#xff0c;降解自身受损、变性大分子物质或者细胞器的自我消化过程。依据其发生途径&#xff0c;主要分为三种&#xff1a;巨自噬 (Macroautophagy)&#xff0c;微自噬 (Microautophagy) 和分子伴侣介导的自噬 (Chape…

MyBatis 缓存机制

文章目录一、一级缓存二、二级缓存1.cache 元素2.缓存命中率一、一级缓存 MyBatis 的一级缓存是 SqlSession 级别的缓存。如果同一个 SqlSession 对象多次执行完全相同的 SQL 语句&#xff0c;在第一次执行完成后&#xff0c;MyBatis 会将查询结果写入一级缓存中&#xff0c;此…

mysql中的binlog用法

binlog是什么 MySQL的二进制日志binlog可以说是MySQL最重要的日志&#xff0c;它记录了所有的DDL和DML语句&#xff08;除了数据查询语句select&#xff09;,以事件形式记录&#xff0c;还包含语句所执行的消耗的时间&#xff0c;MySQL的二进制日志是事务安全型的。使用mysqlb…