数据结构:链表

目录

一.为什么要使用链表存储数据?

二.链表的分类

单向或者双向链表:

带头或者不带头:

循环或者非循环:

三.链表的实现

3.1无头单向非循环链表的实现:

3.1.1单向无头非循环链表的声明

3.1.2动态申请一个节点

 3.1.3单链表打印

  3.1.4单链表尾插

   3.1.5单链表的头插

   3.1.6单链表的尾删

   3.1.7单链表头删

   3.1.8单链表查找

  3.1.9单链表在pos位置之前插入x

 3.1.10单链表在pos位置之后插入x

  3.1.11单链表删除pos之后的值

 3.1.12单链表删除pos位置的值

3.1.13销毁单链表

 头文件:

 测试文件:

3.2带头双向循环链表的实现

3.2.1带头双向循环链表的声明

3.2.2动态申请一个节点

 3.2.3哨兵位初始化(创建链表的头结点)

 3.2.4带头双向循环链表打印

 3.2.5双向链表尾插

  3.2.6双向链表头插

3.2.7双线链表尾删

3.2.8双线链表头删

3.2.9双向链表查找

 3.2.10双向链表在pos的前面进行插入

3.2.11双向链表删除pos位置的结点

 3.2.12双向链表销毁

头文件:

测试文件:

四.链表总结


一.为什么要使用链表存储数据?

内存空间是所有程序的公共资源,在一个复杂的系统运行环境下,空闲的内存空间可能散落在内存各处。我们知道,存储数组的内存空间必须是连续的,而当数组非常大时,内存可能无法提供如此大的连续空间。此时链表的灵活性优势就体现出来了。

让我们来看看链表的结构:

  •  可以得出:链表是一种物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的 。
  • 上述图中的链表知识链表中的其中一种

二.链表的分类

单向或者双向链表:

带头或者不带头:

循环或者非循环:


虽然链表的种类很多,但我们主要使用的还是无头单向非循环链表(OJ题中最常见的链表)和带头循环双向链表(实践应用)

三.链表的实现

3.1无头单向非循环链表的实现:

对于项目我们需要区分测试文件和接口文件,这样做有利于培养良好的代码能力。

