11.链表

数组的分类:便于遍历

静态数组:int arr[10]数据过多造成空间溢出,数据过小空间浪费

动态数组:malloc calloc realloc 合理利用空间不能快捷的插入或删除数据(会涉及到大量的数据移动)

知识点一:链表的基本概念

链表的基本概念

链表是一种物理存储上非连续,数据元素的逻辑顺序通过链表中的指针链接次序,实现的一种线性存储结构

链表由一系列节点( 链表中每一个元素称为节点)组成,节点在运行时动态生成(malloc) ,每个节点包括两个部分:

    1)存储数据元素的数据域          2)存储下一个节点地址的指针域

知识点二:链表结点的定义(结构体实现)

typedef struct stu
{
    //数据域(自定义)
    int num;
    char name[32];
    float score;
    //指针域
    struct stu *next;	//保存 下一个节点的地址:
}STU;

知识点三:静态链表

typedef struct stu
{
    int num;
    char name[32];
    float score;
    struct stu *next;	//保存 下一个节点的地址:
}STU;
void test1()
{    
    STU datal = {100, "德玛",59};
    STU data2 = {101, "小炮",89};
    STU data3 = {102, "小法",79};
    STU data4 = {103,"盲僧",99};
    STU data5 = {104, "快乐风男",39};
    //链表头
    STU *head = NULL;
    head = &datal;
    datal.next = &data2;
    data2.next = &data3;
    data3.next = &data4;
    data4.next = &data5;
    data5.next = NULL;
    //遍历链表
    STU *pb = head;
    while(pb != NULL)
    {
        printf("%d %s %f\n", pb->num, pb->name, pb->score) ;
        pb = pb->next;    //pb指向下一一个节点
    }
}

知识点四:动态链表

1、布局整个框架(main.c)

#include<stdio.h>
#include<string.h>
void stu_help(void);
int main(int argc,char *argv[])
{
    stu_help();
    while(1)
    {
        printf("请输入操作指令:");
        char cmd[32] = "";
        scanf( "%s",cmd);
        if(strcmp(cmd,"help") == 0)
        {
            printf("-----help------\n");
        }
        else if(strcmp(cmd,"insert") == 0)
        {
            printf("-----insert------\n");
        }
        else if(strcmp(cmd,"print") == 0)
        {
            printf("-----print------\n");
        }
        else if(strcmp(cmd,"search") == 0)
        {
            printf("-----search------\n");
        }
        else if(strcmp(cmd,"delete") == 0)
        {
            printf("-----delete------\n");
        }
        else if(strcmp(cmd,"free") == 0)
        {
            printf("-----free------\n");
        }
        else if(strcmp(cmd,"quit") == 0)
        {
            break;
        }
     }        
    return 0;
}
void stu_help(void)
{
    printf("############################\n");
    printf("#help:打印帮助信息         #\n");
    printf("#insert:插入链表节点       #\n");
    printf("#print:遍历链表节点信息    #\n");
    printf("#search:查询链表节点       #\n");
    printf("#delete:删除链表节点       #\n");
    printf("#free:释放链表             #\n");
    printf("#quit:退出                 #\n");
    printf("############################\n");
    return;
}

2、链表插入节点之头部之前插入

链表插入节点之头部之前插入 头部之前插入原理分析图

3、在链表尾部插入

链表尾部插入

4、链表的有序插入

链表有序插入

知识点五:链表查询某个节点

链表查询某个节点

知识点六:删除链表指定节点

删除链表指定节点

知识点七:链表的释放

链表的释放
STU* free_link(STU *head)
{
    //1、判断链表是否存在
    if(head == NULL)//不存在 
    {
        printf("link not found\n");
        retrun head;
    } 
    else	//存在 
    {
        STU *pb = head;
        //逐个节点释放
        while(pb != NULL)
        {
            //head保存下一个节点的位置
            head = pb->next;
            //释放pb指向的节点
            free(pb);
            //pb指向head
            pb = head; 
        }
        printf("链表已经释放完毕\n"); 
        return head;
    }
    return head;
}

知识点八:链表逆序

