C++链表常用的函数编写(增查删改)内附完整程序

简介: C++链表常用的函数编写(增查删改)内附完整程序

一、链表主体

// 链表结构体
typedef struct node
{
    int date;
    struct node *next; // 还未定义别名只能使用struct node定义next指针
} Node;
/***
typedef struct 结构名
{
  类型 变量名;
  类型 变量名;
} 结构别名1, 结构别名2; 
这里如果没有typedef定义别名在定义结构体的时候则需要添加 struct node n1;
 ***/

链表由结构体构成,结构体包含节点数据以及指向下一个节点的指针

二、创建链表

// 创建链表
Node *NodeInit(int n)
{
    // 创建链表
    Node *head = new Node; // 头节点 这里也可以使用malloc方式
    // Node *head = (Node *)malloc(sizeof(Node));
    // 头节点一般不存储数据
    Node *per = head;
    for (int i = 0; i < n; i++)
    {
        // 申请新的空间存储相应数据然后放入per指针
        Node *p = new Node;   //申请新的空间
        p->date = i * 10 + 1; //给新的空间写入数据
        p->next = NULL;       //新的空间指向空
        per->next = p;        //原来的节点指向这个新的空间
        per = p;              //获取新空间的数据
    }
    return head;
}
Node *MainHead = NodeInit(5);

三、链表的应用

1.打印链表

// 打印链表数据
void NodeDisplay(Node *head)
{
    Node *p = head->next;
    while (p != NULL)
    {
        // 遍历节点
        std::cout << p->date << " -> ";
        p = p->next;
    }
    std::cout << "NULL" << std::endl;
}

2.求链表长度

// 链表长度
int NodeLenth(Node *head)
{
    Node *p = head->next;
    int count = 0;
    while (p != NULL)
    {
        // 遍历节点
        count++;
        p = p->next;
    }
    return count;
}

3.插入数据(按照指定位置)

// 指定位置插入链表数据 (头节点、插入位置、插入数据)
void NodeInsert(Node *head, int index, int date)
{
    if (index < 0 || index > NodeLenth(head))
        throw "index error"; //如果插入位置超出链表长度抛出异常
    Node *per = head;
    for (int i = 0; i < index; i++)
    {
        // 循环next到index位置
        per = per->next;
    }
    Node *NewNode = new Node;
    NewNode->date = date;
    NewNode->next = per->next;
    per->next = NewNode;
}

4.插入数据(头插)

// 头插
void NodePushFront(Node *head, int date)
{
    Node *per = head;
    Node *NewNode = new Node;
    NewNode->date = date;
    NewNode->next = per->next;
    per->next = NewNode;
}

5.插入数据(尾插)

// 尾插
void NodePushBack(Node *head, int date)
{
    Node *per = head;
    for (int i = 0; i < NodeLenth(head); i++)
    {
        // 让节点指向最后一个节点
        per = per->next;
    }
    Node *NewNode = new Node;
    NewNode->date = date;
    NewNode->next = NULL;
    per->next = NewNode;
}

6.查找元素是否存在

// 查找元素:如果元素存在返回true,不存在返回false
bool NodeFind(Node *head, int date)
{
    Node *p = head->next;
    for (int i = 0; i < NodeLenth(head); i++)
    {
        if (p->date == date)
            return true;
        else
            p = p->next;
    }
    return false;
}

7.删除指定位置数据

// 删除指定位置数据
void NodeDeleteDate(Node *head, int index)
{
    if (index < 0 || index > NodeLenth(head))
        throw "index error"; //如果删除位置超出链表长度抛出异常
    Node *per = head;
    for (int i = 0; i < index; i++)
    {
        per = per->next;
    }
    Node *p = per->next;
    per->next = per->next->next;
    delete p;
}

8.删除最后一个节点

// 删除最后一个节点
void NodePopback(Node *head)
{
    Node *per = head;
    for (int i = 0; i < NodeLenth(head) - 1; i++)
    {
        per = per->next;
    }
    Node *p = per->next;
    per->next = NULL;
    delete p;
}

9.删除第一个节点

// 删除第一个节点
void NodePopFront(Node *head)
{
    Node *per = head;
    Node *p = per->next;
    per->next = per->next->next;
    delete p;
}

10.修改节点数据

// 修改元素
void NodeChange(Node *head, int index, int date)
{
    if (index < 0 || index > NodeLenth(head))
        throw "index error"; //如果修改位置超出链表长度抛出异常
    Node *per = head;
    for (int i = 0; i < index; i++)
    {
        // 让节点指向index位置
        per = per->next;
    }
    per->date = date;
}

11.清空链表节点

// 清空链表
void NodeClear(Node *head)
{
    while (head->next != NULL)
    {
        Node *p = head->next;
        head->next = head->next->next;
        delete p;
    }
}

四、完整程序

