首页 > 其他分享 >链表--单链表

链表--单链表

时间:2024-06-09 12:34:05浏览次数:20  
标签:Node node 结点 单链 -- next 链表 节点

引言:

链表是一种常用的数据结构,在C语言中提供了一种灵活且高效的数据管理方式,它适用于那些需要频繁插入和删除操作的场景。链表的每个节点包含数据和指向下一个节点的指针,这种结构使得链表能够有效地利用内存,并且提供快速的插入和删除能力。然而,由于是动态分配的,访问链表中的元素通常比访问数组中的元素慢,因为必须从头节点开始按顺序访问。链表的这种特性使其成为许多复杂数据结构和算法的基础。 

一.链表的概念和结构

链表若干个结点组成。每个结点都有两部分组成:数据域和指针域。数据域存储结点的数据,而指针域则指向下一个结点。

struct node    
{
    int value;   //数据域:存放链表数据
    struct node* next;  //指针域:存放指向下一个结点的地址
                        //在链表遍历的过程中,我们根据前一个结点的指针域中的那个地址
                        //找到下一个结点,就这样一个接一个往下遍历,
                        //进行增删改查等一系列基础操作。
};

二.链表的创建和初始化

通过定义一个结构体来表示链表的结点,在结构体中含有指向结构体的指针,通过指针变量将结点链接起来。

#include <stdio.h>
#include <stdlib.h>
//单链表
struct node    
{
    int value;   //数据域:存放链表数据
    struct node* next;  //指针域:存放指向下一个结点的地址
};
int main()
{
    struct node* head, * list, * tmp;
            //头结点   头指针   结点指针
    return 0;
}

开始时list指向头结点head,struct node*tmp通过malloc函数不断地创建结点,list->next指向tmp(下一个结点),同时也需要把tmp的地址赋给list,然后不断重复以上操作一个单链表就形成了。

1.带头结点的单链表中,头指针list指向头节点,头结点的值域不含任何信息,从
头结点的后继节点开始存储数据信息(头指针list始终不等于NULL,list->next
等于NULL的时候,链表为空)
2.不带头结点的单链表的头指针list直接指向开始结点(当list等于NULL的时候,
链表为空)
3.两者最明显的区别为,具有头结点的单链表头结点仅存储一些描述链表属性的信息,而不带头节点的单链表的所有结点都存储信息。
结点是内存中一块动态开辟的存储空间,只有一个地址来表示它的存在。因此,
在分配链表结点空间的时候,同时定义一个指针来存储这片空间的地址,即指针指
向节点。(常用指针的名称来作为结点的名称)

 在链表的创建过程中需要使用malloc函数.它是C语言中的一个动态内存分配函数.用于在堆上分配指定大小的内存块。

在上述链表创建过程中使用malloc函数时需要注意malloc函数是否在内存中开辟出了内存块

int main()
{
    int data[10] = { 1,2,3,4,5,6,7,8,9,10 };

    //创建头结点
    struct node* head = (struct node*)malloc(sizeof(struct node));
    //检查malloc是否成功分配内存
    if (head == NULL)
    {
        printf("Memory allocation failed\n");
        exit(1);
    }
    head->next = NULL;
    //头指针的创建
    struct node* list ;
    list = head;
    
    //创建单链表其他节点
    int i=0;
    struct node* tmp;
    while (i < 10)
    {
        tmp = (struct node*)malloc(sizeof(struct node));
        //检查malloc是否成功分配内存
        if (tmp == NULL)
        {
            printf("Memory allocation failed\n");
            exit(1);
        }
        else
        {
            //对链表结点的数据域赋值
            tmp->value = data[i];

            tmp->next = NULL;
            list->next = tmp;
            list = tmp;
        }
        i++;
    }
    struct node* p;
    p = head;
    while (p->next)
    {
        printf("%d\n", p->next->value);
        p = p->next;
    }
}

