【C语言督学训练营 第十一天】三篇文章吃透数据结构中的线性表(二)----- 链表的增删改查与销毁

news2024/11/15 1:50:48

文章目录

  • 前言
  • 一、链表
    • 1.基本介绍
    • 2.增删改查原理与实战
  • 总结与源码

前言

谭浩强老师说过:“指针是c语言的灵魂”,今天说到的链表就是由C语言的灵魂所筑,学会了链表之后可以使用链表轻松实现树、图等数据结构,可以轻松化解考研数据结构大题!在说今天的内容之前先看一下往年出现的有关链表的大题。
在这里插入图片描述

一、链表

链表通常适用于一下几种情况

  • 在线性表中插入和删除操作大量元素或者很频繁
  • 线性表的大小不好确定

1.基本介绍

下面图片是链表在逻辑结构与物理结构上的存储方式(灰色为实际存储结构,蓝色球球为逻辑结构)
在这里插入图片描述
记住最主要的一点:链表的每一个节点都由指针域与数据域组成,其中指针域负责记录下一个节点的地址,数据域负责记录本节点数据。一个指针域的节点可以串成单链表,两个指针域的节点可以串成双向、循环链表、二叉树等数据结构。做出改变的仅仅是指针域的关系!

老师说未来四月份会开数据结构的课,到时候应该会详细介绍,目前只需了解即可。
单链表中的一些概念如下:
在这里插入图片描述

2.增删改查原理与实战

在链表中插入元素
插入元素的话可以分为头插法、尾插法、中间插入法,下面图片是实现原理,代码分别是头插法、尾插法、中间插法。
在这里插入图片描述

//头插法
void head_insert(myList* head,ElemType e){
    myList *p= (myList*)malloc(sizeof (myList));
    p->data=e;
    p->next=head->next;
    head->next=p;
    // 如果写成以下样子,将不会有效果
    // head->next=p->next;
}
//尾插法
void tail_insert(myList* tail,ElemType e){
    myList *p;
    p=tail;
    while (p->next!=NULL){
        p=p->next;
    }
    p->next=(myList*) malloc(sizeof (myList));
    p->next->data=e;
    p->next->next=NULL;
}
//随机插入
bool random_insert(myList* head,int i,ElemType e){
    myList *p=head;
    int j=0;
    for(;p!=NULL,j<i-1;j++){
        p=p->next;
    }
    if(p!=NULL){
        myList *q=(myList*)malloc(sizeof (myList));
        q->data=e;
        q->next=p->next;
        p->next=q;
        return true;
    }else{
        return false;
    }
}

删除链表中的节点
删除链表中的节点,重中之重是合理的改变节点的指针关系。

在这里插入图片描述

在这里插入图片描述
代码:

//删除相应元素
bool delete_e(myList* head,ElemType e){
    for (myList* p=head;p->next!=NULL;p=p->next){
        if(p->next->data==e){
            myList *q =p->next;
            p->next=p->next->next;
            free(q);
        }
    }
    return false;
}

查找链表中的节点

查找节点一般可以分为:

  • 按序号查找
    在这里插入图片描述
  • 按值查找
    在这里插入图片描述

按值查找与按序号查找我分别实现了一遍,按值查找只判断找到没找到,按序号查找是将找到的信息返回出来,没有匹配的就返回NULL。

//按位置查找
myList* index_search(myList *head,int i){
    if(i<=0){
        return NULL;
    }
    myList *p=head;
    int j=0;
    // 循环终止条件如果有多个的话需要用逻辑表达式连接
    // 不可以使用逗号连接,用逗号连接遵循逗号表达式使用规则
    for(;p->next!=NULL&&j<i-1;j++){
        p=p->next;
    }
    return p->next;
}
//按值查找
bool element_search(myList *head,ElemType e){
    for (myList* p=head;p->next!=NULL;p=p->next){
        if(p->next->data==e){
            return true;
        }
    }
    return false;
}

总体来说还是按值查找用的多一些!

销毁链表
这也是常用的一个功能,比较简单就不细说了!直接上代码不懂的评论区留言吧。

//销毁链表
void destroy_myList(myList* head){
    myList *p=head->next;
    myList *q=NULL;
    while (p!=NULL){
        q=p;
        p=p->next;
        free(q);
    }
    head->next=NULL;
}

下面是遍历链表的两个函数

