电子发烧友App

硬声App

扫码添加小助手

加入工程师交流群

0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

电子发烧友网>嵌入式技术>了解Linux通用的双向循环链表

了解Linux通用的双向循环链表

收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

评论

查看更多

相关推荐
热点推荐

链表结点的数据结构该如何定义

当用户需要使用链表管理数据时,仅需关联数据和链表结点,最简单的方式是将数据和链表结点打包在一起。
2017-09-20 16:28:4115631

周立功阐释高效的双向链表如何用

实际上循环链表,无论是头结点、尾结点还是普通结点,其本质上都是一样的。
2017-09-25 14:14:106875

C语言-链表(单向链表双向链表)

在前面章节已经学习了数组的使用,数组的空间是连续空间,数组的大小恒定的,在很多动态数据存储的应用场景下,使用不方便;而这篇文章介绍的链表结构,支持动态增加节点,释放节点,比较适合存储动态数据的应用场景,而且链表的空间是存储在堆上面的,可以动态分配,释放
2022-09-09 11:30:142373

Linux+C语言】你真的了解system接口的调用吗?

Linux + C语言】话说,你真的了解system接口的调用吗?
2022-09-12 16:33:385356

Linux高级编译】list.h的高效应用—单向链表的实现

Linux高级编译】Linux内核的list.h的高效应用——单向链表的实现
2022-09-12 09:33:003061

Linux高级编译】list.h的高效应用—双向链表的实现

Linux高级编译】Linux内核的list.h的高效应用——双向链表的实现
2022-09-15 10:00:433444

重新排列一个单链表

这道题目很考察基本功和观察能力,最终的结果就是将原链表的前半部分和原链表的后半部分反转之后的链表进行合并得到的。
2022-10-10 09:39:361631

一文搞懂Linux内核链表

hello 大家好,今天给大家介绍一下linux 内核链表的分析,在写这篇文章前,笔者自己以前也只是停留在应用层面,没有深究其中的细节,很多也是理解的不是很透彻。写完此文后,发现对链表的理解更加深刻了。很多现代计算机的思想在内核里面都有体现。
2022-11-14 09:17:111367

一文了解Linux安全模块(LSM)

我猜,你读这篇文章,说明你已经对Linux安全模块(LSM)有所了解。如果你使用过SELinux或AppArmor,其实就已经用过LSM了。甚至,在你使用的Linux发行版本或Android系统之上,也使用了LSM。
2022-11-28 09:21:419044

C语言实现动态链表的建立

上期讲解了静态链表的实例,但是静态链表建立的节点数量有限,毕竟是手工建立,难免也会出问题, 所以这期讲讲怎么使用动态的方式建立链表,也就是 动态链表
2023-01-13 15:16:021873

讲解链表的删除、修改以及插入

上期介绍了动态链表怎么建立,以及使用循环的方式怎么输出整个链表中各个节点的数据,这期主要讲解 链表的删除、修改以及插入 !
2023-01-13 15:25:523568

一文全面了解linux相关知识

今天浩道跟大家分享linux实用场景相关的实例,助你全面了解linux相关知识。
2023-01-29 11:09:09885

数据结构中最简单的链表

数据结构作为嵌入式工程师必修课程之一,今天,我们就来讲一讲数据结构中最简单的链表,包含链表的初始化、插入和遍历操作。 链表在项目开发中使用的场景很多,跟数组相比,它的优点就是,容量没有限制,插入删除效率比较高。
2023-06-13 17:40:58664

如何判断链表是否有环

如何判断链表是否有环?
2023-08-10 17:07:191149

C语言链表知识点(2)

C语言链表知识点(2)
2023-08-22 10:38:35565

数据结构:单链表的排序

给定一个单链表的头结点head(该结点有值),长度为n的无序单链表,对其按升序排序后,返回新链表。如当输入链表 {3,1,4,5,2} 时,经升序排列后,原链表变为 {1,2,3,4,5},对应的输出为 {1,2,3,4,5}。
2023-11-30 13:56:392248

数据结构:删除有序链表的重复节点

