双向链表的写法和使用的优缺点以及我自认为可以改善的地方

单细胞测序流程(十)KEGG通路富集分析与可视化圈图实战解析 本文详细解析了单细胞测序数据分析中KEGG通路富集分析与可视化圈图的完整实战流程。从差异表达基因列表出发,通过R语言进行KEGG富集分析,并利用Perl脚本进行基因ID转换,最终使用GOplot包绘制高级可视化圈图,帮助研究者将基因列表转化为有意义的生物学故事。 阅读详情

目录

头

链表的分类

双链表的优点

双向链表的写法

下面,我们就来讲双向链表的使用了

首先,就是初始化

有始有终,我们来写销毁

接下来就是插入了,

我们先看尾插,

尾插完了,头插,头插也是一样的套路。

我们的重点讲完了,你吸收了吗,看不懂就多看几遍,下面我们讲查找和展示。

双链表的改进

我们就先来初始化一下

现在我们来写我们改后的插入

listfind,这个函数我们找到了,我设置的是返回这个数据的地址,

现在我们就可以来调试了,我们先调试头插

所以这个想法是可以的实现的,但是具体有多大的用,我不是很清楚,这个仅仅是我分享我的一个想法


头

我们要知道双向链表的写法和使用,我们要先知道什么的双向链表吧。那你们知道吗。不需要抢答,想起来了吗,我们先来讲讲链表有多少种分类,怎么分,这个有点细节了,想得起来吗。想不起来也没关系,我们现在就讲,讲一句题外话这个双链表我认为核心是插入,所以要认真看插入。以及后面的改进和插入都有关系,这个有点长,请耐心。

链表的分类

链表分为,带头和不带头,循环和不循环,单向还是双向。而我们前面讲的单向链表就是不带头不循环单向的链表。而双向链表就是全部反过来,带头循环双向的链表。循环和双向可以理解但是带头是什么知道不,这个呢就是头节点(我们也叫哨兵位)这个节点,他不储存数据,他就起一个带头的作用,而为什么要这个带头呢,我猜可能是因为我们在后面加数据的时候要判断这个链表是不是为空,使用这个带头节点就不要判断了,可以减少代码(如果有人说减少不了什么代码,那我只能认为你写的只是一些小项目了),所以这个带头节点还是有用的。双链表的定义我们讲完了,你现在对双链表的认识有没有更深刻呢。

双链表的优点

虽然我们知道了双链表的定义,但是我们前面也学习了单链表,而双链表对比单链表有什么优势呢,反正我感觉,我以后应该不会用单链表了,因为双链表的功能包含了单链表,我们在写单链表的时候,我们有时候要尾节点是不是很麻烦,我们要从头节点开始next到尾节点,而双向链表就不用,因为双向链表是双向的使用我们可以用头节点的上一个节点,就可以得到尾节点了,是不是非常方便,而且双向链表是每一个都可以向前和向后访问,比单链表方便多了,他还有同节点,你都不要判断链表是不是为空。我把双链表吹的怎么高大上,你可以从里面看出双向链表怎么写吗

双向链表的写法

其实,上面说了怎么多,我们就可以看出两条,1,双向链表可以向前,向后访问。2,有头节点。知道了这两点我们就可以写了。首先,我们要一个存放数据的地方,这个存放数据的地方怎么写啊,看过我上一篇文章的兄弟爽了,这个类型我们可以单独定义出来,为了方便后面想要改。

后面就是两个指针了,一个指向前面的(prev),一个指向后面(next)这样我们就链表的元素就定义好了,看代码。

下面,我们就来讲双向链表的使用了

我们想我们写单链表的时候,我们写了哪些函数来对单链表进行操作,嗯……噢噢,增删查改,还有定义,销毁,再来一个展示,差不多了就这些。那我们就来对双链表进行这些操作。