//遍历链表
void print_list(myList *head){
    if(head->next==NULL){
        printf("null!!!");
    }
    for (myList *p=head;p->next!=NULL;p=p->next){
        printf("%2c",p->next->data);
    }
    printf("\n");
}
void print(myList *p){
    if(p!=NULL){
        printf("%2c\n",p->data);
    }else{
        printf("null\n");
    }
}

总结与源码

链表的优缺点
在这里插入图片描述
关于链表调试,由于链表在内存中并不是连续存在的,因此编译器的虚拟内存视图在调试的时候是排不上用场的,大家调试的话可以使用以下方法;通过单步调试,直接在变量窗口,把头指针L,依次点开,观察每一个结点是否符合自己的预期。同时大家在练习时,不要输入过多的数据,数据数量小于等于上课的即可。

在这里插入图片描述

源代码
这个代码实现了对链表的增删查(改与查重的话比较简单大家可以下去添上),每一个函数功能都在函数的正上方,感兴趣的同学可以自己研究研究,有不懂的地方欢迎评论区留言!

//
// Created by Zhu Shichong on 2023/1/9.
//
#include <stdio.h>
#include<stdlib.h>
#define bool int
#define true 1
#define false 0
typedef char ElemType;
//数组类型
struct myList{
    ElemType data;
    struct myList* next;
};
typedef struct myList myList;
//头插法
void head_insert(myList* head,ElemType e){
    myList *p= (myList*)malloc(sizeof (myList));
    p->data=e;
    p->next=head->next;
    head->next=p;
    // 如果写成以下样子,将不会有效果
    // head->next=p->next;
}
//尾插法
void tail_insert(myList* tail,ElemType e){
    myList *p;
    p=tail;
    while (p->next!=NULL){
        p=p->next;
    }
    p->next=(myList*) malloc(sizeof (myList));
    p->next->data=e;
    p->next->next=NULL;
}
//随机插入
bool random_insert(myList* head,int i,ElemType e){
    myList *p=head;
    int j=0;
    for(;p!=NULL,j<i-1;j++){
        p=p->next;
    }
    if(p!=NULL){
        myList *q=(myList*)malloc(sizeof (myList));
        q->data=e;
        q->next=p->next;
        p->next=q;
        return true;
    }else{
        return false;
    }
}
//按位置查找
myList* index_search(myList *head,int i){
    if(i<=0){
        return NULL;
    }
    myList *p=head;
    int j=0;
    // 循环终止条件如果有多个的话需要用逻辑表达式连接
    // 不可以使用逗号连接,用逗号连接遵循逗号表达式使用规则
    for(;p->next!=NULL&&j<i-1;j++){
        p=p->next;
    }
    return p->next;
}
//按值查找
bool element_search(myList *head,ElemType e){
    for (myList* p=head;p->next!=NULL;p=p->next){
        if(p->next->data==e){
            return true;
        }
    }
    return false;
}

//删除相应元素
bool delete_e(myList* head,ElemType e){
    for (myList* p=head;p->next!=NULL;p=p->next){
        if(p->next->data==e){
            myList *q =p->next;
            p->next=p->next->next;
            free(q);
        }
    }
    return false;
}
//销毁链表
void destroy_myList(myList* head){
    myList *p=head->next;
    myList *q=NULL;
    while (p!=NULL){
        q=p;
        p=p->next;
        free(q);
    }
    head->next=NULL;
}
//遍历链表
void print_list(myList *head){
    if(head->next==NULL){
        printf("null!!!");
    }
    for (myList *p=head;p->next!=NULL;p=p->next){
        printf("%2c",p->next->data);
    }
    printf("\n");
}
void print(myList *p){
    if(p!=NULL){
        printf("%2c\n",p->data);
    }else{
        printf("null\n");
    }
}
int main() {
    // 创建一个头结点(头结点一般不用于存储信息)
    myList *head=(myList*)malloc(sizeof (myList));
    head->next=NULL;
    printf("tail insert some data!\n");
    tail_insert(head,'h');
    tail_insert(head,'o');
    tail_insert(head,'w');
    tail_insert(head,'a');
    tail_insert(head,'r');
    tail_insert(head,'e');
    tail_insert(head,'y');
    tail_insert(head,'o');
    tail_insert(head,'u');
    print_list(head);
    printf("after head_insert:");
    head_insert(head,'q');
    head_insert(head,'q');
    print_list(head);
    printf("after random_insert:");
    random_insert(head,3,'t');
    print_list(head);
    delete_e(head,'t');
    printf("after delete:");
    print_list(head);
    printf("search:%c \nsearch_reasult:%d\n", 'q',element_search(head,'q'));
    myList *q= index_search(head,10);
    print(q);
    q= index_search(head,1);
    print(q);
    q= index_search(head,100);
    print(q);
    q= index_search(head,-100);
    print(q);
    printf("list destroyed!!\n");
    destroy_myList(head);
    print_list(head);
    return 0;
}

