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

news2024/11/26 0:53:00

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

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

//节点定义
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/27690.html

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

相关文章

减少乘法次数的优化算法(Gauss、Strassen、Winograd)

目录 Gauss算法 Strassen算法 Winograd算法 Winograd 1D Winograd 2D 在硬件设计中&#xff0c;乘法无论是在逻辑资源的使用上还是组合逻辑的延时上都要比加法高很多。从硬件方面考虑&#xff0c;我们都更倾向于将乘法转换成移位和加法&#xff0c;譬如乘以8&#xff0c;可…

stm32项目平衡车详解(stm32F407)

stm32项目 stm32项目介绍值平衡车 本文章学习借鉴于创客学院团队&#xff0c;以表感谢。教学视频 文章目录stm32项目前言一、平衡小车平衡小车的功能介绍平衡小车功能开发需求平衡小车整体框架小车环境数据采集进程1. 平衡小车姿态信息介绍2. 平衡小车项目工程框架搭建3. Mpu6…

【面试题】原型和原型链

1. 如何用class实现继承 // 父类 class People{constructor(name){this.name name}eat(){console.log(${this.name} eat something)} }// 子类 class Student extends People{constructor(name, number){super(name)this.number number}sayHi(){console.log(姓名&#xff1a…

自动化脚本如何切换环境?Pytest这些功能你必须要掌握

文章目录一、前言二、安装三、使用第1种:使用方式是终端添加–base-url这个命令第2种:使用方式是在pytest.ini配置文件种去配置base_url,然后自动读取url的数据&#xff0c;这样就不用添加–base-url这个命令行参数了&#xff1a;第3种:pytest有个hooks函数&#xff0c;可以自定…

最优二叉搜索树问题(Java)

最优二叉搜索树问题&#xff08;Java&#xff09; 文章目录最优二叉搜索树问题&#xff08;Java&#xff09;1、前置介绍2、算法设计思路2.1 最优二叉搜索树的结构2.2 一个递归算法2.3 计算最优二叉搜索树的期望搜索代价3、代码实现4、复杂度分析5、参考资料1、前置介绍 设S{x…

R语言探索 BRFSS 数据和预测

加载包 library(ggplot2) library(dplyr) library(Hmisc) library(corrplot) 加载数据 load("brfss2013.RData") 第1部分&#xff1a;关于数据 行为风险因素监测系统&#xff08;BRFSS&#xff09;是美国的年度电话调查。BRFSS旨在识别成年人口的风险因素并报告…

docker启动出现Error response from daemon: Cannot restart container的报错

