数据结构C语言-单链表的定义、销毁及增删改查

2023-11-07

声明部分:

typedef struct Lnode
{
    int data;
    struct Lnode *next;
} Lnode, *LinkList; //LinkList单链表

//以下操作均为带头结点的单链表
LinkList CreateLinkList();                           //创建单链表
void DestoryLinkList(LinkList *L);                   //销毁单链表
int ListIsEmpty(LinkList L);                         //判空:=1为空表,=0为非空表
Lnode *GetListElem(LinkList L, int index);           //按位查找:按位序查找该结点的指针
Lnode *LocateListElem(LinkList L, int elem);         //按值查找:给定一个值,查找表中第一个数据域与其相等的结点指针
int ListLength(LinkList L);                          //求表长(结点个数,不算头结点)
int LinkListInsert(LinkList L, int index, int elem); //按位序插入:在index位置插入一个结点,其值为elem
int InsertNextNode(Lnode *node, int elem);           //后插法:在node指针所指的结点后插入一个新节点
int InsertPriorNode(Lnode *node, int elem);          //前插法:在node指针所指的结点前插入一个新节点
int LinkListDelete(LinkList L, int index);           //按位序删除:在index位置删除一个结点
int DeleteNode(Lnode *p);                            //删除指定节点,仅给定需要删除的结点的指针(无法删除最后一个结点)

每个函数的具体定义:

创建单链表:

LinkList CreateLinkList()
{
    LinkList L = (LinkList)malloc(sizeof(Lnode)); //用一个单链表的指针指向头结点
    if (L == NULL)
    {
        printf("创建单链表失败,内存不足!\n");
    }
    else
    {
        L->data = 0;    //头指针不存放数据
        L->next = NULL; //暂时没有后继结点
        return L;
    }
}

销毁单链表:

void DestoryLinkList(LinkList *L)
{
    LinkList p;
    while(*L != NULL)
    {
        p = *L;
        *L = (*L)->next;
        free(p);
    }
}

判空(=1为空表,=0为非空表):

int ListIsEmpty(LinkList L)
{
    return L->next == NULL;
}

按位查找(按位序查找该结点的指针 ):

Lnode *GetListElem(LinkList L, int index)
{
    int loc = 1;        //当前p指针指向的结点是链表中的第几个
    Lnode *p = L->next; //初始化时指向链表的第一个结点

    if (index == 0)
    {
        return L;
    }
    if (index < 1)
    {
        printf("查找的入口非法\n");
        return NULL;
    }

    while (p != NULL && loc < index)
    {
        p = p->next;
        loc++;
    }
    return p;
}

按值查找(定一个值,查找表中第一个数据域与其相等的结点指针 ):

Lnode *LocateListElem(LinkList L, int elem)
{
    Lnode *p = L->next;
    while (p != NULL && elem != p->data)
    {
        if (p->next == NULL)
        {
            printf("未找到该元素\n");
            return NULL;
        }
        else
        {
            p = p->next;
        }
    }
    return p;
}

求表长(结点个数,不算头结点):

int ListLength(LinkList L)
{
    int len = 0;
    Lnode *p = L;
    while (p->next != NULL)
    {
        len++;
        p = p->next;
    }
    return len;
}

按位序插入(在index位置插入一个结点,其值为elem ):

int LinkListInsert(LinkList L, int index, int elem)
{
    if (index < 1)
    {
        printf("入口越界!\n");
        return 0;
    }

    Lnode *pre = GetListElem(L, index - 1); //寻找index前驱节点
    InsertNextNode(pre, elem);              //在前驱结点之后插入新结点
    return 1;
}

 后插法(在node指针所指的结点后插入一个新节点):

int InsertNextNode(Lnode *node, int elem)
{
    if (node == NULL)
    {
        printf("输入了非法指针\n");
        return 0;
    }

    Lnode *new = (Lnode *)malloc(sizeof(Lnode));
    if (new == NULL)
    {
        printf("插入失败,内存不足!\n");
        return 0;
    }

    new->data = elem;
    new->next = node->next;
    node->next = new;
    return 1;
}

 前插法(在node指针所指的结点前插入一个新节点):