警示自己:循环里面的循环变量变动可以使用,隔开,但是循环终止条件必须使用逻辑运算符隔开!!!


在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/431913.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

《无线神经调节的微创技术治疗慢性顽固性疼痛:初步观察报告》

**全文概况 **&#xff1a;该文件讨论了一种新型无线和微创神经调节设备&#xff0c;用于治疗之前曾经失败的患者慢性顽固性疼痛。该设备通过经皮植入的电极远程控制&#xff0c;进行高频背根节神经刺激或周围神经刺激。该系统对于患有腰腿疼痛的患者有重要潜力&#xff0c;因为…

车载 Android开发面试习题整合~

随着车联网技术的不断发展和普及&#xff0c;越来越多的汽车厂商开始使用 Android 操作系统作为车载娱乐和信息娱乐系统的核心。在这个趋势下&#xff0c;车载 Android 应用开发程序员的需求也日益增加。 像一些车企大厂在广招这方面的技术人才。给原本处于落寞的Android 开发行…

PTA:C课程设计(7)

山东大学&#xff08;威海&#xff09;2022级大一下C习题集&#xff08;7&#xff09;函数题7-6-1 递增的整数序列链表的插入7-6-2 查找学生链表7-6-3 统计专业人数7-6-4 建立学生信息链表编程题7-7-1 查找书籍7-7-2 找出总分最高的学生函数题 7-6-1 递增的整数序列链表的插入…

五子棋透明棋盘界面设计(C语言)

五子棋透明棋盘设计&#xff0c;漂亮的界面制作。程序设置双人对奕&#xff0c;人机模式&#xff0c;对战演示三种模式。设置悔棋&#xff0c;记录功能&#xff0c;有禁手设置。另有复盘功能设置。 本文主要介绍透明的玻璃板那样的五子棋棋盘的制作。作为界面设计&#xff0c;…

「Bug」OpenCV读取图像为 None 分析

头一次遇到 OpenCV 无法读取图像&#xff0c;并且没有任何提示&#xff0c;首先怀疑的就是中文路径&#xff0c;因为大概率是这个地方出错的&#xff0c;但是修改完依旧是None&#xff0c;这就很苦恼了&#xff0c;分析了下出现None的原因&#xff0c;大概有以下三种情况&#…

ssm--MyBatis基础day01

1.MyBatis概述 1.1 ORM框架 对象关系映射&#xff08;Java中的对象 对应 数据库中的表&#xff09; 1.2 官网地址 mybatis 1.3 MyBatis Plus MyBatis-Plus (baomidou.com)官网 1.4 JPA Java 持久层API 2. MAVEN引入 2.1 配置maven 2.2 导入MyBatis <dependency>…

带你们偷瞄编程绕不开的C语言(三)

&#x1f929;本文作者&#xff1a;大家好&#xff0c;我是paperjie&#xff0c;感谢你阅读本文&#xff0c;欢迎一建三连哦。 &#x1f970;内容专栏&#xff1a;这里是《C专栏》&#xff0c;笔者用重金(时间和精力)打造&#xff0c;基础知识一网打尽&#xff0c;希望可以帮到…

面试篇-学习Java多线程编程必备:深入理解volatile与synchronized

1. 概述 1.1 Volatile概述 Volatile是Java中的一种轻量级同步机制&#xff0c;用于保证变量的可见性和禁止指令重排。当一个变量被声明为Volatile类型时&#xff0c;任何修改该变量的操作都会立即被所有线程看到。也就是说&#xff0c;Volatile修饰的变量在每次修改时都会强制…

8080时序驱动液晶屏

一、TFT-LCD简介。 TFT-LCD&#xff08;thin film transistor-liquid crystal display&#xff09;即薄膜晶体管液晶显示器。液晶显示屏的每一个像素上都设置有一个薄膜晶体管&#xff08;TFT&#xff09;&#xff0c;每个像素都可以通过点脉冲直接控制&#xff0c;因而每个节点…

第一节 法学