链表逆序
STU* reverse_link(STU *head)
{
    //1、判断链表是否存在
    if(head == NULL)//不存在 
    {
        printf("link not found\n");
        retrun head;
    } 
    else//存在 
    {
        //int *p,num;     //p为int *, num为int
        STU *pb,*pr;    //pb为STU *,pr 为STU *
        //pb保存head->next ( 原因head->next会置NULL)
        pb = head->next;
        //将head->next置NULL(原因:头节点变尾节点)
        head->next = NULL;
        while(pb != NULL)
        {
            //pr 保存pb->next ( 原因:pb->next会指向head)
            pr = pb -> next;
            //pb->next指向head ( 原因:逆转方向)
            pb->next = head ;
            //保存逆转方向的代码可以重复执行
            head = pb;
            pb = pr;
        }
        return head;
    }
    return head;
}

知识点九:链表排序

选择法排序:(以数组实现)

链表排序
#include<stdio.h>
int main()
{
    int arr[10] = {0};
    int n = sizeof(arr)/sizeof(arr[0]);
    int i = 0,j = 0,min = 0;
    printf("请输入%d个int数据\n", n);
    for(i = 0; i<n; i++)
    {
        scanf("%d",arr+i);
    }
    for(i = 0;i < n-1;i++)
    {
        for(min = i,j = min+1;j < n;j++)
        {
            if (arr[min] > arr[j])
            min = j;
        }
        if (min != i)
        {
            int tmp = 0;
            tmp = arr[i];
            arr[i] = arr[min];
            arr [min] = tmp;
        }
    }
    for(i = 0;i < n;i++) 
    {
        printf("%d ",arr[i]);
    }
    printf("\n");
    return 0;
}

选择法排序:(以链表实现)

链表排序1

知识点十:认识双向链表

双向链表

知识点十一:双链表插入

双链表插入

知识点十二:双向链表删除指定节点

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

知识点十三:结构的浅拷贝和深拷贝

1、指针变量作为结构体的成员

指针变量作为结构体的成员
typedef struct
{
    int num;
    char *name;//指针变量作为结构体的成员
}DATA;
void test01()
{
    DATA data = {100, "hehehehaha"};
    printf("%d\n",sizeof(DATA));//8字节
    printf("num = %d\n" ,data.num) ;
    //指针变量作为结构体的成员保存的是空间的地址
    printf("name = %s\n", data. name);
}

2、指针变量作为结构体的成员 操作前 必须有合法空间

指针变量作为结构体的成员1
void test02()
{
    DATA data;
    printf( "%d\n",sizeof(DATA));
    printf("num = %d\n", data.num) ;
    //指针变量作为结构体的成员操作前必须有合法的空间
    //data.name = "hehe" ;
    //给name事先申请一块堆区空间
    data.name = (char *)calloc(1,10);
    strcpy(data.name,"hahaha");
    printf("name = %s\n", data.name ) ;
    //如果name指向堆区空间一定要记得释放
    if(data. name != NULL )
    {
        free(data. name) ;
        data. name = NULL;
    }
}

3、指针变量作为结构体成员,结构体变量间的赋值操作容易导致“浅拷贝”发生

指针变量作为结构体的成员2

运行结果:出现段错误

两个结构体变量中的指针成员指向同-块堆区空间

void test03()
{
    DATA data1;
    DATA data2;
    data1.num = 100;
    data1.name = (char *)calloc(1,10);
    strcpy(data1.name,"my data");
    //指针变量作为结构体的成员结构体变量间的赋值操作容易导致"浅拷贝”发生
    data2 = data1;    //"浅拷贝”
    printf("data2: num = %d,name = %s\n", data2.num,data2.name); 
     if(datal.name != NULL)
    {
        free(data1.name);
        data1.name = NULL;
    }
    if( data2.name != NULL)
    {
        free(data2.name);
        data2.name = NULL;
    }
}

4、深拷贝

前提:是指针变量作为结构体的成员

两个结构体变量中的指针成员指向各自的堆区空间