给定一个有序单链表(从小到大有序)的头结点head(该结点有值),删除链表中的重复元素,使链表中的所有元素都只出现一次。如当输入 {1,1,2} 时,经删除后,原链表变为 {1,2},对应的输出为 {1,2}。
2023-12-05 15:46:341655

Linux Kernel数据结构:链表

Linux Kernel数据结构:链表原创 2016年10月20日 22:58:25标签:LINUX/kernel/链表 数据结构数据结构中链表是 节点中包含数据 , kernel中的链表链表包含
2018-09-25 16:41:11

Linux Shell系列教程之Shell until循环

表达式,如果返回值为 false,则继续执行循环体内的语句,否则跳出循环。  Shell until循环使用举例  还是老规矩,通过例子来深入了解下Shell until循环。  例子1
2018-09-04 16:02:25

Linux内核链表详讲(1)

大家好,是不是对linux内核很感兴趣,有人是不是在跟着市面的教程,不管是收费的还是免费的,或多或少为大家讲下内核链表分析,不知道有多少人真的在本质上给您有讲.今天狄泰唐老师为你们免费讲解,总共分3
2017-07-10 18:23:35

Linux内核中的数据结构的一点认识

/linux/list.h头文件,就可以看到内核中声明的一些与链表操作相关的结构体定义和函数接口。内核中使用更多的是双向循环链表。我们就看一看内核中双向循环链表的精妙之处吧。首先看链表节点的结构体
2022-04-20 16:42:25

Linux内核的链表操作

的特点是尾节点的后继指向首节点。前面已经给出了双循环链表的示意图,它的特点是从任意一个节点出发,沿两个方向的任何一个,都能找到链表中的任意一个数据。如果去掉前驱指针,就是单循环链表。在Linux内核中使用了
2017-08-29 11:13:00

Linux基础

一:嵌入式c语言:Linux基础  Linux操作系统的概念、安装方法,详细了解Linux下的目录结构、基本命令、编辑器VI ,编译器GCC,调试器GDB和 Make 项目管理工具, Shell
2017-08-03 09:46:54

Linux平台上如何进行通用计算并行优化

Linux平台上如何进行通用计算并行优化
2021-03-12 07:43:40

linux循环定时任务

linux循环定时任务
2020-05-20 14:59:46

C语言链表的学习

链表有有头链表和无头链表无头链表:所有的节点都包含了有效数据。有头链表:用一个固定的头节点来指代整个链表,所有的对象挂在这个头节点下面,而头节点本身不包含有效数据。今天学习在有头链表下插入节点,插入
2016-08-21 13:12:52

C语言玩转链表

C语言是必学的一个课程,不管你是单片机还是嵌入式物联网,都是基础,所以还是要好好学习的今天推荐的资料是关于C语言链表的资料我自己看了一下主要说的内容是快速认识数据结构,重点讲解链表,掌握学习其他数据结构的方法
2018-11-13 13:50:05

Mini Linux

Mini Linux EMMC
2023-03-28 13:06:25

RT-Thread中侵入式链表的应用有哪些呢

*/struct LNode pre;/ 指向下一个结点 */struct LNode next;/ 指向上一个结点 */}侵入式链表在 RT-Thread 以及 Linux 内核中链表是这样定义
2022-12-05 13:59:32

RT-Thread内核中双链表的使用与实现

不能随机访问数据,只能遍历。双链表:由一个个节点(node)组成,每个节点都有指向下一个节点的指针,每个节点都有一个指向上一个节点的指针。所以节点的连接方向是双向的,节点之间用指针连起来,所有结构体型
2022-04-01 12:05:25

Raw os 内核链表

Raw os 的基础链表双向循环链表,这样的好处是插到尾部速度非常快,有些传统的os 采用了单个指针头的双向链表,虽然这样省了4个字节指针,但是算法复杂了,插入到尾部时间不确定,意义不大。Raw
2013-02-27 14:00:09

【HarmonyOS】双向循环链表

了一个个双向循环链表,把指针的高效能运用到了极致,这也许就是编程的艺术吧!致敬鸿蒙内核开发者贡献了如此优秀的源码,鸿蒙内核源码可作为大学C语言,操作系统,数据结构三门课的教学项目
2020-10-20 15:39:05

