C++实现单链表的构造

yizhihongxing

首先,我们需要了解单链表的基本概念。单链表是一种数据结构,它由一系列节点组成,每个节点包含两个部分:数据域和指针域。数据域用于存储节点的数据,指针域则指向下一个节点的地址。单链表的最后一个节点的指针域指向空地址,表示链表的结束。

下面就是C++实现单链表的构造的完整攻略:

  1. 定义节点结构体

首先我们需要定义一个节点的结构体,它包含两个成员,分别是数据域和指针域。具体代码如下所示:

struct Node {
    int data;
    Node* next;
};

其中,int data代表节点的数据,Node* next代表指向下一个节点的指针。

  1. 实现链表的插入操作

链表的插入操作是指向链表中添加一个节点。链表的插入操作分为两种情况,分别是在链表的头部插入节点和在链表的尾部插入节点。具体代码如下所示:

在链表头部插入节点:

void insertNodeAtBeginning(Node* &head, int data) {
    Node* newNode = new Node;
    newNode->data = data;
    newNode->next = head;
    head = newNode;
}

在链表尾部插入节点:

void insertNodeAtEnd(Node* &head, int data) {
    Node* newNode = new Node;
    newNode->data = data;
    newNode->next = nullptr;
    if (head == nullptr) {
        head = newNode;
    } else {
        Node* curr = head;
        while (curr->next != nullptr) {
            curr = curr->next;
        }
        curr->next = newNode;
    }
}

在这里,Node* &head代表链表的头指针。对于在链表头部插入节点的函数void insertNodeAtBeginning(Node* &head, int data)来说,我们需要先申请一个新的节点newNode,将新节点的数据域赋值为要插入的数据,将新节点的指针域指向当前的头结点,并将头指针指向新节点。

对于在链表尾部插入节点的函数void insertNodeAtEnd(Node* &head, int data),我们首先也是需要申请一个新节点newNode,将新节点的数据域赋值为要插入的数据,将新节点的指针域指向空地址,接下来,我们需要判断链表是否为空,如果为空,直接将头指针指向新节点。如果链表不为空,我们需要遍历整个链表,找到最后一个节点,将该节点的指针域指向新节点。

  1. 实现链表的删除操作

链表的删除操作是指从链表中删除一个节点。对于链表的删除操作,我们需要分情况讨论。分为删除头节点、删除尾节点和删除中间节点。具体代码如下所示:

删除头节点:

void deleteNodeAtBeginning(Node* &head) {
    if (head == nullptr) {
        cout << "链表为空,无法进行删除操作" << endl;
        return;
    }
    Node* temp = head;
    head = head->next;
    delete temp;
}

删除尾节点:

void deleteNodeAtEnd(Node* &head) {
    if (head == nullptr) {
        cout << "链表为空,无法进行删除操作" << endl;
        return;
    }
    if (head->next == nullptr) {
        Node* temp = head;
        head = nullptr;
        delete temp;
        return;
    }
    Node* prev = nullptr;
    Node* curr = head;
    while (curr->next != nullptr) {
        prev = curr;
        curr = curr->next;
    }
    prev->next = nullptr;
    delete curr;
}

删除中间节点:

void deleteNode(Node* &head, int data) {
    if (head == nullptr) {
        cout << "链表为空,无法进行删除操作" << endl;
        return;
    }
    Node* prev = nullptr;
    Node* curr = head;
    while (curr != nullptr && curr->data != data) {
        prev = curr;
        curr = curr->next;
    }
    if (curr == nullptr) {
        cout << "需要删除的节点不存在" << endl;
        return;
    }
    if (prev == nullptr) {
        head = curr->next;
    } else {
        prev->next = curr->next;
    }
    delete curr;
}

在这里,对于删除头节点的函数void deleteNodeAtBeginning(Node* &head)来说,我们首先需要判断链表是否为空,如果为空,打印错误信息并直接返回,如果链表不为空,则将头指针指向头节点的下一个节点,并释放头节点所占用的内存。