深拷贝
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct
{
    int num;
    char *name;
} DATA;
void test01()
{
    DATA datal ;
    DATA data2 ;
    datal.num = 100;
    datal.name = (char *)calloc(1,12);
    strcpy (datal.name,"my data");
    data2. num = datal. num;
    //为结构体变量 申请 独立空间 
    data2.name = (char *)calloc(1,12);
    strcpy(data2.name,datal.name) ;
    printf("data1:num = %d,name = %s\n",datal.num,datal.name);
    printf("data2:num = %d,name = %s\n",data2.num,data2.name);
    if (datal.name!=NULL)
    {
        free(datal.name);
        datal.name = NULL;
    }
    if (data2.name!=NULL)
    {
        free(data2.name);
        data2.name = NULL;
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Python】使用pip安装seaborn sns及失败解决方法与sns.load_dataset(“tips“)

&#x1f60e; 作者介绍&#xff1a;我是程序员洲洲&#xff0c;一个热爱写作的非著名程序员。CSDN全栈优质领域创作者、华为云博客社区云享专家、阿里云博客社区专家博主。 &#x1f913; 同时欢迎大家关注其他专栏&#xff0c;我将分享Web前后端开发、人工智能、机器学习、深…

system 和 exec 的区别

在 linux 中&#xff0c;使用 system 和 exec 都可以执行一个程序或者执行一个命令。两者的区别如下&#xff1a; system 中创建了一个子进程&#xff0c;在子进程中执行用户的命令&#xff0c;子进程执行完毕之后&#xff0c;system 会返回。exec 不会创建子进程&#xff0c;…

pdf的压缩该怎么做?快速在线压缩pdf的方法

pdf文件是现在很常用的一种文件格式&#xff0c;有很多的文件内容都可以通过这种格式来展示内容&#xff0c;比如一些通知文件、设计图、个人信息等等&#xff0c;文件的内容越多就会越大&#xff0c;在使用的时候经常会受到一定的限制。那么有什么方法能够快速的将pdf文件变小…

计算机提示msvcp120.dll如何修复,7个不同方法分享

msvcp120.dll 是 Microsoft Visual C Redistributable 的一个关键组件&#xff0c;它包含了 C 运行时库&#xff0c;这些库对基于 Visual C 编写的应用程序至关重要。当应用程序运行时&#xff0c;msvcp120.dll 会被加载到内存中以提供必要的函数和类支持。 一、msvcp120.dll功…

详解python中的pandas.read_csv()函数

&#x1f60e; 作者介绍&#xff1a;我是程序员洲洲&#xff0c;一个热爱写作的非著名程序员。CSDN全栈优质领域创作者、华为云博客社区云享专家、阿里云博客社区专家博主。 &#x1f913; 同时欢迎大家关注其他专栏&#xff0c;我将分享Web前后端开发、人工智能、机器学习、深…

从GPU到ASIC,博通和Marvell成赢家

ASIC市场上&#xff0c;博通预计今年AI收入将达到110亿美元以上&#xff0c;主要来自与Google和Meta的合作&#xff1b;Marvell预计2028年AI收入将达到70亿至80亿美元&#xff0c;主要来自与Amazon和Google的合作。 随着芯片设计和系统复杂性的增加&#xff0c;科技大厂将更多地…

初阶 《函数》 2.C语言中函数的分类

2.C语言中函数的分类 1.库函数 2.自定义函数 2.1 库函数 为什么会有库函数&#xff1f; 1.我们知道在我们学习C语言编程的时候&#xff0c;总是在一个代码编写完成之后迫不及待的想知道结果&#xff0c;想把这个结果打印到我们的屏幕上看看。这个时候我们会频繁的使用一个功能…

排序-快排算法对数组进行排序

目录 一、问题描述 二、解题思路 1.初始化 2.将右侧小于基准元素移到左边 3.将左侧大于基准元素移到右边 4.重复执行上面的操作 5.对分好的左、右分区再次执行分区操作 6.最终排序结果 三、代码实现 四、刷题链接 一、问题描述 二、解题思路 快排算法实现数组排序&am…

配置 JDK 和 Android SDK

目录 一、配置JDK 1. 安装 JDK 2. JDK 环境配置 3. JDK的配置验证 二、配置 adb 和Android SDK环境 1、下载 2、配置 Android SDK 环境 一、配置JDK 1. 安装 JDK 安装链接&#xff1a;Java Downloads | Oracle 我安装的是 .zip &#xff0c;直接在指定的文件夹下解压就…

产品创新:驱动企业增长的核心动力

在当今快速变化的市场环境中&#xff0c;产品创新已成为企业生存和发展的关键。产品创新不仅涉及全新产品或服务的开发&#xff0c;也包括对现有产品或服务的持续改进和优化。本文将深入探讨产品创新的定义、重要性以及如何通过创新驱动企业增长&#xff0c;并结合实际案例进行…

Redis系列之淘汰策略介绍

Redis系列之淘汰策略介绍 文章目录 为什么需要Redis淘汰策略&#xff1f;Redis淘汰策略分类Redis数据淘汰流程源码验证淘汰流程Redis中的LRU算法Redis中的LFU算法 为什么需要Redis淘汰策略&#xff1f; 由于Redis内存是有大小的&#xff0c;当内存快满的时候&#xff0c;又没有…

IO进程线程(十一)进程间通信 消息队列

文章目录 一、IPC(Inter-Process Communication)进程间通信相关命令 &#xff1a;&#xff08;一&#xff09;ipcs --- 查看IPC对象&#xff08;二&#xff09;获取IPC键值&#xff08;三&#xff09;删除IPC对象的命令&#xff08;四&#xff09;获取IPC键值的函数1. 函数定义…

13 RTP包的使用

RTP RTP包最主要的就是Sequence number。 对于发送者来说&#xff0c;视频的每一个帧都有很多包组成。对于接收端来接收的时候是有一个队列进行接收的。这个队列大小都是通过计算的。有了队列之后就会不断的往队列中插入数据。当队列中有的数据超时一直组不成包的时候&#xf…

k8s离线部署Calico网络(2续)

下载离线镜像 百度网盘 链接&#xff1a;https://pan.baidu.com/s/14ReJW-ZyYZFLbwSEBZK6mA?pwdi6ct 提取码&#xff1a;i6ct 1.将离线镜像上传至所有服务器并解压&#xff1a; [rootmaster ~]# tar xf calico.tar.gz [rootmaster ~]# cd calico 2.所有服务器使用for循环导入…

【微服务】springcloud-alibaba 配置多环境管理使用详解

目录 一、前言 二、配置多环境问题概述 2.1 什么是微服务多环境配置管理 2.1.1 微服务多环境配置管理问题起源 2.2 为什么要做多环境配置管理 2.3 微服务多环境配置管理解决方案 三、springboot 配置多环境管理解决方案 3.1 前置准备 3.1.1 搭建一个springboot工程 3.…

IO流(转换流)

InputStreamReader&#xff08;字符输入转换流 &#xff09; 解决不同编码时&#xff0c;字符流读取文本内容乱码的问题 public static void main(String[] args) {try (//1.得到文件的原始字节流(GBK的字节流形式)FileInputStream is new FileInputStream("src/666.tx…

前端实现点击图片放大查看,并点击关闭

效果展示 HTML 代码 HTML代码比较简单&#xff0c;包含了一个img元素&#xff0c;用显示原有图片&#xff0c;和一个模态框元素div&#xff0c;用于显示放大之后的图片元素&#xff0c;模拟模态框的样式 <!DOCTYPE html> <html lang"en"> <head>…

Vue3全局封装dialog弹框

Vue3全局封装modal弹框使用&#xff1a; 应用场景&#xff1a;全局动态form表单弹框 应用Vue3碎片&#xff1a; ref&#xff0c;reactive&#xff0c;app.component&#xff0c;defineExpose&#xff0c;defineProps&#xff0c;defineEmits 应用UI: element-plus dialog form …

MySQL系列-安装配置使用说明(MAC版本)

1、前言 本文将介绍MySQL的安装配置以及基本语法操作说明 环境&#xff1a;mac 版本&#xff1a;MySQL 8.0.28 之前电脑安装卸载过&#xff0c;后面在装的时候遇到一些问题&#xff0c;用了四五天才解决&#xff0c;主要是参考 https://blog.csdn.net/zz00008888/article/deta…

动态内存管理(malloc,calloc,realloc,free)+经典笔试题

动态内存管理 一. malloc 和 free1. malloc2. free 二. calloc三. realloc四.动态内存的错误1.对NULL指针的解引用操作2.对动态开辟空间的越界访问3.对非动态开辟内存使用free释放4.使用free释放一块动态开辟内存的一部分5.对同一块动态内存多次释放6.动态开辟内存忘记释放&…