int InsertPriorNode(Lnode *node, int elem)
{
    int predata = 0;
    if (node == NULL)
    {
        printf("输入了非法指针\n");
        return 0;
    }

    Lnode *new = (Lnode *)malloc(sizeof(Lnode));
    if (new == NULL)
    {
        printf("插入失败,内存不足!\n");
        return 0;
    }

    //将原来的结点复制到新结点
    new->next = node->next;
    new->data = node->data;
    //让原来结点的data = elem
    node->next = new;
    node->data = elem;
    return 1;
}

 按位序删除(在index位置删除一个结点):

int LinkListDelete(LinkList L, int index)
{
    if (L == NULL)
    {
        printf("传入指针为空!\n");
        return 0;
    }

    Lnode *pre = GetListElem(L, index - 1); //找到index的前驱结点
    if (pre == NULL || pre->next == NULL)   //前驱结点或此节点不存在
        printf("此结点或前驱结点为空!\n");
    return 0;

    Lnode *p = pre->next;
    pre->next = p->next; //断开p结点
    free(p);
    return 1;
}

 删除指定节点(仅给定需要删除的结点的指针,无法删除最后一个结点):

int DeleteNode(Lnode *node)
{
    if (node == NULL)
        return 0;

    Lnode *p = node->next;
    node->data = p->data; //由于最后一个结点无后继结点,p的数据域没有数据,无法删除最后一个结点
    node->next = p->next;
    free(p);
    return 1;
}

 总结:

1.学习过程中发现,销毁单链表操作需要用到二级指针,由于 LinkList L 传入的为单链表的一级指针,所以只能在传入函数后通过一级指针修改其所指空间的内容(即数据域和指针域的内容),而销毁操作需要释放链表的空间,修改链表本身的地址为NULL,所以需要传入二级指针对链表本身的地址,才可以销毁链表。

2.引用头指针的好处:

   (1).使得在链表的第一个位置上的操作和在表的其他位置上的操作一致。

   (2).空表和非空表的处理一致。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

数据结构C语言-单链表的定义、销毁及增删改查 的相关文章

  • 什么是HTML? 看这一篇就够了(附带主流IDE推荐)

    1 HTML简介 1 1 HTML是什么 百度词条 HTML称为超文本标记语言 是一种标识性的语言 它包括一系列标签 通过这些标签可以将网络上的文档格式统一 使分散的Internet资源连接为一个逻辑整体 HTML文本是由HTML命令组成的