/*
 * @Author: Stylle
 * @Date: 2020-08-25 18:08:28
 * @LastEditors: Stylle
 * @LastEditTime: 2020-08-25 21:43:50
 * @FilePath: \learing-master\链表.cpp
 */
#include <iostream>
// 链表结构体
typedef struct node
{
    int date;
    struct node *next; // 还未定义别名只能使用struct node定义next指针
} Node;
/***
typedef struct 结构名
{
  类型 变量名;
  类型 变量名;
} 结构别名1, 结构别名2; 
这里如果没有typedef定义别名在定义结构体的时候则需要添加 struct node n1;
 ***/
// 创建链表
Node *NodeInit(int n)
{
    // 创建链表
    Node *head = new Node; // 头节点 这里也可以使用malloc方式
    // Node *head = (Node *)malloc(sizeof(Node));
    // 头节点一般不存储数据
    Node *per = head;
    for (int i = 0; i < n; i++)
    {
        // 申请新的空间存储相应数据然后放入per指针
        Node *p = new Node;   //申请新的空间
        p->date = i * 10 + 1; //给新的空间写入数据
        p->next = NULL;       //新的空间指向空
        per->next = p;        //原来的节点指向这个新的空间
        per = p;              //获取新空间的数据
    }
    return head;
}
// 链表长度
int NodeLenth(Node *head)
{
    Node *p = head->next;
    int count = 0;
    while (p != NULL)
    {
        // 遍历节点
        count++;
        p = p->next;
    }
    return count;
}
// 指定位置插入链表数据 (头节点、插入位置、插入数据)
void NodeInsert(Node *head, int index, int date)
{
    if (index < 0 || index > NodeLenth(head))
        throw "index error"; //如果插入位置超出链表长度抛出异常
    Node *per = head;
    for (int i = 0; i < index; i++)
    {
        // 循环next到index位置
        per = per->next;
    }
    Node *NewNode = new Node;
    NewNode->date = date;
    NewNode->next = per->next;
    per->next = NewNode;
}
// 头插
void NodePushFront(Node *head, int date)
{
    Node *per = head;
    Node *NewNode = new Node;
    NewNode->date = date;
    NewNode->next = per->next;
    per->next = NewNode;
}
// 尾插
void NodePushBack(Node *head, int date)
{
    Node *per = head;
    for (int i = 0; i < NodeLenth(head); i++)
    {
        // 让节点指向最后一个节点
        per = per->next;
    }
    Node *NewNode = new Node;
    NewNode->date = date;
    NewNode->next = NULL;
    per->next = NewNode;
}
// 打印链表数据
void NodeDisplay(Node *head)
{
    Node *p = head->next;
    while (p != NULL)
    {
        // 遍历节点
        std::cout << p->date << " -> ";
        p = p->next;
    }
    std::cout << "NULL" << std::endl;
}
// 查找元素:如果元素存在返回true,不存在返回false
bool NodeFind(Node *head, int date)
{
    Node *p = head->next;
    for (int i = 0; i < NodeLenth(head); i++)
    {
        if (p->date == date)
            return true;
        else
            p = p->next;
    }
    return false;
}
// 清空链表
void NodeClear(Node *head)
{
    while (head->next != NULL)
    {
        Node *p = head->next;
        head->next = head->next->next;
        delete p;
    }
}
// 删除指定位置数据
void NodeDeleteDate(Node *head, int index)
{
    if (index < 0 || index > NodeLenth(head))
        throw "index error"; //如果删除位置超出链表长度抛出异常
    Node *per = head;
    for (int i = 0; i < index; i++)
    {
        per = per->next;
    }
    Node *p = per->next;
    per->next = per->next->next;
    delete p;
}
// 删除最后一个节点
void NodePopback(Node *head)
{
    Node *per = head;
    for (int i = 0; i < NodeLenth(head) - 1; i++)
    {
        per = per->next;
    }
    Node *p = per->next;
    per->next = NULL;
    delete p;
}
// 删除第一个节点
void NodePopFront(Node *head)
{
    Node *per = head;
    Node *p = per->next;
    per->next = per->next->next;
    delete p;
}
// 修改元素
void NodeChange(Node *head, int index, int date)
{
    if (index < 0 || index > NodeLenth(head))
        throw "index error"; //如果修改位置超出链表长度抛出异常
    Node *per = head;
    for (int i = 0; i < index; i++)
    {
        // 让节点指向index位置
        per = per->next;
    }
    per->date = date;
}
int main(int argc, char **argv)
{
    Node *MainHead = NodeInit(5);
    NodeDisplay(MainHead);
    std::cout << "链表长度:" << NodeLenth(MainHead) << std::endl;
    // 按位置插入数据
    NodeInsert(MainHead, 2, 12);
    NodeDisplay(MainHead);
    std::cout << "链表长度:" << NodeLenth(MainHead) << std::endl;
    // 尾插
    NodePushBack(MainHead, 42);
    NodeDisplay(MainHead);
    std::cout << "链表长度:" << NodeLenth(MainHead) << std::endl;
    // 头插
    NodePushFront(MainHead, 0);
    NodeDisplay(MainHead);
    std::cout << "链表长度:" << NodeLenth(MainHead) << std::endl;
    // 修改数据
    NodeChange(MainHead, 1, 99);
    NodeDisplay(MainHead);
    // 查找数据
    if (NodeFind(MainHead, 12))
    {
        std::cout << "已查询到元素12" << std::endl;
    }
    // 删除指定节点
    NodeDeleteDate(MainHead, 7);
    NodeDisplay(MainHead);
    std::cout << "链表长度:" << NodeLenth(MainHead) << std::endl;
    // 删除最后一个节点
    NodePopback(MainHead);
    NodeDisplay(MainHead);
    std::cout << "链表长度:" << NodeLenth(MainHead) << std::endl;
    // 删除第一个节点
    NodePopFront(MainHead);
    NodeDisplay(MainHead);
    std::cout << "链表长度:" << NodeLenth(MainHead) << std::endl;
    // 清空节点
    NodeClear(MainHead);
    NodeDisplay(MainHead);
    std::cout << "链表长度:" << NodeLenth(MainHead) << std::endl;
    return 0;
}