在链表创建和初始化完成后,我们需要去验证一下自己的学习和实践成果。那么我们就可以去打印一下链表数据域中初始化存入的数值,如果一致,恭喜我们今天又掌握了"汪洋大海中的一滴水"

 显然,我们刚才的创建和初始化是成功的,那么接下来我们就需要去探索一下单链表的功能和作用了。

三.单链表的功能和作用

1.删除结点

单链表的节点删除可以通过以下步骤实现:

遍历链表,找到要删除的节点的前一个节点。
将前一个节点的指针指向要删除节点的下一个节点。
释放要删除节点的内存。

#include <stdio.h>
#include <stdlib.h>

typedef struct Node {
    int val;
    struct Node* next;
} Node;

Node* delete_node(Node* head, int val) {
    if (head == NULL) {
        return NULL;
    }

    if (head->val == val) {
        Node* new_head = head->next;
        free(head);
        return new_head;
    }

    Node* prev = head;
    Node* cur = head->next;
    while (cur != NULL) {
        if (cur->val == val) {
            prev->next = cur->next;
            free(cur);
            break;
        }
        prev = cur;
        cur = cur->next;
    }

    return head;
}

示例中,我们定义了一个`Node`结构体表示单链表的节点,其中包含一个整数值和一个指向下一个节点的指针。`delete_node`函数接受一个头节点和一个要删除的值,然后删除具有该值的节点。如果头节点是要删除的节点,我们将头节点的指针指向下一个节点,并释放头节点的内存。否则,我们遍历链表,找到要删除节点的前一个节点,并将前一个节点的指针指向要删除节点的下一个节点,然后释放要删除节点的内存。最后,返回修改后的头节点。

2.插入结点

单链表的节点插入可以通过以下步骤实现:

单链表的节点插入可以通过以下步骤实现:

 创建一个新的节点,并设置其值。
 找到要插入的位置的前一个节点。
 将新节点的指针指向前一个节点的下一个节点。
 将前一个节点的指针指向新节点。

#include <stdio.h>
#include <stdlib.h>

typedef struct Node {
    int val;
    struct Node* next;
} Node;

Node* insert_node(Node* head, int val, int position) {
    Node* new_node = (Node*)malloc(sizeof(Node));
    new_node->val = val;
    if (position == 0) {
        new_node->next = head;
        return new_node;
    }

    Node* prev = NULL;
    Node* cur = head;
    for (int i = 0; i < position; i++) {
        if (cur == NULL) {
            break;
        }
        prev = cur;
        cur = cur->next;
    }

    if (prev != NULL) {
        prev->next = new_node;
    }
    new_node->next = cur;

    return head;
}

示例中,`ListNode`类表示单链表的节点,`insert_node`函数接受一个头节点、一个要插入的值和一个插入位置,然后插入一个新节点。如果要在链表的开头插入节点,我们将新节点的指针指向头节点,并将新节点作为新的头节点返回。否则,我们遍历链表,找到要插入位置的前一个节点,并将新节点的指针指向前一个节点的下一个节点,然后将前一个节点的指针指向新节点。最后,返回修改后的头节点。

3.清空链表

单链表的清空可以通过以下步骤实现:

遍历链表,释放每个节点的内存。
将头节点指针设置为NULL。

#include <stdio.h>
#include <stdlib.h>

typedef struct Node {
    int val;
    struct Node* next;
} Node;

void clear_list(Node* head) {
    Node* cur = head;
    while (cur != NULL) {
        Node* next = cur->next;
        free(cur);
        cur = next;
    }
}

4.其他功能:

求链表长度:遍历链表并计数,直到最后一个节点,即可得到链表的长度
查找结点:通过遍历链表寻找含有特定数据的节点,常用于搜索操作
输出链表:通过从头到尾遍历链表,输出每个节点的数据域内容
修改结点值:通过遍历链表找到对应的节点,然后修改其数据域的值

结语:

谢谢你看完我的文章,喜欢我的文章的话就给我点个赞再走吧!

下次见!拜拜┏(^0^)┛

标签:Node,node,结点,单链,--,next,链表,节点
From: https://blog.csdn.net/2301_79695216/article/details/139474029