1、发现问题 突然发现启动(重启)容器的时候报这个错 Error response from daemon: Cannot restart container 容器id: driver failed programming external connectivity on endpoint 容器名 (容器id): (iptables failed: iptables --wait -t nat -A DOCKER -p tcp -d 0/0 --…

图像超分辨率:优化最近邻插值Super-Resolution by Predicting Offsets

文章目录3. Super-Resolution by Predicting Offsets3.1. 这篇论文用于处理栅格化图像的超分&#xff0c;不知道这样翻译对不对&#xff0c;3.2. 作者认为栅格图像的边缘比较规则&#xff0c;可以训练一个offset map移动栅格图像的 边缘点&#xff08;背景和前景像素 移动 和交…

能率携手梦想改造家,打造适老化住宅新典范

家装改造类节目《梦想改造家》第九季温情回归&#xff0c;日本一级建筑设计师本间贵史携手知名燃热品牌能率&#xff0c;与节目组一起关注民生&#xff0c;走进由一家五口组成的“足不出户的家”&#xff0c;共启老宅改造计划&#xff0c;倾情助力普通家庭拥抱生活与梦想&#…

(Matlab实现)蚂蚁狮子优化算法在电力系统中的应用

目录 1 知识一网打尽 2 蚂蚁狮子优化算法在电力系统经济调度中的应用 3 运行结果 4 Matlab代码实现 1 知识一网打尽 这里总结一位博主的电力系统经济调度目录 蚂蚁狮子优化算法&#xff08;完整Matlab代码实现&#xff09; 多目标蚂蚁狮子优化算法&#xff08;Matlab代码…

拒绝灵感焦虑,藏在UI设计师书签里的宝藏网站!

都在说UI设计“越来越吃香”&#xff0c;导致其他门类的设计师一心想转行。 上次和入行8年的UI大佬聊天&#xff0c;她告诉小摹3条UI设计师必备能力&#xff1a; 审美能力和眼界&#xff1a;一个界面好不好看最后都是UI来定&#xff0c;为了不背锅&#xff0c;UI一定要有国际流…

dolphinscheduler2.0.5性能手动测试

目录&#x1f42c;官方配置文件说明&#x1f42c;测试并发量&#x1f420;线程数量设置100&#x1f420;线程数量设置200&#x1f420;线程数量设置500&#x1f42c;测试结论&#x1f42c;官方配置文件说明 官方说明 master.exec.threads&#xff1a; master工作线程数量,用于…

【2013】408联考数据结构真题整理

2013年 1 题目 解析 原始&#xff1a;升序 升序 变 升序 尾插法 改编&#xff1a;升序 升序 变 降序 头插法 2 题目 答案&#xff1a;C 解析 3 题目 答案&#xff1a;B 解析 二叉排序树&#xff0c;或者是空树&#xff0c;或者是满足以下性质的二叉树&#xff1a; …

基于PHP+MySQL音乐网站的设计与实现

随着时代的发展,音乐已经逐渐成为了人们生活中必不可少的一种调剂品,人们对音乐的追求也越来越强烈,为此我通过PHP和MYSQL开发了本音乐网站 本音乐网站是一个综合性的音乐分享网站,它主要实现了娱乐新闻,上榜歌手,音乐试听,音乐下载,下载排行,音乐库,在线留言等基本的音乐共享功…

Matplotlib绘制折线图、散点图、柱状图、直方图、饼图代码

一、折线图 以折线的上升或下降来表示统计数量的增减变化的统计图 特点&#xff1a;能够显示数据的变化趋势&#xff0c;反映事物的变化情况(变化)函数&#xff1a;plt.plot(x, y) import matplotlib.pyplot as plt import randomfrom pylab import mpl mpl.rcParams["f…

day31 文件上传js验证mimeuser.ini语言特性

前言 #知识点&#xff1a; 1、文件上传-前端验证 2、文件上传-黑白名单 3、文件上传-user.ini妙用 4、文件上传-PHP语言特性 #详细点&#xff1a; 1、检测层面&#xff1a;前端&#xff0c;后端等 2、检测内容&#xff1a;文件头&#xff0c;完整性&#xff0c;二次渲染…

基于MATLABsimulink的《电路原理》课程仿真实验平台开发

目 录 摘 要 I Abstract II 第一章 绪论 1 1.1选题背景及意义 1 1.2设计内容 1 1.3设计思想 2 第二章 MATLAB简介 3 2.1 MATLAB程序设计 3 2.2 Simulink仿真 4 2.2.1 Simulink 启动 4 2.2.2 Simulink 模块库及模块操作 4 2.2.3 仿真参数设置 6 2.3图形用户界面&#xff08;GUI&…

基于STM32的温控风扇

本设计是基于STM32的温控风扇&#xff0c;主要实现以下功能&#xff1a; 温度控制风速&#xff0c;四个挡位&#xff0c;停止、低速、中速、高速 按键可切换模式&#xff0c;可手动切换挡位&#xff0c;四个挡位&#xff0c;停止、低速、中速、高速 按键设置温度值&#xff0c…

网络刷卡器开发,刷新移动物联新生活

在物联网应用需求和身份校验普及的影响下&#xff0c;沐渥自主研发生产了一款基于网络协议传输的读卡设备——网络刷卡器&#xff0c;这是一款体积小巧&#xff0c;方便携带&#xff0c;即插即用&#xff0c;无需安装驱动&#xff0c;采用USB通讯&#xff0c;即刻响应对接客户的…

Linux系统漏洞本地提权

目录 一、实验项目名称 二、实验目的 三、实验内容 四、实验环境 五、实验步骤 六、实验结果 七、实验总结 一、实验项目名称 Linux系统漏洞本地提权及跳板设置实验 二、实验目的 1.msf工具的使用&#xff1b; 2.“脏牛”漏洞CVE-2016-5195漏洞利用方法。 三、实验…