3.1.1单向无头非循环链表的声明

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>typedef int SLNDataType;// 声明一个  Single Link List Node (单向无头链表)typedef struct SLLN
{//节点值SLNDataType val;//指向下一个节点的指针struct SLLN* next;}SLNode;

3.1.2动态申请一个节点

// 动态申请一个节点
SLNode* CreateNode(SLNDataType x)
{SLNode* newnode = (SLNode*)calloc(1, sizeof(SLNode));if (newnode == NULL){perror("calloc");//直接终止程序exit(-1);}newnode->val = x;newnode->next = NULL;return newnode;
}

 3.1.3单链表打印

// 单链表打印
void SLNodePrint(SLNode* plist)
{SLNode* cur = plist;if (cur != NULL){while (cur){printf("%d->", cur->val);cur = cur->next;}printf("NULL");printf("\n");}else{printf("链表为空无需打印\n");}
}

  3.1.4单链表尾插

// 单链表尾插
void SLNodePushBack(SLNode** pplist, SLNDataType x)
{//先创造一个新节点SLNode* newnode = CreateNode(x);SLNode* tail = *pplist;//将plist赋值给tail//找尾if (*pplist == NULL){*pplist = newnode;}else{while (tail->next != NULL){tail = tail->next;}tail->next = newnode;}
}

   3.1.5单链表的头插

// 单链表的头插
void SLNodePushFront(SLNode** pplist, SLNDataType x)
{//先创建一个新节点SLNode* newnode = CreateNode(x);newnode->next = *pplist;*pplist = newnode;
}

   3.1.6单链表的尾删

// 单链表的尾删
void SLNodePopBack(SLNode** pplist)
{//如果链表为空则不能删除,报错assert(*pplist);//找尾SLNode* tail = *pplist;//tail移动时我们还需要有一个前驱指针 prev 跟在tail后面SLNode* prev = NULL;//单链表只有一个节点情况下尾删if (tail->next == NULL){free(*pplist);*pplist = NULL;}//单链表有多个节点情况下尾删else{while (tail->next != NULL){prev = tail;tail = tail->next;}free(tail);tail = NULL;prev->next = NULL;}}

   3.1.7单链表头删

// 单链表头删
void SLNodePopFront(SLNode** pplist)
{//当链表为空时不能删除,报错assert(*pplist);SLNode* cur = *pplist;SLNode* newplist = (*pplist)->next;free(cur);cur = NULL;*pplist = newplist;}

   3.1.8单链表查找

// 单链表查找(配合在pos位置插入或者删除使用)
SLNode* SLNodeFind(SLNode* plist, SLNDataType x)
{while (plist != NULL){if (plist->val == x){return plist;}else{plist = plist->next;}}return NULL;
}

  3.1.9单链表在pos位置之前插入x

//单链表在pos位置之前插入x
void SLNodeInsertBefore(SLNode** pplist, SLNode* pos, SLNDataType x)//此处传入二级指针pplist是为了在头插时改变plist的值,传址调用
{//此处需要对哪个指针进行断言检查呢?assert(pos && *pplist);//防止人为乱传空SLNode* cur = *pplist;SLNode* prev = NULL;//前驱指针prev保存cur前一个节点的地址if (pos == *pplist){//在头节点位置前插入x实质上就是头插,我们调用之前写的头插函数即可SLNodePushFront(pplist, x);}else{SLNode* newnode = CreateNode(x);while (cur != pos){prev = cur;cur = cur->next;}prev->next = newnode;newnode->next = cur;}
}

 3.1.10单链表在pos位置之后插入x

// 单链表在pos位置之后插入x
void SLNodeInsertAfter(SLNode* pos, SLNDataType x)
{//链表为空无法在pos位置之后插入xassert(pos);SLNode* newnode = CreateNode(x);if (newnode == NULL){perror(calloc);return;}SLNode* next = pos->next;pos->next = newnode;newnode->next = next;}

  3.1.11单链表删除pos之后的值

//单链表删除pos之后的值
void SLNodeEraseAfter(SLNode* pos)
{//链表为空无法删除assert(pos);//当链表只剩下一个节点或者pos后面无节点时也无法删除assert(pos->next);SLNode* del = pos->next;pos->next = pos->next->next;free(del);del == NULL;
}

 3.1.12单链表删除pos位置的值

//单链表删除pos位置的值
void SLNodeErasepos(SLNode** pplist, SLNode* pos)
{//链表为空不能删除assert(*pplist);SLNode* cur = *pplist;SLNode* prev = NULL;//前驱指针prev保存cur前一个节点的地址if (pos != *pplist){while (cur != pos){prev = cur;cur = cur->next;}SLNode* next = cur->next;free(cur);cur = NULL;//链接两个节点prev->next = next;}else{SLNode* next = cur->next;free(cur);cur = NULL;//更新头节点*pplist = next;}
}

3.1.13销毁单链表

//销毁链表
void SLNodeDestory(SLNode** pplist)
{assert(pplist);assert(*pplist);SLNode* cur = *pplist;while (cur){SLNode* next = cur->next;free(cur);cur = next;}*pplist = NULL;
}

以上代码为单链表所实现的所有功能(接口)


 头文件:

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>typedef int SLNDataType;// 声明一个  Single Link List Node (单向无头链表)typedef struct SLLN
{//节点值SLNDataType val;//指向下一个节点的指针struct SLLN* next;}SLNode;// 动态申请一个节点
SLNode* CreateNode(SLNDataType x);// 单链表打印
void SLNodePrint(SLNode* plist);// 单链表尾插
void SLNodePushBack(SLNode** pplist, SLNDataType x);// 单链表的头插
void SLNodePushFront(SLNode** pplist, SLNDataType x);// 单链表的尾删
void SLNodePopBack(SLNode** pplist);// 单链表头删
void SLNodePopFront(SLNode** pplist);// 单链表查找
SLNode* SLNodeFind(SLNode* plist, SLNDataType x);//单链表在pos位置之前插入x
void SLNodeInsertBefore(SLNode** pplist, SLNode* pos, SLNDataType x);//单链表在pos位置之后插入x
void SLNodeInsertAfter(SLNode* pos, SLNDataType x);//单链表删除pos位置之后的值
void SLNodeEraseAfter(SLNode* pos);//单链表删除pos位置的值
void SLNodeErasepos(SLNode** pplist, SLNode* pos);//销毁单链表
void SLNodeDestory(SLNode** pplist);

 测试文件:

#define  _CRT_SECURE_NO_WARNINGS 1
#include"Single_linked_lists.h"//单链表尾插测试
void text1()
{SLNode* plist = NULL;SLNodePushBack(&plist, 1);SLNodePushBack(&plist, 2);SLNodePushBack(&plist, 3);SLNodePushBack(&plist, 4);SLNodePrint(plist);
}
//单向链表头插测试
void text2()
{SLNode* plist = NULL;SLNodePushFront(&plist, 1);SLNodePushFront(&plist, 2);SLNodePushFront(&plist, 3);SLNodePushFront(&plist, 4);SLNodePrint(plist);}
//单向链表尾删测试
void text3()
{//SLNode* plist = NULL;//SLNodePushBack(&plist, 1);//SLNodePushBack(&plist, 2);//SLNodePushBack(&plist, 3);//SLNodePushBack(&plist, 4);多节点尾删测试//SLNodePopBack(&plist);SLNode* plist = NULL;SLNodePushBack(&plist, 1);//单节点尾删测试SLNodePopBack(&plist);SLNodePrint(plist);
}
//单向链表头删测试
void text4()
{SLNode* plist = NULL;SLNodePushBack(&plist, 1);SLNodePushBack(&plist, 2);SLNodePushBack(&plist, 3);SLNodePushBack(&plist, 4);//头删测试SLNodePopFront(&plist);SLNodePrint(plist);
}//单向链表查找 val 测试
void text5()
{SLNode* plist = NULL;SLNodePushBack(&plist, 1);SLNodePushBack(&plist, 2);SLNodePushBack(&plist, 3);SLNodePushBack(&plist, 4);//查找val测试SLNode* pos = SLNodeFind(plist, 4);printf("%p\n", pos);
}// 单链表在pos位置之后插入 x 测试
void text6()
{SLNode* plist = NULL;SLNodePushBack(&plist, 1);SLNodePushBack(&plist, 2);SLNodePushBack(&plist, 3);SLNodePushBack(&plist, 4);//pos之后插入xSLNode* pos = SLNodeFind(plist, 3);SLNodeInsertAfter(pos, 0);SLNodePrint(plist);
}//单链表删除pos之后的值测试
void text7()
{SLNode* plist = NULL;SLNodePushBack(&plist, 1);SLNodePushBack(&plist, 2);SLNodePushBack(&plist, 3);SLNodePushBack(&plist, 4);//单链表删除pos之后的值测试SLNode* pos = SLNodeFind(plist, 3);SLNodeEraseAfter(pos);SLNodePrint(plist);}
//单链表在pos前一个位置插入 x 测试
void text8()
{SLNode* plist = NULL;SLNodePushBack(&plist, 1);SLNodePushBack(&plist, 2);SLNodePushBack(&plist, 3);SLNodePushBack(&plist, 4);SLNodePrint(plist);SLNode* posbefore = SLNodeFind(plist, 3);//单链表在pos前一个位置插入 x 测试SLNodeInsertBefore(&plist, posbefore, 0);SLNodePrint(plist);}
//单链表删除pos位置的值
void text9()
{SLNode* plist = NULL;SLNodePushBack(&plist, 1);SLNodePushBack(&plist, 2);SLNodePushBack(&plist, 3);SLNodePushBack(&plist, 4);SLNodePrint(plist);//单链表删除pos位置的值SLNode* pos1 = SLNodeFind(plist, 1);SLNode* pos2 = SLNodeFind(plist, 3);SLNodeErasepos(&plist, pos1);SLNodeErasepos(&plist, pos2);SLNodePrint(plist);}
int main()
{//text1();//单链表尾插测试//text2();//单向链表头插测试//text3();//单向链表尾删测试//text4();//单向链表头删测试//text5();//单向链表查找 val 测试//text6();// 单链表在pos位置之后插入 x 测试//text7();//单链表删除pos之后的值测试//text8();//单链表在pos前一个位置插入 x 测试//text9();//单链表删除pos位置的值测试return 0;
}

3.2带头双向循环链表的实现

3.2.1带头双向循环链表的声明

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>typedef int DataType;typedef struct ListNode
{DataType val;struct LTNode* next;struct LTNode* prev;
}LTNode;

3.2.2动态申请一个节点

//Create one newnode
LTNode* Createnode(DataType x)
{LTNode* newnode = (LTNode*)malloc(sizeof(LTNode));if (newnode == NULL){perror("malloc");exit(-1);}newnode->val = x;newnode->next = NULL;newnode->prev = NULL;return newnode;
}

 3.2.3哨兵位初始化(创建链表的头结点)

//哨兵位初始化(创建链表的头结点)
LTNode* LTInit()
{LTNode* plist = Createnode(-1);plist->next = plist;plist->prev = plist;return plist;
}

 3.2.4带头双向循环链表打印

//带头双向循环链表打印
void LTPrint(LTNode* plist)
{assert(plist);LTNode* cur = plist->next;printf("哨兵位<=>");while (cur != plist){printf("%d<=>", cur->val);cur = cur->next;}printf("\n");
}

 3.2.5双向链表尾插

// 双向链表尾插
void LTNodePushBack(LTNode* plist, DataType x)
{LTNode* newnode = Createnode(x);LTNode* tail = plist->prev;tail->next = newnode;newnode->prev = tail;plist->prev = newnode;newnode->next = plist;}

  3.2.6双向链表头插

// 双向链表头插
void LTNodePushFront(LTNode* plist, DataType x)
{assert(plist);LTNode* first = plist->next;LTNode* newnode = Createnode(x);newnode->next = first;first->prev = newnode;plist->next = newnode;newnode->prev = plist;}

3.2.7双线链表尾删

// 双向链表尾删
void LTNodePopBack(LTNode* plist)
{//防止链表不存在assert(plist);//防止链表为空assert(plist->next);LTNode* tail = plist->prev;plist->prev = tail->prev;LTNode* tailprev = tail->prev;tailprev->next = plist;
}

3.2.8双线链表头删

// 双向链表头删
void LTNodePopFront(LTNode* plist)
{//防止链表不存在assert(plist);//防止链表为空assert(plist->next);LTNode* first = plist->next;LTNode* second = first->next;plist->next = second;second->prev = plist;free(first);first = NULL;}

3.2.9双向链表查找

// 双向链表查找
LTNode* LTNodeFind(LTNode* plist, DataType x)
{//防止链表不存在assert(plist);//防止链表为空assert(plist->next);LTNode* cur = plist->next;while (cur != plist){if (cur->val == x){return cur;}cur = cur->next;}return NULL;
}

 3.2.10双向链表在pos的前面进行插入

// 双向链表在pos的前面进行插入
void LTNodeInsert(LTNode* pos, DataType x)
{assert(pos);LTNode* newnode = Createnode(x);LTNode* posprev = pos->prev;posprev->next = newnode;newnode->next = pos;pos->prev = newnode;newnode->prev = posprev;
}

3.2.11双向链表删除pos位置的结点

// 双向链表删除pos位置的结点
void LTNodeErase(LTNode* pos)
{//防止传空assert(pos);LTNode* posnext = pos->next;LTNode* posprev = pos->prev;posprev->next = posnext;posnext->prev = posprev;free(pos);
}

 3.2.12双向链表销毁

// 双向链表销毁
void LTNodeDestory(LTNode* plist)
{//防止链表不存在assert(plist);LTNode* cur = plist->next;while (cur != plist){LTNode* next = cur->next;free(cur);cur = next;}free(plist);plist = NULL;
}

以上代码为单链表所实现的所有功能(接口)


头文件:

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>typedef int DataType;typedef struct ListNode
{DataType val;struct LTNode* next;struct LTNode* prev;
}LTNode;//生成新节点
LTNode* Createnode(DataType x);//哨兵位初始化
LTNode* LTInit();//带头双向循环链表打印
void LTPrint(LTNode* plist);// 双向链表销毁
void LTNodeDestory(LTNode* plist);// 双向链表尾插
void LTNodePushBack(LTNode* plist, DataType x);// 双向链表尾删
void LTNodePopBack(LTNode* plist);// 双向链表头插
void LTNodePushFront(LTNode* plist, DataType x);// 双向链表头删
void LTNodePopFront(LTNode* plist);// 双向链表查找
LTNode* LTNodeFind(LTNode* plist, DataType x);// 双向链表在pos的前面进行插入
void LTNodeInsert(LTNode* pos, DataType x);// 双向链表删除pos位置的结点
void LTNodeErase(LTNode* pos);

测试文件:

#define  _CRT_SECURE_NO_WARNINGS 1
#include"list.h"
// 初步测试
void test1()
{// 创建一个哨兵位头节点LTNode* plist = LTInit();LTPrint(plist);
}// 尾插尾删测试
void test2()
{LTNode* plist = LTInit();LTNodePushBack(plist, 1);LTNodePushBack(plist, 2);LTNodePushBack(plist, 3);LTNodePushBack(plist, 4);LTNodePushBack(plist, 5);LTPrint(plist);LTNodePopBack(plist);LTPrint(plist);
}
// 头插头删测试
void test3()
{LTNode* plist = LTInit();LTNodePushFront(plist, 1);LTNodePushFront(plist, 2);LTNodePushFront(plist, 3);LTNodePushFront(plist, 4);LTNodePushFront(plist, 5);LTPrint(plist);LTNodePopFront(plist);LTPrint(plist);
}
// 链表查找测试
void test4()
{LTNode* plist = LTInit();LTNodePushBack(plist, 1);LTNodePushBack(plist, 2);LTNodePushBack(plist, 3);LTNodePushBack(plist, 4);LTNodePushBack(plist, 5);LTPrint(plist);LTNode* pos = LTNodeFind(plist, 3);printf("%d\n", pos->val);}
// 双向链表在pos的前面进行插入测试
void test5()
{LTNode* plist = LTInit();LTNodePushBack(plist, 1);LTNodePushBack(plist, 2);LTNodePushBack(plist, 3);LTNodePushBack(plist, 4);LTNodePushBack(plist, 5);LTPrint(plist);LTNode* pos = LTNodeFind(plist, 3);LTNodeInsert(pos, 100);LTNodeInsert(pos, 200);LTPrint(plist);}
// 双向链表删除pos位置的结点测试
void test6()
{LTNode* plist = LTInit();LTNodePushBack(plist, 1);LTNodePushBack(plist, 2);LTNodePushBack(plist, 3);LTNodePushBack(plist, 4);LTNodePushBack(plist, 5);LTPrint(plist);LTNode* pos = LTNodeFind(plist, 3);LTNodeErase(pos);LTPrint(plist);
}
// 链表销毁测试
void test7()
{LTNode* plist = LTInit();LTNodePushBack(plist, 1);LTNodePushBack(plist, 2);LTNodePushBack(plist, 3);LTNodePushBack(plist, 4);LTNodePushBack(plist, 5);LTNodeDestory(plist);plist = NULL;LTPrint(plist);
}
int main()
{// 初步测试test1();// 尾插尾删测试test2();// 头插头删测试test3();// 链表查找测试test4();// 双向链表在pos的前面进行插入测试test5();// 双向链表删除pos位置的结点测试test6();// 链表销毁测试//test7();return 0;
}

四.链表总结

这是一个我个人做的思维导图,对于学习链表的一些总结,希望对你有所帮助:

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

二叉树的顺序结构及实现

目录 1 二叉树的顺序结构2. 堆的概念及结构3 .堆的实现(小堆) 1 二叉树的顺序结构 普通的二叉树是不适合用数组来存储的&#xff0c;因为可能会存在大量的空间浪费。而完全二叉树更适合使用顺序结构存储。现实中我们通常把堆(一种二叉树)使用顺序结构的数组来存储&#xff0c;…

思维模型 潘多拉效应

本系列文章 主要是 分享 思维模型 &#xff0c;涉及各个领域&#xff0c;重在提升认知。越是禁止&#xff0c;越是好奇。 1 潘多拉效应的应用 1.1 潘多拉效应在管理中的应用 通用电气公司曾经推出了一项名为“六西格玛”的管理方法&#xff0c;该方法旨在通过优化业务流程和提…

LangChain的简单使用介绍

❤️觉得内容不错的话&#xff0c;欢迎点赞收藏加关注&#x1f60a;&#x1f60a;&#x1f60a;&#xff0c;后续会继续输入更多优质内容❤️ &#x1f449;有问题欢迎大家加关注私戳或者评论&#xff08;包括但不限于NLP算法相关&#xff0c;linux学习相关&#xff0c;读研读博…

Shell循环:for(一)

语法结构&#xff1a; for 变量名 [ in 取值列表] do 循环体 done 示例1&#xff1a; 1、需求&#xff1a;自动循环创建10个用户 2、演示&#xff1a; [rootlocalhost ~]# vim for.sh #脚本编写 #!/bin/bash for i in {1..10} do useradd "user$…

图神经网络的数学原理总结

图深度学习(Graph Deep Learning) 多年来一直在加速发展。许多现实生活问题使GDL成为万能工具&#xff1a;在社交媒体、药物发现、芯片植入、预测、生物信息学等方面都显示出了很大的前景。 本文将流行的图神经网络及其数学细微差别的进行详细的梳理和解释&#xff0c;图深度学…

Chrome 访问不了项目?10080端口 ERR_UNSAFE_PORT:问题原因 / 解决方案

文章目录 被禁用端口列表解决方法方法一、更换端口 / 使用代理 / 使用域名方法二、对浏览器下手WindowsMac 最近有客户反馈&#xff0c;在chrome浏览器中访问不了项目&#xff0c;其他浏览器都是正常的。 &#xff1f;奇了怪了&#xff0c;难道客户对chrome做了什么操作&#x…

java飞翔的鸟

一.准备工作 首先创建一个新的Java项目命名为“飞翔的鸟”&#xff0c;并在src中创建一个包命名为“com.qiku.bird"&#xff0c;在这个包内分别创建4个类命名为“Bird”、“BirdGame”、“Column”、“Ground”&#xff0c;并向需要的图片素材导入到包内。 二.代码呈现 p…

itext - PDF模板套打

目录 环境配置 快速使用 代码实现 添加图片 封装 项目需求&#xff1a;获取列表数据之后直接将数据生成一个pdf。因此需要使用到 itext 对pdf进行直接操作。 环境配置 需要为pdf添加文字域&#xff0c;因此需要安装Adobe Acrobat 准备一个空的PDF文件&#xff0c;如果有现…

如何为您的企业选择合适的多因素认证?

在传统的网络安全架构中&#xff0c;重点在于防止非法入侵&#xff0c;例如防火墙、VPN 、堡垒机等安全设备的重心都在于防止用户违规访问企业资源&#xff0c;一旦合法用户的账号密码被入侵者拿到&#xff0c;就可以冒充合法用户访问企业资源&#xff0c;所有的安全设备形同虚…

解决:ImportError: cannot import name ‘Adam‘ from ‘keras.optimizers‘

解决&#xff1a;ImportError: cannot import name ‘Adam‘ from ‘keras.optimizers‘ 背景 在使用之前的代码时&#xff0c;报错&#xff1a; from keras.optimizers import Adam ImportError: cannot import name ‘Adam’ 报错问题 from keras.optimizers import Adam I…

微机原理_2

一、单项选择题(本大题共15小题,每小题3分,共45分。在每小题给出的四个备选项中,选出一个正确的答案&#xff0c;请将选定的答案填涂在答题纸的相应位置上。&#xff09; 下列数中最大的数为&#xff08;&#xff09; A. 10010101B B. (126)8 C. 96H D. 100 CPU 执行 OUT 60H,…

vue一个页面左边是el-table表格 当点击每条数据时可以在右边界面编辑表格参数,右边保存更新左边表格数据

实现思路&#xff1a; 1.点击当前行通过row拿到当前行数据。 2.将当前行数据传给子组件。 3.子组件监听父组件传过来的数据并映射在界面。 4.点击保存将修改的值传给父组件更新表格。 5.父组件收到修改过后的值&#xff0c;可以通过字段判断比如id&#xff0c;通过 findIn…