C++实现单链表的构造

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

下面就是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日

相关文章

  • uml14种图记忆口诀

    以下是关于“UML 14种图记忆口诀”的完整攻略: UML是一种用于软件开发的标准建模语言,包括14种不同类型的图。为了更好地记忆这些,可以使用以下口诀: 序图:时间轴,垂直画。 用例图:用户需求,功能列。 类图:属性和方法,关系连。 活动图:流程控制,节点画。 状态图:状态变化,箭头连。 部署图:物理结构,节点画。 组件图:模块划分,节点画。 对象图:实例…

    other 2023年5月7日
    00
  • 微信公众平台开发教程(五)详解自定义菜单

    下面是“微信公众平台开发教程(五)详解自定义菜单”的完整攻略。 简介 自定义菜单是微信公众平台提供的重要功能之一,它可以让公众号在用户关注后,通过菜单方便地实现导航、功能入口、消息等功能。 实现方式 实现自定义菜单需要遵循以下步骤: 登录微信公众平台,进入“开发-基本配置”页面,获取公众号的AppID和AppSecret。 在“开发-开发者工具”页面,下载安…

    other 2023年6月25日
    00
  • Bitget安全下载地址以及基础知识分享

    Bitget安全下载地址以及基础知识分享攻略 1. Bitget安全下载地址 要确保安全下载Bitget,您可以按照以下步骤进行操作: 访问Bitget官方网站:https://www.bitget.com/ 在网站首页,您可以找到一个名为\”下载\”或\”Download\”的选项。点击该选项。 在下载页面,您将看到不同的版本和平台的下载链接。根据您的操作…

    other 2023年8月4日
    00
  • 如何修改自己的电脑子网掩码、网关、IP/DNS地址?

    如何修改电脑的子网掩码、网关、IP/DNS地址 在修改电脑的子网掩码、网关、IP/DNS地址之前,请确保您具有管理员权限。以下是修改这些设置的步骤: 1. 打开网络设置 首先,打开控制面板或系统设置,然后选择“网络和互联网”选项。 2. 进入网络适配器设置 在“网络和互联网”选项中,找到并点击“网络和共享中心”链接。在新窗口中,您将看到当前连接的网络名称,旁…

    other 2023年7月30日
    00
  • java父类和子类初始化顺序的深入理解

    下面我将详细讲解Java父类和子类初始化顺序的深入理解。 父类和子类初始化顺序的基本概念 在Java中,对象的初始化包括两部分:静态初始化和实例初始化。当类被加载时,它的静态成员会被初始化;当类的对象被创建时,会调用构造函数进行实例初始化。父类和子类的初始化顺序如下: 父类的静态成员初始化 子类的静态成员初始化 父类的实例成员初始化 父类的构造函数初始化 子…

    other 2023年6月26日
    00
  • ios中处理四舍五入的问题

    iOS中处理四舍五入的问题 在iOS开发中,我们经常需要对数字进行四舍五入。本攻略将介绍iOS中处理四舍入的问题,并提供两个示例。 使用round()函数进行四五入 在iOS中,我们可以使用round()函数进行四舍五。该函数接受浮点数作为参数,并返回最接近该浮点数的整。以下是使用round()函数进行四舍五入的示例: let number = 3.1415…

    other 2023年5月9日
    00
  • Win10预览版17758怎么手动升级到17763版?

    下面是详细的步骤: 准备工作 在升级之前,请确保做好了以下几个准备工作: 确保你的电脑已经安装了Win10预览版17758。 确保你的电脑连接到了互联网,并且网络连接顺畅。 确保你的电脑没有其他的升级任务在进行中,比如正在下载其他的更新包。 确保你已经备份了重要的数据,以防数据丢失或者数据泄露。 使用Windows Update手动升级 打开开始菜单,点击“…

    other 2023年6月27日
    00
  • swift自定义表格控件(UITableView)

    下面是关于Swift自定义表格控件(UITableView)的完整攻略: 什么是UITableView UITableView 是 iOS 开发中经常用到的一个控件,用于展示有序列表数据。它是一个高度可定制化的控件,能够展示表格详细信息,支持多种样式、多种编辑方式和交互。 UITableView的基础使用 UITableView 在 iOS 开发中是非常常用…

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