对于删除尾节点的函数void deleteNodeAtEnd(Node* &head)来说,我们同样需要判断链表是否为空,如果为空则打印错误信息并直接返回。如果链表的长度为1,则将头指针置为空,直接释放头节点所占用的内存。否则,我们需要遍历链表,找到倒数第二个节点,将倒数第二个节点的指针域指向空地址,并释放最后一个节点所占用的内存。

对于删除中间节点的函数void deleteNode(Node* &head, int data)来说,我们需要先遍历链表,找到要删除的节点的前一个节点。如果要删除的节点不存在,则打印错误信息并直接返回。如果要删除的节点是头节点,则需要将头指针指向头节点的下一个节点。如果要删除的节点不是头节点,则需要将要删除的节点的前一个节点的指针域指向要删除的节点的下一个节点,并释放要删除的节点所占用的内存。

  1. 完整代码示例如下所示:
#include <iostream>

using namespace std;

struct Node {
    int data;
    Node* next;
};

void insertNodeAtBeginning(Node* &head, int data) {
    Node* newNode = new Node;
    newNode->data = data;
    newNode->next = head;
    head = newNode;
}

void insertNodeAtEnd(Node* &head, int data) {
    Node* newNode = new Node;
    newNode->data = data;
    newNode->next = nullptr;
    if (head == nullptr) {
        head = newNode;
    } else {
        Node* curr = head;
        while (curr->next != nullptr) {
            curr = curr->next;
        }
        curr->next = newNode;
    }
}

void deleteNodeAtBeginning(Node* &head) {
    if (head == nullptr) {
        cout << "链表为空,无法进行删除操作" << endl;
        return;
    }
    Node* temp = head;
    head = head->next;
    delete temp;
}

void deleteNodeAtEnd(Node* &head) {
    if (head == nullptr) {
        cout << "链表为空,无法进行删除操作" << endl;
        return;
    }
    if (head->next == nullptr) {
        Node* temp = head;
        head = nullptr;
        delete temp;
        return;
    }
    Node* prev = nullptr;
    Node* curr = head;
    while (curr->next != nullptr) {
        prev = curr;
        curr = curr->next;
    }
    prev->next = nullptr;
    delete curr;
}

void deleteNode(Node* &head, int data) {
    if (head == nullptr) {
        cout << "链表为空,无法进行删除操作" << endl;
        return;
    }
    Node* prev = nullptr;
    Node* curr = head;
    while (curr != nullptr && curr->data != data) {
        prev = curr;
        curr = curr->next;
    }
    if (curr == nullptr) {
        cout << "需要删除的节点不存在" << endl;
        return;
    }
    if (prev == nullptr) {
        head = curr->next;
    } else {
        prev->next = curr->next;
    }
    delete curr;
}

int main() {
    Node* head = nullptr;
    insertNodeAtBeginning(head, 3);
    insertNodeAtBeginning(head, 2);
    insertNodeAtBeginning(head, 1);
    insertNodeAtEnd(head, 4);
    deleteNode(head, 3);
    deleteNodeAtBeginning(head);
    deleteNodeAtEnd(head);
    Node* curr = head;
    while (curr != nullptr) {
        cout << curr->data << " ";
        curr = curr->next;
    }
    cout << endl;
    return 0;
}

上面的代码中,我们首先定义了一个头指针Node* head,表示链表的头节点,随后我们向头部插入节点1、2、3,向尾部插入节点4,接下来我们删除了节点3,删除了头节点,并删除了尾节点,最后我们通过遍历链表的方式将链表中的所有节点输出。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C++实现单链表的构造 - Python技术站

(0)
上一篇 2023年6月27日
下一篇 2023年6月27日