五、运行结果

六、总结

程序的说明在注释里已经说明的比较清楚了,最后说一下链表的一般使用场景,和其他的几种链表(本文编写的链表为单链表)

1、链表包含两个部分:数据域、节点指针

2、链表一般使用在需要快速插入和删除而不需要随机访问的情况下使用

3、链表和数组的区别:链表数据随机地址存储,访问需要需要从节点遍历,而数组存储在连续的内存空间,可以使用下标访问(随机访问)

4、单向链表:

5、双向链表(不常使用):

和单向链表相比多一个指针域,一个指向前面的数据节点,一个指向后面的数据节点

6、循环链表:

首尾节点相互链接,特点是”无头无尾“,比较利于数据存储缓存。

虽然本文只编写了单向链表,但是我相信看懂了上面的代码,写出双向链表和循环链表并不是多难。


相关文章
|
18天前
|
存储 算法 搜索推荐
【C++】类的默认成员函数
【C++】类的默认成员函数
|
2天前
|
C++
C++ 根据程序运行的时间和cpu频率来计算在另外的cpu上运行所花的时间
C++ 根据程序运行的时间和cpu频率来计算在另外的cpu上运行所花的时间
10 0
|
3天前
|
编译器 C++ 容器
【C++】String常见函数用法
【C++】String常见函数用法
8 1
|
11天前
|
C++
c++常见函数及技巧
C++编程中的一些常见函数和技巧,包括生成随机数的方法、制表技巧、获取数字的个位、十位、百位数的方法、字符串命名技巧、避免代码修改错误的技巧、暂停和等待用户信号的技巧、清屏命令、以及避免编译错误和逻辑错误的建议。
15 6
|
11天前
|
存储 C++
c++学习笔记05 函数
C++函数使用的详细学习笔记05,包括函数的基本格式、值传递、函数声明、以及如何在不同文件中组织函数代码的示例和技巧。
18 0
c++学习笔记05 函数
|
2天前
|
PHP C++ Python
右手坐标系,空间点绕轴旋转公式&程序(Python和C++程序)
右手坐标系,空间点绕轴旋转公式&程序(Python和C++程序)
6 0
|
10天前
|
存储 C++
【C/C++学习笔记】string 类型的输入操作符和 getline 函数分别如何处理空白字符
【C/C++学习笔记】string 类型的输入操作符和 getline 函数分别如何处理空白字符
22 0
|
11天前
|
C++
c++学习笔记03 程序流程结构
C++学习笔记,主要介绍了程序流程结构,包括顺序结构、选择结构和循环结构。选择结构中详细解释了if语句、三目运算符和switch语句的用法和注意事项。循环结构部分则涵盖了while循环、do-while循环和for循环的语法和使用技巧。此外,还介绍了跳转语句,包括break、continue和goto语句的用途和用法。
20 0
|
16天前
|
Dart 编译器 API
Dart ffi 使用问题之在C++线程中无法直接调用Dart函数的问题如何解决
Dart ffi 使用问题之在C++线程中无法直接调用Dart函数的问题如何解决
|
22天前
|
JavaScript C++
【C++ visual studio】解决VS报错:error C2447: “{”: 缺少函数标题(是否是老式的形式表?)【亲测有效,无效捶我】
【C++ visual studio】解决VS报错:error C2447: “{”: 缺少函数标题(是否是老式的形式表?)【亲测有效,无效捶我】

热门文章

最新文章

下一篇
云函数