首先,就是初始化,都没有初始化,怎么进行后面的操作啊,对不对。那问题来了,怎么初始化呢(换个说法就是我们想要初始化为什么样子呢),那我们就要想双链表的定义了,有一个头节点,然后链表是循环的,噢噢,我们要先申请了一个节点吗,嗯……,节点怎么申请。单链表里面就讲了哦,就是malloc嘛直接开辟,因为这个申请我们经常要用所以,我们也写一个函数,叫listbuy,我们又要注意了,我们的链表元素有两个指针,这两个指针指向哪啊,还是不指向了(也可以在后面具体使用的时候再指向,但是这个怕你忘了),但是双链表是循环的啊(一个都没开辟的情况),循环,噢噢噢,指向自己嘛,因此,我们就可以写出

listnode这个是定义的类型,我们虽然开辟了一个地方,为了以防万一还是要判断一下。

所以,我们就可以初始化了,我们先通过listnode得到一个节点(这个节点的指针还是指向自己的因此就不需要我们再操作了),这个就是头节点,就行了

为什么我这里要传-1,其实这里传什么都行,反正你不用就行。

有始有终,我们来写销毁,其实销毁也好写,我们单链表里面销毁怎么写的,是不是一个循环,一个一个空间来释放,就行了,这个的判断条件是指向为空的时候,我们双链表又没有指向为空,这是一个循环,哎,循环,那他走了一圈回来的时候停不就行了。噢,我们也写一个循环,那这个判断条件怎么写呢,虽然说走一圈但是,实际还是要想一下的,因此我画了一个图来理解,我们先创建两个指针,tem,not,为什么我们要两个,因为一个的话,我们如果先free,这里就为空了,就找不到后面的了,我们先往下走了,这里就没有free了,所以我们要两个指针。一开始是这样

然后写一个循环,我们的not先向后走,再free(tem),tem向后走……就到了

这时not的next为头节点了,但是头节点被free了,所以我们不能对他解引用,所以我们这时就要停下来,所以我们的判断条件就为not->next !=头节点(phead),但是我们虽然停下来了,我们还有两个没有free,也简单啊,再释放,就行了

还要把phead(头节点) 赋值为空噢,不然就是野指针了。

接下来就是插入了,要注意,这个插入他是分情况的,分什么情况呢,你也想想,闭眼想,

就是头插和尾插,就是这样你可能还是看不出区别,看图

我是这样认为你,如果你要反过来,我感觉也可以但是,双链表的全部插入就这两种(就是随机插入也和头插的写法是一样的),

我们先看尾插,

我们要把数据3尾插到2的后面去,我们应该怎么办,哎,这个和单链表有区别的啊,单链表的一部分可以借鉴,但是核心思想是一样的,那单链表的核心思想是什么,我感觉是指针,上一个的指针可以指向下一个,所以,我们可以参考一下,那这个是指针,或者说3加进来会影响哪些指针,我们,可以看到的是2的next指针要改,你能想到,phead(头指针)也会有影响吗,那有影响,我们就要改嘛,那我们来理一下改的思路,就是我们要找到原来链表的最后一个元素,这个怎么找,我们可以像单链表一样一个循环一直走到低吗,不能,为什么单链表到低是因为指向NULL才停下来,双链表是循环的一直不为空,哎,循环,那我直接phead的上一个不仅可以了,那

phead->prev不就可以表示原来链表的最后一个元素吗,那我们就可以把原来元素的最后一个和3连上了,就是phead->prev->next(这个可以理解吗,如果不能理解就把phead->prev看为一个指针(叫wei)就变为了wei->next)这个指针指向3(我把这个数据的名字叫jied)的地址就行了,我们再把jied->prev指向2就行了一半,对就是一半因为还有phead,把phead->prev指向哪里,对,指向newnode,再把newnode->next指向phead

我们一共赋值了4次,但是这4次,顺序可以乱,但是

要在的前面,因为这个指针都被你改了,那他指向的地方就不是原链表的最后一个了。

尾插完了,头插,头插也是一样的套路。

一开始就是这样

像上面一样,我们利用phead的next找到,2,然后像上面一样插入。

和上面一样

要在的前面,原因一样。