什么是链表?怎样使用链表作为队列管理电路

一元素,代码如下。对于这一场景,也可以考虑使用逆向链表,释放逻辑就跟上面的head释放是类似的了,但添加元素会有所区别。插入一个问题,存在双向链表的数据结构,但从硬件来看,其实没有必要,或者说硬件链表
2022-08-29 14:26:51

链表的缺陷是什么

链表有一定的缺陷,就是单向性,只能从一个结点到下一个节点,而不能访问到上一个结点,而循环链表就可以解决这一问题,当然,用双向链表更加方便#include #include typedef
2021-07-14 08:09:22

在RT-Thread中普通链表和侵入式链表有何区别

普通链表学习数据结构的时候写的链表是下面这个样子侵入式链表在 RT-Thread 以及 Linux 内核中链表是这样定义的在使用的时候是这样定义的每一个内核对象定义的时候,让结构体包含一个成员变量
2022-04-11 15:15:35

如何在C语言中去创建一种双向链表

双向链表的结构是由哪些部分组成的?如何在C语言中去创建一种双向链表呢?
2021-12-24 06:22:06

嵌入式Linux了解

我专业是电子信息工程,在初入大学的时候,我们的班主任便要我们多多去了解一些关于电子方面的知识。后来我了解到了嵌入式,继而了解到了嵌入式Linux。其实我们学习linux差不多就学习linux内核
2021-11-05 09:05:08

嵌入式Linux系统开发学习路线

Linux基础  Linux操作系统的概念、安装方法,详细了解Linux下的目录结构、基本命令、编辑器VI ,编译器GCC,调试器GDB和 Make 项目管理工具, Shell Makefile脚本
2016-09-21 10:09:23

怎么实现c语言循环链表

怎么实现c语言循环链表
2021-10-19 06:07:36

数据结构链表的基本操作

node{ int data; struct node *pNext;//用于指向下一个节点};我们知道,结构体的出现是为了解决数组内部数据格式单一的问题。而链表具有结构体和数组优点,...
2021-12-22 08:05:22

无数据域双向链表的代码

下面是一个简单的示例,演示了如何使用无数据域双向链表进行插入和访问操作: #include #include// 包含offsetof宏 // 定义节点结构体 struct Node
2025-12-11 06:56:33

有关Linux系统的PBC (进程控制块)基础知识介绍

,线程只不过是一种特殊的进程罢了。后续的文章专门介绍进程和线程的创建过程进行分析。在操作系统中,内核把进程的列表存放在一个叫任务队列的双向循环链表中,链表中的每个元素类型就是上述的数据结构
2022-06-23 16:27:52

有谁知道HarmonyOS内核最重要的结构体是什么呢

(注者后续将比喻成一对左右触手)灵活的指挥着系统精准的运行,越是深入分析内核源码,越能感受到内核开发者对LOS_DL_LIST非凡的驾驭能力,笔者仿佛看到了无数双手前后相连,拉起了一个个双向循环链表
2022-03-11 15:09:25

浅析RT-Thread中对象容器与双链表的操作

的操作RT-Thread的对象容器是依赖于双链表双向循环链表)的,其双链表的相关操作在文件rtservice.h中:其节点结构体为:struct rt_list_node{ struct
2022-05-18 14:23:06

玩转C语言链表-链表各类操作详解

));  }  p2->next = NULL; //此句就是根据单向链表的最后一个节点要指向NULL  free(p1); //p1->num为0的时候跳出了while循环,并且释放p1  p1
2019-09-18 13:30:42

约瑟夫环之循环链表这个程序题目大家知道做吗

题目:   n个人围成一圈(编号依次为:0,1,2...n-1),从第一个人开始报数,1,2,……数到m者出列,再从下一个开始重新报数,数到m者再出列……。 下面的程序中,用不带附加表头的循环链表
2020-10-27 11:08:59

请问ADI是否有通用的数字双向隔离芯片?

您好,例如I2C的SDA就是双向的数据信号,请问ADI是否有通用的数字双向隔离芯片?目前看翻倍的光耦就能实现光耦隔离。目标是用来隔离MCU的GPIO到外部的信号,我查到ADUM1250支持1Mbps
2018-08-16 06:02:22