相关文章

  • vue-cli3 配置开发与测试环境详解

    下面我将为您详细讲解 “vue-cli3 配置开发与测试环境详解” 的完整攻略。 一、什么是 Vue CLI3 Vue CLI3 是 Vue.js 官方提供的脚手架工具,它提供了一整套预定义的项目脚手架,能够帮助开发者快速搭建 Vue.js 项目的基础框架。 二、Vue CLI3 的使用 Vue CLI3 通过命令行交互的方式,提供了一系列的命令用于创建、启…

    other 2023年6月27日
    00
  • Lua中的递归函数写法实例

    下面是由浅入深的关于Lua中递归函数的写法规范和实例说明。 1. 递归函数的定义 递归函数是指在函数的执行过程中,调用自身的行为。 递归函数必须有一个递归终止条件,否则将会发生无限递归,使程序崩溃。 2. 递归函数的写法 下面是递归函数的标准写法。 function recursion(num) — 1.递归终止条件 if (num == 1) then …

    other 2023年6月27日
    00
  • Docker容器启动时初始化Mysql数据库的方法

    下面我为您详细讲解Docker容器启动时初始化Mysql数据库的方法。 方法一:使用SQL脚本初始化 1.创建.SQL初始化文件 我们可以在启动容器前,先自己制作好一个SQL初始化脚本文件,然后将其放置在Docker镜像内部。假设我们将SQL脚本命名为”mydb.sql”。 2.在Dockerfile中引入SQL脚本文件 在Dockerfile中使用ADD或…

    other 2023年6月20日
    00
  • 利用QDir实现删除选定文件目录下的空文件夹

    利用QDir实现删除选定文件目录下的空文件夹的攻略如下: 通过QDir::entryList()函数获取被选中文件夹的所有子文件夹和子文件的信息,并将它们放入一个QStringList中; 遍历上一步得到的QStringList,使用QDir::isEmpty()函数判断每个子文件夹是否为空,若为空,则递归删除该文件夹; 在递归删除时,应当从当前文件夹开始,…

    other 2023年6月26日
    00
  • OpenCV与Qt的环境搭建及Demo

    OpenCV与Qt的环境搭建及Demo 在本文中,我们将学习如何在Windows操作系统下,搭建OpenCV与Qt的环境,并了解如何用Qt编写并运行一个基础的OpenCV应用。 环境搭建 安装OpenCV 在Windows系统下,安装OpenCV的最简单方法是通过 OpenCV官网的安装程序。下载对应版本的exe文件,按照安装向导逐步完成安装。安装完成后,将…

    其他 2023年3月28日
    00
  • Android 画一个太极图实例代码

    下面我将为你详细讲解如何在Android上画一个太极图的完整攻略,包括示例说明。 1. 准备工作 在开始画太极图之前,先确保你已经在Android Studio中创建了一个项目,并且可以正常运行。 接下来,在项目的res/drawable文件夹下创建一个名为taichi.xml的文件,用于定义太极图的样式。 2. 定义太极图样式 在taichi.xml中加入…

    other 2023年6月20日
    00
  • 使用淘宝IP库获取用户ip地理位置

    使用淘宝IP库获取用户IP地理位置攻略 淘宝IP库是一个常用的工具,可以通过用户的IP地址获取其地理位置信息。下面是使用淘宝IP库获取用户IP地理位置的完整攻略。 步骤一:获取用户IP地址 首先,你需要获取用户的IP地址。在Web开发中,可以通过HTTP请求的头部信息中的X-Forwarded-For字段或者REMOTE_ADDR字段来获取用户的IP地址。具…

    other 2023年7月30日
    00
  • Vue3常用的通讯方式总结与实例代码

    Vue3常用的通讯方式总结与实例代码攻略 Vue3是一个流行的JavaScript框架,提供了多种通讯方式来实现组件之间的数据传递和交互。本攻略将详细介绍Vue3中常用的通讯方式,并提供两个示例说明。 Props Props是Vue3中最常用的通讯方式之一。通过在父组件中定义props属性,并将其传递给子组件,可以实现父子组件之间的数据传递。以下是一个示例:…

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