目录 法学的概念法学的性质 实践性构成了法学的学问性质 法学的研究对象 1.法律制度问题&#xff08;X法律制度&#xff09;2. 社会现实或社会生活关系问题 (Y社会现实/社会关系)3.法律制度与社会现实之间如何对应的问题 &#xff08;Yf(x) f为什么函数&#xff09; 法学的概…

ChatGPT或要推出APP,OpenAI官宣为ChatGPT招募移动端开发工程师

文 | 兔子酱OpenAI官方招聘页面放出了英雄帖&#xff0c;他们正在为ChatGPT招聘移动端工程师&#xff1a;传送门&#xff1a;https://openai.com/careers/mobile-engineering-manager-chatgpt其中&#xff0c;跨iOS和Android的工程主管年薪为20至37万美元,总薪酬还包括慷慨的股…

ActiveMQ使用(五):在JavaScript中发送的MQTT消息在C#中变为字节数组

ActiveMQ使用(五):在JavaScript中发送的MQTT消息在C#中变为字节数组 1. 问题描述 ** C#中的代码: ** internal class Program{static void Main(string[] args){ConnectionFactory factory new ConnectionFactory("tcp://localhost:61616");IConnection connecti…

【数据结构与算法】程序员常用10种算法(分治算法)

一、分治算法介绍 在计算机科学中&#xff0c;分治法就是运用分治思想的一种很重要的算法。 分治&#xff0c;字面上的解释是“分而治之”&#xff0c;就是把一个复杂的问题分成两个或更多的相同或相似的子问题&#xff0c;再把子问题分成更小的子问题……直到最后子问题可以…

【DNS】域名解析服务

文章目录 1.DNS1.1 DNS定义1.2 DNS系统作用1.3 DNS解析过程 1.DNS 1.1 DNS定义 DNS是"域名系统"的英文缩写。它作为将域名和IP地址相互映射的一个分布式数据库&#xff0c;能够使人更方便地访问互联网。 DNS服务使用TCP和UDP的53端口&#xff0c;TCP的53端口用于连…

Java - 内部类

1、本地内部类 2、实例内部类 3、静态内部类 4、匿名内部类 首先&#xff0c;我要在这声明一下&#xff0c;内部类也是类&#xff0c;不管它是属于何种类型。 只要是类&#xff0c;就会有类的特性&#xff1a;继承 / 被继承&#xff0c;实现接口&#xff0c;套娃【内部类再套一…

JWT 鉴权插件上线!让你的 API 更安全!

API鉴权是保证API安全性和可用性的一项重要措施。通过API鉴权&#xff0c;系统可以对用户或者应用进行有效的身份认证和权限管理。 除了我们之前更新的 Basic Auth 鉴权插件&#xff0c;这次给大家带来 JWT 鉴权插件。 JSON Web Token是一种开放标准&#xff0c;可以让服务器生…

数字孪生智慧路桥怎么实现?

近年来&#xff0c;道路桥梁安全事故频发&#xff0c;直接影响到了行车人员的人身安全&#xff0c;并且对整个公路桥梁的稳定性产生了不良影响。因此对道路桥梁运行状态的实时监测、及时进行运行状态的预警、实现巡检运维智慧化&#xff0c;已成为桥梁道路管理重点关注的方面。…

PostgreSQL与MySQL优劣势比较浅谈

目录 1 简介2 postgresql比mysql强大在那些方面3 PostgreSQL 为什么在国内没有MySQL流行4 postgresql比mysql一些主要区别5 postgresql比mysql特征比较5.1 MariaDB的主要特点5.2 PostgreSQL的主要特点 6 总结 1 简介 因为公司使用PostgreSQL很长时间了&#xff0c;忙于功能开发…

计算机视觉-角点检测

角点检测 1.分别实现Harris角点检测与SIFT特征提取&#xff0c;对比两者的区别1.1代码实现1.2两者区别 2.利用SIFT算法实现两幅相近图像的特征匹配2.1代码实现 3.实现匹配地理标记图像3.1代码实现 4.实验注意事项4.1实验需要安装的库和应用4.2报错内容 5.小结 1.分别实现Harris…

cdr文件怎么转化成ai文件 CDR文件转AI文件大小会变化吗

cdr与AI软件都可以用于制作矢量图形。基于不同的打印与使用需求&#xff0c;可能需要将cdr文件保存为ai文件使用。那么&#xff0c;cdr文件怎么转化成ai文件&#xff0c;CDR文件转AI文件大小会变化吗&#xff1f;下面让我们来详细解读一下吧。 一、cdr文件怎么转化成ai文件 c…