我们的重点讲完了,你吸收了吗,看不懂就多看几遍,下面我们讲查找和展示。

其实查找和展示的核心就是那个循环,你那个循环理解了(是理解不是直接写一样的,这两个还是有一点区别的),那你现在自己就可以写出来了,查找不就是在循环里面一个一个比较有一样的就返回那个数据的地址,找不到就返回NULL,然后展示就是在循环里面一个一个的printf,假如在跳出循环前有没有打印的,那就出循环后再打印,建议自己写一下尝试一下,我就直接放代码了

全部写好了,你测试一下,反正我测试没有任何问题。

双链表的改进

现在,我来讲一讲我对双链表的设想,我们在上面讲了插入,我们是不是分为了头插和尾插,也可以叫尾插和任意位置插入(包括头插),假如我写一个函数是不是还要判断他是不是尾插还是任意位置插入是不是有点复杂,那我们有没有办法写一个函数是他尾插和任意位置插入都可以,不知道,对我不知道这个我没有想出来,但是我想我把双链表改一下,就可以实现尾插和任意位置插入都行,所以我们来实现一下

这个叫什么我不知道,在这里我还是叫他双链表,但是现在的所有双链表都不是我们认为的那个双链表了,而是我自定义的双链表。那是怎么定义的呢。

你想我们为什么会写出任意位置插入和尾插,就是因为我们有头节点,所有我们就要改这个头节点,但是我们为什么要这个头节点,不就是因为不要判断链表是不是为空吗,那这个头节点我们就不能删除他,不能删除他,那我们又能怎么改呢,既然删除不了,那就再加一个尾,一个头一个尾不就可以了,所有我自己改的链表就是在初始化的时候,我再加一个尾节点,这样就不要分任意位置插入和尾插了。

我们就先来初始化一下,我们可以用上面的listbuy函数得到二个节点,但是双链表是循环的啊,所有我们就把这两个节点连接起来,就好了。我们就初始化为了我们想要的一个头,一个尾节点。

这里为什么传-1和-2,不为什么,因为爱一个人不需要理由。所以这里你只需要传一个你喜欢但是不常用的数据就行了。销毁还是和上面一样一个循环就行了

现在我们来写我们改后的插入,因为这个不需要分头插还是尾插,所以我直接写任意位置插入

函数是

list*pos这个是你要插的位置,假如你要插在头节点的后面你就传头节点,你要插在谁的后面你就传谁。x就是你要插的数据。现在我们就来写

假如链表为空一开始是这样的,我们只能插头节点的后面,你不能插尾节点后面(我是这样认为的,因为没有什么意义),其实链表不为空也是可以的。

我们想要把数据1(newnode)插入头节点后面,我们就要改他两边的指针,这里我们只能通过头节点的下一个节点,(有没有小聪明想到用头节点的上一个节点也可以找到尾节点,你真厉害,但是没用,我是要头节点的下一个节点,这个节点不一定是尾节点)所以我们先通过头节点找到头节点的下一个节点就是phead->next,这个就是现在的尾节点我们就按照,上面的把newnode和phead->next连起来就行了,再连就行了,但是顺序不能反,反了就不能用phead->next找到我们想要的节点了

这个是代码,但是我们的设想的不是为空,我们是要这个函数在任意位置都可以插入,但是你看这个函数就可以在任意位置插入了后面我测试给你们看,测试之前你要你们找到,我怎么传一个指定位置吗,这个链表每一个的元素地址我都不知道,怎么传。但是我们前面已经给了方法,那就是listfind,这个函数我们找到了,我设置的是返回这个数据的地址,所以我们就可以用这个函数来得到数据的地址,而这个函数的核心思路还是循环(这个循环你可能看起来简单,但是要你真正的写了,才可以理解他每一个的奥妙),我就直接放代码了,

还有展示函数和原来的双链表差不多,

现在我们就可以来调试了,我们先调试头插

可以看到没有问题,那我们再来找数据

