C++模拟实现JDK中的ArrayList和LinkedList

C++模拟实现JDK中的ArrayList和LinkedList

介绍

在Java语言中,ArrayList和LinkedList是两种常见的List集合实现方式。ArrayList底层基于动态数组实现,适用于随机访问元素,但插入和删除操作效率较低。LinkedList底层基于双向链表实现,适用于频繁插入和删除操作,但访问元素效率较低。

本篇文章将介绍如何使用C++语言模拟实现ArrayList和LinkedList,实现它们基本的操作。

C++实现ArrayList

数据结构

在C++中,可以使用std::vector代替Java中的ArrayList,std::vector基于动态数组实现,使用前需要包含< vector >头文件。

#include <vector>
#include <iostream>

using namespace std;

int main() {
    vector<int> arrlist;
    arrlist.push_back(1);
    arrlist.push_back(2);
    arrlist.push_back(3);
    for(int i=0; i<arrlist.size(); i++) {
        cout << arrlist[i] << " ";
    }
    cout << endl;
    return 0;
}

运行结果为:1 2 3

基本操作

在C++中,可以使用std::vector实现ArrayList的基本操作,包括插入、删除、获取元素、获取大小等。

vector<int> arrlist;
arrlist.push_back(1); // 插入元素1
arrlist.push_back(2); // 插入元素2
arrlist.push_back(3); // 插入元素3

arrlist.erase(arrlist.begin() + 1); // 删除第二个元素2
cout << arrlist[1] << endl; // 输出第二个元素3

string s = "size: " + to_string(arrlist.size()); // 获取元素个数
cout << s << endl; // 输出size: 2

C++实现LinkedList

数据结构

在C++中,可以使用自定义结构体实现链表,包括链表节点和链表类。

#include <iostream>

/* 链表节点 */
struct Node {
    int val; // 节点值
    Node* prev; // 前驱指针
    Node* next; // 后继指针
    Node(int val) : val(val), prev(nullptr), next(nullptr) {} // 构造函数
};

/* 链表类 */
class LinkedList {
public:
    LinkedList() : head(nullptr), tail(nullptr) {} // 构造函数

    void addFirst(int val); // 在头部添加节点
    void addLast(int val); // 在尾部添加节点
    void insert(int val, int index); // 在指定位置插入节点
    void removeFirst(); // 删除头部节点
    void removeLast(); // 删除尾部节点
    void remove(int index); // 删除指定位置的节点
    int get(int index); // 获取指定位置的节点值
    int size(); // 获取节点总数

private:
    Node* head; // 头节点指针
    Node* tail; // 尾节点指针
};

int main() {
    LinkedList linkedlist;
    linkedlist.addFirst(1);
    linkedlist.addLast(3);
    linkedlist.insert(2, 1);
    linkedlist.remove(1);
    std::cout << linkedlist.get(1) << std::endl;
    std::cout << linkedlist.size() << std::endl;
    return 0;
}

基本操作

在C++中,根据链表节点的前驱指针和后继指针,可以实现链表的基本操作,包括在头部、尾部和指定位置插入节点,删除头部、尾部和指定位置的节点,获取指定位置的节点值和获取总节点数。

void LinkedList::addFirst(int val) {
    Node* node = new Node(val);
    if(head == nullptr) {
        head = node;
        tail = node;
    } else {
        node->next = head;
        head->prev = node;
        head = node;
    }
}

void LinkedList::addLast(int val) {
    Node* node = new Node(val);
    if(tail == nullptr) {
        head = node;
        tail = node;
    } else {
        node->prev = tail;
        tail->next = node;
        tail = node;
    }
}

void LinkedList::insert(int val, int index) {
    Node* node = new Node(val);
    Node* p = head;
    for(int i=0; i<index-1 && p!=nullptr; i++) {
        p = p->next;
    }
    if(p == nullptr) { // 插入位置越界
        std::cout << "Out of range!" << std::endl;
        return;
    }
    if(p == head) {
        addFirst(val);
        return;
    }
    node->prev = p->prev;
    node->next = p;
    p->prev->next = node;
    p->prev = node;
}

void LinkedList::removeFirst() {
    if(head == nullptr) {
        return;
    }
    Node* p = head;
    head = head->next;
    if(head != nullptr) {
        head->prev = nullptr;
    } else {
        tail = nullptr;
    }
    delete p;
}

void LinkedList::removeLast() {
    if(tail == nullptr) {
        return;
    }
    Node* p = tail;
    tail = tail->prev;
    if(tail != nullptr) {
        tail->next = nullptr;
    } else {
        head = nullptr;
    }
    delete p;
}

void LinkedList::remove(int index) {
    Node* p = head;
    for(int i=0; i<index && p!=nullptr; i++) {
        p = p->next;
    }
    if(p == nullptr) { // 删除位置越界
        std::cout << "Out of range!" << std::endl;
        return;
    }
    if(p == head) {
        removeFirst();
        return;
    }
    if(p == tail) {
        removeLast();
        return;
    }
    p->prev->next = p->next;
    p->next->prev = p->prev;
    delete p;
}