阿尔法Linux

阿尔法Linux ATK-IMX6F800E8GD512M-B 6~24V
2023-03-28 13:06:25

鸿蒙内核源码分析(双循环链表篇) :内核最重要结构体

感受到内核开发者对LOS_DL_LIST非凡的驾驭能力,笔者仿佛看到了无数双手前后相连,拉起了一个个双向循环链表,把指针的高效能运用到了极致,这也许就是编程的艺术吧!致敬鸿蒙内核开发者贡献了如此优秀的源码
2020-11-26 08:00:31

鸿蒙内核源码分析(双循环链表篇) :内核最重要结构体

感受到内核开发者对LOS_DL_LIST非凡的驾驭能力,笔者仿佛看到了无数双手前后相连,拉起了一个个双向循环链表,把指针的高效能运用到了极致,这也许就是编程的艺术吧!致敬鸿蒙内核开发者贡献了如此优秀的源码
2020-12-02 16:55:44

鸿蒙内核源码分析(双循环链表篇) :内核最重要结构体

深入分析内核源码,越能感受到内核开发者对LOS_DL_LIST非凡的驾驭能力,笔者仿佛看到了无数双手前后相连,拉起了一个个双向循环链表,把指针的高效能运用到了极致,这也许就是编程的艺术吧!致敬鸿蒙内核开发者
2020-11-24 13:39:32

C语言实现单链表举例

所谓链表,就是用一组任意的存储单元存储线性表元素的一种数据结构。链表又分为单链表双向链表循环链表等。我们先讲讲单 链表 。所谓单链表,是指数据接点是单向排列的。
2011-07-11 16:40:3787

[9.10.1]--6.10循环链表双向链表

程序设计
jf_75936199发布于 2023-03-06 22:18:07

C加加建立动态链表

C加加建立动态链表利用C语言及c++编写程序
2015-11-19 13:43:200

067. while循环:5.2 了解循环

循环
充八万发布于 2023-07-05 15:48:56

067. while循环:5.2 了解循环 #硬声创作季

循环
充八万发布于 2023-07-07 03:43:39

深入浅出linux内核源代码之双向链表list_head说明文档

深入浅出linux内核源代码之双向链表list_head说明文档以及源码,可以移植到单片机中来。
2016-07-20 17:21:526

算法与数据结构——双向链表

第三章为算法与数据结构,本文为3.3 双向链表
2017-09-19 17:56:007788

周立功新著内容分享:双向链表是什么?

单向链表的添加、删除操作,都必须找到当前结点的上一个结点,以便修改上一个结点的p_next指针完成相应的操作。
2017-09-22 18:24:536348

C语言基础教程之链表

(一)什么是链表链表是一种常见的基础数据结构,是一种线性表,是一种在物理存储单元上非连续非顺序的存储结构。 链表有一系列节点构成,节点在运行时动态生成,每个节点包括数据域,数据域存储当前节点
2017-11-16 10:22:052430

FreeRTOS 中的链表链表元素的定义

FreeRTOS 内核中采用双向循环链表来进行任务调度,对任务总数没有限制,同一优先级的任务数也没有限制。相对于uC/OS-II 来说是一个大的优点。不过,有利必有弊。采用双向链表后代码相对来说要复杂一些。 本文会对此过程进行简单操作。
2017-11-18 01:28:012615

合并两个排序的链表

合并两个排序的链表一、题目要求 输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。 二、我的思路 1、比较两个链表的头结点大小,哪个小就将其作为新链表的头
2018-01-16 22:02:01709

C语言链表相关资料下载

C语言链表相关资料
2018-03-08 10:47:405

如何轻松理解「链表」实现「LRU缓存淘汰算法

双向链表的灵活处就是知道链表中的一个元素结构就可以向左或者向右开始遍历查找需要的元素结构。因此对于一个有序链表双向链表的按值查询的效率比单链表高一些。因为,我们可以记录上次查找的位置 p,每次查询时,根据要查找的值与 p 的大小关系,决定是往前还是往后查找,所以平均只需要查找一半的数据。
2018-12-25 10:09:483364