可以看到我要找两个数据都找到了,并且地址返回了那现在我们在这个地址后面加数据,注意我的链表是4是头节点的next,1是尾节点的上一个节点

所以这个想法是可以的实现的,但是具体有多大的用,我不是很清楚,这个仅仅是我分享我的一个想法

checking OpenSSL library version... configure: error: OpenSSL >= 1.1.1 required (have “100020bf 解决方案  本文主要介绍了checking OpenSSL library version… configure: error: OpenSSL >= 1.1.1 required (have “100020bf (OpenSSL 1.0.2k-fips 26 Jan 2017)”)解决方案,希望能对使用Linux的同学们有所帮助。 文章目录 1. 问题描述 2. 解决方案 阅读详情

相关推荐

Amesim与Simulink联合仿真:S-Function接口配置与实战避坑指南

本文详细介绍了Amesim与Simulink联合仿真中S-Function接口的配置方法与实战避坑指南。从环境搭建、编译器配置到S-Function接口实战,逐步解析关键步骤与常见问题解决方案,帮助工程师高效实现多领域系统仿真,特别适合汽车、航空航天等复杂系统建模场景。

weixin_29173777的博客 344

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

双向链表定义 双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。 双向链表与单链表 单向链表优缺点: 1、优点:单向链表增加删除节点简单。遍历时候不会死循环; 2、缺点:只能从头到尾遍历。只能找到后继,无法找到前驱,也就是只能前进。 双向链表优缺点: 1、优点:可以找到前驱和后继,可进可退; 2、缺点:增加节点和删除节点复杂,多需要分配一个指针存储空间。 代码实现与思路 1.定义结点

我会二进制 793

从理论到实践:使用Sigrity SystemSI完成DDR4信号完整性仿真全流程解析

本文详细解析了使用Sigrity SystemSI完成DDR4信号完整性仿真的全流程,从核心挑战到实战操作。文章深入探讨了DDR4信号完整性问题,介绍了SystemSI工具链的演进与分工,并提供了从前期准备到高级技巧的详细指南,帮助工程师有效解决DDR4设计中的信号完整性问题。

weixin_30505225的博客 510

数据结构——双向链表

数据结构、双向链表、双向链表的优缺点、程序代码封装双向链表、双向链表的操作及方法

qq_56668869的博客 928

ios生成海报使用dom-to-image中toPng报错isTrusted:true

主要是ios中safari浏览器解析错误,引起的报错,主要引起原因toPng会调用toSvg,toSvg直接将html标签内容通过svg中foreignObject标签直接包裹,然后转base64, 通过data:image/svg+xml;解决办法:二次生成(调用两次),判断ios or 安卓,生成第一次生成,不用参数,例如:scale: 3,在第二次生成再进行清晰度操作,避免多次生成,引起性能消耗。以上种种很多案例,使用canvase进行转换的,标签丢失,直接toPng版本的,兼容性问题。

weixin_44601570的博客 2105

无感FOC之高频注入法——永磁同步电机控制

1.摘要电机运行在低速或零速时,磁链产生的反电动势很微弱,可用信号的信噪比太低,因而难以从反电动势中提取转子的位置和速度信息。因而在电机处于低速或零速时,需要借助电机的凸极特性来获取转子的位置信息。内置式永磁同步电机或磁密较大的表贴式永磁同步电机具有这种凸极特性,可借助高频电压注入法获取转子位置。2.凸极特性凸极电机内部的气隙是不均匀的,d轴和q轴的有效气隙是不同的,通俗来说在凸极电机里,q轴电感往往大于d轴电感,而在大部分表贴式永磁同步电机,气隙分布相对均匀,q轴电感近似于d轴电感。凸极率常用q轴电感和d

qq_2545470942的博客 2万+

单向链表和双向链表有什么区别?各自有什么优缺点?

单向链表和双向链表有什么区别?各自有什么优缺点?

tanshunlin的博客 3882

【PADS-开发指南】

馒头破戒大师

sinat_23896491的博客 3216

双向链表

相比于单向链表,双向链表的优点是:对于链表中的任意一个节点,可以从两个方向进行操作,在单向链表中,只有获得结点的前驱结点的指针,才能删除该结点。双向链表中,因为每个结点都有指向前驱节点的指针,所以不必知道前驱结点的地址也能进行删除操作。但是也有缺点:每个节点多出了一个额外的指向前驱结点地址的指针,需要更多的空间开销,另外,对于节点的插入或者删除需要操作更多的指针。 1.双向链表的定义

nch_ren的博客 1100

DPM|03Injection设置

摘要:本文介绍了CFD软件Fluent中粒子注入的设置方法。粒子注入是将离散颗粒引入连续相的过程,可用于模拟灰尘、燃料液滴等。设置流程包括:选择粒子类型(质量less、惰性等)、定义注入点属性(坐标、时间、粒径等)、处理多组分粒子、使用文本文件批量定义复杂注入。文中还详细说明了要考虑的湍流影响,包括随机追踪法模拟湍流扩散,以及粒子旋转建模等注意事项。最后介绍了多种注入类型和粒子类型,并强调在湍流系统中需设置足够的尝试次数以确保结果准确性。

qq_28258217的博客 2228

踩坑实录:C#上位机YOLOv11从2FPS到45FPS,ONNX Runtime GPU加速全解析

算力迁移:将推理核心从CPU迁移至GPU(核心提速手段);内存复用:避免重复分配/释放内存,减少GC压力;维度固定:工业场景固定输入分辨率,关闭动态维度;资源限制:合理限制GPU/CPU/内存占用,避免资源耗尽;解耦设计:推理线程与UI线程解耦,避免跨线程问题。

这里只有干货:从 Modbus 通信到 MES 对接,从 YOLO 训练到工控机部署,带你搞定工业软件开发全流程。 570

解密双向链表:高效增删查改全攻略

本文系统介绍了双向链表的结构与实现,包括基本概念、优缺点分析、节点设计及核心操作(增删查改)。双向链表每个节点包含前驱和后继指针,支持双向遍历和高效删除(O(1)),但需更多内存空间。详细讲解了头插法、尾插法、数据删除等操作的实现逻辑和代码示例,并对比了单向链表的差异。此外还简要提及通用型容器概念和双向循环链表的特点,后者通过首尾相连形成闭环,适用于循环缓冲区等场景。全文通过图解和代码相结合的方式,完整呈现了双向链表的实现过程和应用方法。

2402_83622972的博客 4696

置顶必读(1) |《YOLOv8实战:从入门到深度优化》专栏导读,带你一文了解本专栏!

🏆 本文收录于 《YOLOv8实战:从入门到深度优化》 专栏,该专栏专注于分享我在YOLOv8目标检测模型中的实战经验,涵盖从入门基础到深度优化的全方位解决方案。无论你是计算机视觉的新手,还是具有多年深度学习经验的专家,本专栏都将为你提供高效、可复现的技术方案,助你掌握YOLOv8的核心技术,提升目标检测性能,突破瓶颈,优化模型,并加速项目开发🚀!

**My Coding Family** 14万+

C语言实现双向链表

本章使用C语言实现了数据结构中的双向链表,对于数据结构的初学者来说有一定难度,但对于提升对链表的理解来说意义非凡,值得我们亲自去实现。

2401_86557724的博客 2718

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

双向链表专题

双向链表专题

weixin_73077334的博客 1374

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

单向链表和双向链表的优缺点及使用场景

单向链表:只有一个指向下一个节点的指针。 优点:单向链表增加删除节点简单。遍历时候不会死循环; 缺点:只能从头到尾遍历。只能找到后继,无法找到前驱,也就是只能前进。 适用于节点的增加删除。 双向链表:有两个指针,一个指向前一个节点,一个后一个节点。 优点:可以找到前驱和后继,可进可退; 缺点:增加删除节点复杂,需要多分配一个指针存储空间。 适用于需要双向查找节点值的情况。 ...

qq_36553031的博客 3万+

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

单链表和双向链表

对于单链表的优缺点对于双向链表优缺点双向链表优点缺点查询比单链表效率高,虽然都是o(N),但是可以利用双向特性,进行左右开始查询(类似二分法)内存占用大(两个指针和一个数据,3个元素)双向遍历代码实现向较为单链表复杂插入删除方便总结:对于双向链表和单链表,当需要频繁存入大量数据并查询时,可以首先考虑单链表(内存和代码实现)。当需要频繁插入和删除并频繁遍历时,可以考虑双向链表(时间效率高)。

努力学习C++的熊大(保护森林版) 1015

C语言-双向链表

本文详细介绍了双向链表在C语言中的实现与应用。主要内容包括:1. 指针类型NODE*和NODE**的区别与使用场景,重点说明双指针在修改头节点时的必要性;2. 双向链表的完整实现,包含节点设计、增删改查等基本操作;3. 双向循环链表的实现,分析其循环特性带来的优势;4. 内存检测工具valgrind的使用方法;5. Linux内核链表的设计思想及简化版实现,展示如何解耦链表操作与具体数据类型。文章通过代码示例对比了不同链表结构的优缺点,并阐述了它们在各种场景下的适用性,为开发者提供了链表实现的全面参考。

wy_yy047的博客 1935

双向链表(详解)

在单链表专题中我们提到链表的分类,其中提到了带头双向循环链表,今天小编将详细讲下双向链表。话不多说,直接上货。

2302_79376097的博客 1958

数据结构|双向链表的类型和实现

之前的博客介绍并实现了(

laimaxgg 1521

c--单向链表和双向链表

单向链表和带头双向循环链表的基本介绍和实现

qq_64840642的博客 904

双向链表的实现(双向链表与单向链表的简单区别联系和实现)

前言单向链表和双向链表的优缺点及使用场景双向链表的简单实现及图示分析 前言 之前写了一些文章简单地介绍顺序表,链表的基础知识,还总结了几道链表的笔试题,今天继续开干,向老铁们简单地介绍一下无头双向循环链表及其代码的实现。 为什么要引入无头双向循环链表呢????? 我们可以简单地这样去思考,单向链表只能单向地从头节点去访问其他的节点,不能会退的访问其他的节点,也不能循环地访问,与单向链表不同,双向链表在插入删除的时候不需要寻找前驱节点,因为本身就能回到前面一个节点,**查找时,我们可以用二分发的思路,从首节.

weixin_47792933的博客 919

双向链表添加和删除 java

为了更好地理解双向链表,先说几个相关的概念 List:特性:必须按照插入的顺序来保存元素 第一种实现:最常用的arrylist:结构类似于数组,所以访问元素的时候可以直接通过索引来访问任何位置的数据,但是当插入元素的时候默认是追加到数组的最后,那么数组当中原有的元素的位置不变 只是申请开辟了一块内存空间和新增加了一个索引,其他都没有变化,但是当向其他位置插入元素的时候,会先申请开辟一块内存空间和一...

Marlboro8023的博客 3812

双向链表的简单实现

1.双向链表的结构注意:这里的“带头”和之前的文章中单链表和顺序表说的“头节点”是两个概念,实际前面的在单链表阶段称呼不严谨,但是更好的理解就直接称为单链表的头节点。带头链表里的头节点,实际为“哨兵位”,哨兵位节点不存储任何有效元素,只是站在这⾥“放哨的”“哨兵位”存在的意义:遍历循环链表避免死循环。

2303_80472275的博客 963

用C语言实现双向链表

用C语言实现了一个带头双向循环链表,简单介绍了每个函数的实现和顺序表与双向链表的优缺点。

0xFFFFFFFF 1452

单,双向链表详解

这章开始链表的详解,如果不了解数据结构和顺序表,可以看看-->

chuxinweihui的博客 1143
上一篇: 数据结构(宝宝级别:顺序表-》通讯录)
下一篇: Java数据类型介绍
star050913
博客等级 码龄3年 277粉丝 33原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值