int LinkedList::get(int index) {
    Node* p = head;
    for(int i=0; i<index && p!=nullptr; i++) {
        p = p->next;
    }
    if(p == nullptr) { // 获取位置越界
        std::cout << "Out of range!" << std::endl;
        return -1;
    }
    return p->val;
}

int LinkedList::size() {
    Node* p = head;
    int count = 0;
    while(p != nullptr) {
        count++;
        p = p->next;
    }
    return count;
}

总结

本篇文章介绍了如何使用C++语言模拟实现ArrayList和LinkedList,基于std::vector实现了ArrayList的基本操作,基于自定义结构体实现了LinkedList的基本操作,包括插入、删除、获取元素和获取大小。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C++模拟实现JDK中的ArrayList和LinkedList - Python技术站

(0)
上一篇 2023年3月28日
下一篇 2023年3月28日

相关文章

  • Android中自定义进度条详解

    如果你想在Android中实现自定义进度条的效果,可以按照以下步骤进行操作: 步骤1:准备自定义进度条的资源文件 为了实现自定义进度条,你需要先准备自定义进度条的资源文件,例如进度条的背景色、前景色等等。 步骤2:在布局文件中添加自定义进度条 在布局文件中添加ProgressBar控件,然后设置它的样式为你自定义的进度条样式。如下所示: <Progre…

    other 2023年6月25日
    00
  • 利用ceye中的dns来获取数据

    利用ceye中的dns来获取数据 什么是ceye? ceye是一款兼具网络安全测试与被动安全监控的在线工具,提供了DNS解析、HTTP响应、SMTP邮件、TCP/UDP端口等多种方式进行数据采集,可以使用它搭建自己的DNS服务端来监听网站流量、收集敏感信息等。 ceye的使用方法 注册与登录 首先需要注册一个ceye账号,注册成功之后进入官网,右上角会有”登…

    其他 2023年3月28日
    00
  • isp算法:深入聊聊lensshading

    ISP算法:深入聊聊Lens Shading 在数字图像处理中,ISP(Image Signal Processing,图像信号处理)是一个重要的概念。它涉及到诸如降噪、增强对比度、颜色校正等过程,可以让拍摄的图像更加鲜明、逼真。 而Lens Shading(镜头阴影)则是ISP中的一个非常重要的步骤。本文将深入介绍Lens Shading算法的原理和实际应…

    其他 2023年3月28日
    00
  • C++ 类的继承与派生实例详解

    C++ 类的继承与派生实例详解 一、什么是继承与派生 在面向对象的编程中,继承与派生是两个很重要的概念。通过继承,我们可以在已有的类的基础上,创建一个子类,并且让子类保留父类的功能和特征,然后在子类中再添加自己的功能和特征。这就是继承的意义所在。 派生是继承的一种实现方式。通过派生,子类可以从父类中继承所有的属性和方法,包括公有(public)、私有(pri…

    other 2023年6月26日
    00
  • 你一定不知道的Java Unsafe用法详解

    你一定不知道的Java Unsafe用法详解 1. 什么是Java Unsafe Java Unsafe是Java核心库中的一个类,它提供了一些底层操作的方法,可以绕过Java语言的限制,直接操作内存和对象。它通常被用于实现一些底层的功能,比如CAS操作、直接内存访问等。 2. 使用Java Unsafe的注意事项 在使用Java Unsafe时,需要注意以…

    other 2023年10月16日
    00
  • python单向循环链表实例详解

    Python 单向循环链表实例详解 单向循环链表是一种常用的链表结构,它和单向链表的最大区别在于其尾节点指向头节点。这种循环的结构使得我们可以轻松地在链表中进行循环操作。下面我们来详细讲解如何使用 Python 实现单向循环链表。 实现思路 实现节点类:首先我们需要定义一个节点类,用来储存我们链表中的每个节点,并且需要定义一些方法来访问和更新节点的值、指针等…

    other 2023年6月27日
    00
  • java中file.separator作用详解

    Java中file.separator作用详解 在Java中,file.separator是一个系统属性,用于表示文件路径中的分隔符。file.separator的值在不同的操作系统中是不同的。例如在Windows中,file.separator的值是\,而在Linux中,file.separator的值是/。以下是Java中file.separator的详…

    other 2023年5月9日
    00
  • Spring 整合多个配置文件的方法

    Spring框架支持将多个配置文件整合到一起,以便于管理和维护。下面是 Spring 整合多个配置文件的方法的完整攻略。 一、使用 import 标签方式整合多个配置文件 使用 import 标签将多个配置文件整合到一起的方式是比较常见的,它可以通过 Spring 配置文件的方式引用其他配置文件,从而实现整合。 示例1: 假设有一个名为 applicatio…

    other 2023年6月25日
    00
合作推广
合作推广
分享本页
返回顶部