Linux USB总线的两个链表

一个 USB 总线引出两个首要 的链表,一个为 USB 设备链表,一个为 USB 驱动链表。设备链表包含各种系统中的 USB 设备以及这些设备的所有接口,驱动链表包含 USB 设备驱动程序(usb device driver)和 USB 驱动程序(usb driver)。
2019-04-20 10:33:111253

详细介绍Linux内核链表

链表是一种常用的组织有序数据的数据结构,它通过指针将一系列数据节点连接成一条数据链,是线性表的一种重要实现方式。
2019-04-28 16:39:39774

需要了解Linux模块编程框架

Linux是单内核系统,可通用计算平台的外围设备是频繁变化的,不可能将所有的(包括将来即将出现的)设备的驱动程序都一次性编译进内核,为了解决这个问题,Linux提出了可加载内核模块(Loadable
2019-05-13 10:04:53865

你知道Linux内核数据结构中双向链表的作用?

Linux 内核提供一套双向链表的实现,你可以在 include/linux/list.h 中找到。我们以双向链表着手开始介绍 Linux 内核中的数据结构 ,因为这个是在 Linux 内核中使用最为广泛的数据结构。
2019-05-14 17:27:002115

驱动之路-内核链表的使用

kernel list展示的是内核链表的结构,normallist展示的是普通链表的结构。head是链表头,p1,p2,p3是链表节点。从图中可以看出普通链表的p1的next指针是指向的结构体p2的地址,p2的pre指针指向p1结构体的地址。
2019-05-15 17:24:071558

链表学习的超详细说明(二)

昨天跟大家分享了单链表的一些基本用法,今天接着继续和大家分享单链表的用法,今天分享完,单链表的操作就暂告一段落了,后面接着分享双链表的学习和实战!一、单链表的遍历:1、什么叫遍历?遍历就是把单链表中的各个节点挨个拿出来,就叫遍历
2020-12-24 17:33:071155

链表学习的总结(一)

想必大多数人和我一样,刚开始学数据结构中的单链表还是蛮吃力的,特别是后面的双链表操作更是如此。还有就是在实践代码操作时,你又会感到无从下手,没有思路。
2020-12-24 17:35:263863

可实现骨骼运动重定向的通用双向循环自编码器

针对面向关节坐标表示的骨骼运动数据重定向网络缺乏通用性的问题,提出一种能够实现源骨骼到多种骨骼运动重定向的通用双向循环自编码器。该自编码器由基于关节坐标表示的运动数据以重建误差为损失函数训练得到。在
2021-04-21 10:38:352

双向循环链表函数是什么?如何去实现它?

双向循环链表结点内部有2个指针prev和next分别指向前后的结点,结点定义代码如下。
2021-06-17 12:50:451968

嵌入式linux通用截图工具

嵌入式linux通用截图工具
2021-11-01 17:07:142

链表的代码免费下载

//头插法新建链表 LinkList CreatList1(LinkList &L){//list_head_insert LNode *s; int x; L
2022-05-16 14:25:394

linux内核中llist.h文件中的链表宏讲解

链表宏在linux内核、鸿蒙内核、rtos和一些开源代码中用的非常多。链表宏是双向链表的经典实现方式,总代码不超过50行,相当精炼。在一些开源框架中,它的数据结构,就是以链表宏为基础进行搭建(如shttpd,一个开源的轻量级、嵌入式服务器框架)。本篇文章将对llist.h文件中的链表宏进行逐个讲解。
2022-05-23 12:06:302557

双向循环链表的创建

需要注意的是,虽然双向循环链表成环状,但本质上还是双向链表,因此在双向循环链表中,依然能够找到头指针和头节点等。双向循环链表双向链表相比,唯一的不同就是双向循环链表首尾相连,其他都完全一样。
2022-05-24 16:27:382632

关于llist.h文件中的链表宏讲解

链表宏在linux内核、鸿蒙内核、rtos和一些开源代码中用的非常多。链表宏是双向链表的经典实现方式,总代码不超过50行,相当精炼。
2022-07-01 11:58:361854

C语言_链表总结

本篇文章介绍C语言链表相关知识点,涉及链表的创建、单向链表循环链表双向链表、单向循环链表链表常见问题总结等,还列出了结构体数组与链表的练习题,将在下篇文章贴出完整代码。
2022-08-14 09:53:392489

OpenHarmony中软件模块的单链表实现

为了性能考虑,嵌入式系统一般使用C语言进行开发,由于C语言标准库没有封装链表,所以嵌入式系统一般自己设计和实现链表这种数据结构。
2022-08-30 09:25:50627

应用开发中结构体和链表的关系是怎样的

链表在RTOS上比较常见,这里会把复杂的东西简单化,这也是为啥有些推文的文字很少的原因,码农的产出就是代码,核心就是看相关代码;链表分单链表和双链表,核心都差不多的,就用单链表做展示;
2022-12-12 10:57:291585

链表的基本操作

回看了一下以前写的链表操作,确实有点复杂不利于初学,这篇文章就换个写法,简单明了的介绍链表的操作。
2022-12-13 10:11:151919

链表的基础知识

的知识详细地叙述,所涉及的链表类型包括:单链表,双链表循环链表,每个链表的操作涉及到创建链表,删除链表,插入链表结点,删除链表结点。
2023-01-20 17:00:001884

C++创建链表并输出

使用C++代码创建一个链表并输出。
2023-01-10 15:05:471701

LeetCode876链表的中间结点介绍

给定一个头结点为 head 的非空单链表,返回链表的中间结点。
2023-01-11 17:58:461258

浅析LeetCode 83删除排序链表中的重复元素

给定一个已排序的链表的头 head , 删除所有重复的元素,使每个元素只出现一次 。返回 已排序的链表
2023-02-06 10:25:001169

详细介绍链表在操作系统中定义和使用的方式

链表和数组是两种不同的数据存储方式。链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。
2023-02-22 10:06:041844

Linux内核的链表数据结构

Linux内核实现了自己的链表数据结构,它的设计与传统的方式不同,非常巧妙也很通用
2023-03-24 11:34:341355

C语言入门之链表概述

链表是一种常见的重要的数据结构。它是动态地进行存储分配的一种结构,是根据需要开辟内存单元。 链表有一个“头指针”变量,它存放一个地址,该地址指向一个元素。 链表中每一个元素称为“结点”,每个结点都应包括两个部分
2023-03-24 15:04:541667

链表数据结构基本概念

链表基本概念 头指针: 头指针是指链表指向第一个结点的指针,若链表有头结点,则是指向头结点的指针。 头指针具有标识作用,所以常用头指针冠以链表的名字。 无论链表是否为空,头指针均不为空,头指针是链表
2023-07-27 11:14:401297

链表和双链表的区别在哪里

。 上面的三幅图对于理解链表的插入、删除很重要,看代码的时候要对着看。 实际中经常使用的一般为带头双向循环链表,下面是一个双向循环链表的 demo,是最简单的情况。
2023-07-27 11:20:192399

双向循环链表创建代码

双向循环链表demo #include #include typedef struct node { int data; //"数据域" 保存数据元素 struct node * next
2023-07-27 11:26:131501

如何创建单链表

实际中经常使用的一般为带头双向循环链表。 单链表1 # include # include typedef struct node { int data; //"数据域" 保存数据元素 struct
2023-07-27 16:05:351819

Linux内核中使用的数据结构

Linux内核代码中广泛使用了数据结构和算法,其中最常用的两个是链表和红黑树。 链表 Linux内核代码大量使用了链表这种数据结构。链表是在解决数组不能动态扩展这个缺陷而产生的一种数据结构。链表
2023-11-09 14:24:191114

数组和链表有何区别

数组和链表的区别,这个问题,不仅面试中经常遇到,考研的同学也得掌握才行。
2024-02-19 15:33:471209

数组和链表在内存中的区别 数组和链表的优缺点

数组和链表在内存中的区别 数组和链表的优缺点  数组和链表是常见的数据结构,用于组织和存储数据。它们在内存中的存储方式以及优缺点方面存在一些显著的差异。本文将详细探讨这些差异以及它们的优缺点。 1.
2024-02-21 11:30:221965

已全部加载完成