随机推荐

  • 第十九篇:处理僵尸进程的两种经典方法

    前言 如果父进程没有结束 而子进程终止了 那么在父进程调用 wait 函数回收这个子进程或者父进程终止以前 这个子进程将一直是僵尸进程 本文将提供两种方法处理这个问题 方法一 父进程回收法 wait函数将使其调用者阻塞 直到其某个子进程终止
  • 伺服电机的三种控制方式与三闭环控制

    项目 FPGA双电机主从快速稳定控制实现 第一章 伺服电机的三种控制方式与三闭环控制 伺服电机的三种控制方式与三闭环控制 项目 FPGA双电机主从快速稳定控制实现 前言 一 电机控制方式 二 电机三个闭环负反馈PID控制系统 三 三闭环位置
  • GLUE基准数据集介绍

    图1 整篇文章的思维导图 一 简介 自然语言处理 NLP 主要自然语言理解 NLU 和自然语言生成 NLG 为了让NLU任务发挥最大的作用 来自纽约大学 华盛顿大学等机构创建了一个多任务的自然语言理解基准和分析平台 也就是GLUE Gene
  • 完美解决dataframe添加列,并且指定列的位置

    需求是这样的 我需要从原始表中提取几列数据 分别填入税表的人员和收入表中 原始表中只有 姓名 身份证号码 年金领取额是有效数据 但是税务局的模板表中有一大堆莫名其妙的字段不需要填写 先把原始表定义一下 把身份证字符串一下 再把需要的人员 收
  • Spark整理

    文章目录 1 概述 1 1 Spark 和 Hadoop 组成 1 2 Spark 和 Hadoop 区别 2 Spark 运行架构 2 1 基础架构 2 2 Master Worker Standalone模式 2 3 Applicati
  • 如何给VScode安装clang(C language)插件

    前言 1 本篇经验专门为 使用VScode开发c语言项目的学生和工程师而写 2 安装了clang C language 插件的VScode编辑器 补全功能将更加智能 正文 首先你得先安装vscode软件 安装教程请参考下链接 对于本人就不费
  • STC15单片机——定时/计数器2、3、4

    STC15单片机拥有5个定时器 分别为定时器0 1 2 3 4 本文章将记录定时器2 3 4所使用的寄存器 以及注意事项 由于STC15单片机定时器的使用于传统51单片机类似 这里仅标出应用所需的j寄存器 以及对陌生位的相关说明 其他不作过
  • 2020年下一个创业风口是什么?

    提到风口 大家总是兴致勃勃 满心期待的看完一个风口项目后 剩下的不是去选择执行 而是继续问道 还有其它的风口项目吗 所以 在我看来 对于大多数人而言 风口就是继续追问 没完没了的问还有其它的吗 今年没有抓住风口 告诉自己 不能灰心 明年拜菩
  • 支持向量机(SVM)

    SVM简介 SVM Support Vector Machine 它是一种二分类模型 其基本模型定义为特征空间上的间隔最大的线性分类器 其学习策略便是间隔最大化 最终可转化为一个凸二次规划问题的求解 这里涉及了几个概念 二分类模型 线性分类
  • 去除百度推广等广告的插件神器

    给大家推荐一款去除百度推广的神器 包括右边 及右下角弹出的广告 1 搜索ADblock进入官网https adblockplus org 点击 安装到chrome 弹出提示框点击 添加扩展程序 2 重新打开网址 你会发现之前的广告都消失了
  • 微信小程序开发一个小型商城(四、商品列表)

    上一篇文章 微信小程序开发一个小型商城 三 商品分类设计 在从上一个界面跳转过来 会看到商品列表这个界面 如下图所示 页面分析 从上到下 分别是一个已经定义好的自定义组件 下面的综合 销量 也是一个自定义组件 下面商品的一个个的小框框就是一
  • postgresql安装配置和基本操作

    1 安装 linux上安装 最好是centos7 6或者7 8 参考官网 PGSQL的官方地址 PostgreSQL The world s most advanced open source database PGSQL的国内社区 Pos
  • 【ElasticSearch】查询报错JsonpMappingException

    ElasticSearch查询报错JsonpMappingException 具体报错信息如下 co elastic clients json JsonpMappingException Error deserializing co ela
  • ajax+同步+返回数据库,如何使AJAX同步

    异常是我需要从数据库中立即返回的数据 不过 我需要 连续代码 来等待Id被返回 最好的办法是不要让这种情况发生 而是要接受事件驱动的 基于浏览器和网络编程的异步性质 非常小的选项是强制ajax请求同步 目前 在jQuery 1 x中 您可以
  • Unity 动态打图集并完成小Demo的实现

    为什么要动态打图集 比如在英雄联盟中的选择英雄界面 有很多的图标供我们选择 而我们进入游戏之后只需要选择的那两三个图标而已 这是如果我们将所有图标都打成图集 就造成内存浪费 因为我们只需要两三个而已 那么我们有什么办法让我们只将要用到的图标
  • YOLOv7改进之二十二:涨点神器——引入递归门控卷积(gnConv)

    前 言 作为当前先进的深度学习目标检测算法YOLOv7 已经集合了大量的trick 但是还是有提高和改进的空间 针对具体应用场景下的检测难点 可以不同的改进方法 此后的系列文章 将重点对YOLOv7的如何改进进行详细的介绍 目的是为了给那些
  • win10 远程桌面连接失败

    为什么远程桌面连接不上win10 防火墙 我关了 Te Service服务没开 我开 Remote Procedure Call RPC 服务没开 我再开 还不行 看图
  • 【unity】角色移动控制,移动,跳跃,地面监测

    文章目录 场景 1 character controller 2 通过键盘操控前后左右移动 3 重力作用 4 地面检测 5 跳跃 6 跳跃的时候保持地速 7 完整的代码如下 场景 做一个简单的任务移动控制 wasd的键盘移动 跳跃 地面检测
  • CCF201612-2工资计算

    试题编号 201612 2 试题名称 工资计算 时间限制 1 0s 内存限制 256 0MB 问题描述 问题描述 小明的公司每个月给小明发工资 而小明拿到的工资为交完个人所得税之后的工资 假设他一个月的税前工资 扣除五险一金后 未扣税前的工
  • 数据结构C语言-单链表的定义、销毁及增删改查

    声明部分 typedef struct Lnode int data struct Lnode next Lnode LinkList LinkList单链表 以下操作均为带头结点的单链表 LinkList CreateLinkList 创