相关文章

  • OnlyOwner在Solidity中是一个修饰符,TypeError:
    目录OnlyOwner在Solidity中是一个修饰符TypeError:Datalocationmustbe"memory"or"calldata"forparameterinfunction,butnonewasgiven.functionAddDOm(addressdataOwnermAddress,stringdataProduct,stringdataNotes)OnlyOwnerpublic{^-......
  • Spring Boot入坑-8-定时任务
    概述在企业级的项目业务中,往往会有一系列的任务需要在有逻辑的指定时间点执行,如系统间定时同步数据、定时做某个复杂的计算、订单提交后30分钟需要付款等上述这些,就需要任务的定时调度与执行来完成,这是程序的基本需要在Java语言中,提供了基础的基于Timer和ScheduledExecut......
  • SCI论文中缩写怎么使用,SCI伪代码命名规范
    目录sci论文中缩写怎么使用SCI伪代码命名规范方法命名变量命名规范常量命名规范过滤停用词性sci论文中缩写怎么使用在SCI论文中,缩写的使用应遵循一定的规则和格式,以确保论文的清晰度和可读性。以下是一些关于SCI论文中缩写使用的详细指导:使用频率:一个词或词......
  • SuntoryProgrammingContest2024(AtCoder Beginner Contest 357)
    A-SanitizeHands题意:给定一个序列和m,问m按顺序减去这个序列,m>=0情况下最多能减多少个数思路:前缀和+prev(upper_bound())总结:disinfectan(消毒ji),disinfect(消毒,杀毒),aliens(外星人),voidsolve(){ intn,m; cin>>n>>m; vector<int>a(n); for(inti=......
  • 【运维必备知识】Linux系统平均负载与top、uptime命令详解
    【运维必备知识】Linux系统平均负载与top、uptime命令详解大家好,我是秋意零工作中,服务出现问题如何排查Linux系统侧。首先第一想到应该排查是否是负载过高导致的。今天,这篇就来看看,top、uptime命令中平均负载(loadaverage)相关内容,初学者应该关注都比较少(也包括我。。)top......
  • SoftMax 的困境:在稀疏性和多模态之间左右为难
    SoftMax是现代机器学习算法中无处不在的组成部分。它将输入向量映射到概率单纯形,并通过将概率质量集中在较大的条目上,来重新加权输入。然而,作为Argmax函数的平滑近似,SoftMax将大量的概率质量分配给其他剩余的条目,导致可解释性差和噪声。虽然稀疏性可以通过一系列SoftMa......
  • TiffUtity
    usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Threading.Tasks;usingSystem.Drawing;usingSystem.Drawing.Imaging;usingSystem.IO;usingSystem.Collections;usingEmgu.CV;namespaceTestWinform{publicclassTiffUtity{......
  • 练习:用户设计一个程序,要求程序每隔1s就获取当前系统时间并输出到终端,但是用户不打算让
    练习:用户设计一个程序,要求程序每隔1s就获取当前系统时间并输出到终端,但是用户不打算让其他用户通过快捷键Ctrl+C来强制结束该程序,所以要求现在设计该程序。#include<stdio.h>#include<stdlib.h>#include<unistd.h>#include<signal.h>//信号处理函数,用于忽略S......
  • 《软件定义安全》之四:什么是软件定义安全
    第4章什么是软件定义安全1.软件定义安全的含义1.1软件定义安全的提出虚拟化、云计算、软件定义架构的出现,对安全体系提出了新的挑战。如果要跟上网络演进的步伐和业务快速创新的速度,安全体系应该朝以下方向演变。......
  • 港口码头人员定位管理 - 北斗RTK+蓝牙+UWB融合解决方案应用
    1.行业痛点港口码头规模庞大、人员众多,每日人员流动频繁,货物吞吐量巨大。需要有效对人员进行安全管控。1.1避免潜在的安全风险机械设备运作、货物搬运、危险品操作等潜在危险因素无处不在。通过人员定位系统,我们可以实时掌握每个工作人员的位置和状态,一旦发现安全隐患,便能......