数据结构(一)线性结构(3)栈

数据结构和算法之线性结构 例如Java,通过动态数组实现了ArrayList,因为是用数组实现,其存储结构就是顺序存储的,因而具有顺序表的特征,插入删除效率低,查询元素效率高,但又不完全等同顺序表,因为它的空间是可以动态扩容的;然而,如果栈的使用是固定的,不随输入数据的大小变化,那么空间复杂度为O(1)。顺序表是采用顺序存储结构实现的线性表,一组地址连续的存储单元依次存放线性表的数据元素,即以存储位置相邻表示位序相继的两个元素之间的前驱和后继关系,从而使得逻辑上相邻的两个元素在物理位置上也相邻。为前行者蓄力,为后来者探路! 阅读详情

顺序表、链表是线性表的两种表示方法,指定的线性表的组织方式,对于不同的读写顺序的线性表,也有不同的定义,例如:

元素按照先入后出的顺序读写的线性表称为栈

元素按照先入先出的顺序读写的线性表称为队列

按照上面的定义,可以组合出四种数据结构:顺序栈、链栈、顺序队列、链队列

对于顺序栈,空间是事先分配好的,一般都会偏大,为了更好地利用顺序栈空间,可以将一个大栈拆分为两个小栈,大栈的两端分为别两个小栈的头部,数据元素从两端向中间插入

 

本节介绍单向顺序栈和链栈的基本操作实现

栈的构成为:数据域、栈顶指针(对于顺序栈,栈顶指针就是一个整形变量)

顺序栈定义:
typedef struct STACK {
    int aidata[ARRAY_SIZE];
    int iTop;
}T_Stack, *PT_Stack;

链栈定义:

typedef struct STACK {
    int iData;
    struct STACK *ptNext;
}T_Stack, *PT_Stack;

 

对链栈,同前所述,分有无头节点两种情况,这里以常用的有头节点版本为例

栈的主要操作有:

1、创建空栈:PT_Stack createStack(void);

对顺序栈,创建栈就是预先分配一块数据空间和一个栈顶变量,并初始化变量为-1(数据从0位置开始存储)

对链栈,创建栈只需要创建一个头节点(标志性作用)
2、判空/判满:int isEmpty(PT_Stack ptHead); / int isFull(PT_Stack ptStack)

对顺序栈,判空条件为栈顶指针等于-1,判满条件为栈顶指针等于栈大小-1

对链栈,判空条件是头指针的指针域为空,判满条件为内存空间不足
3、入栈:int pushToStack(int iEle, PT_Stack *pptHead);

对顺序栈,入栈时先判满,不满则将栈顶指针加1,写入数据即可

对链栈,入栈时先创建新节点,创建成功则新节点作为第一个数据节点插入链表
4、出栈:int popFromStack(PT_Stack *pptHead);

对于顺序栈,出栈时先判空,不空则先读出数据,然后栈顶指针减1即可

对链栈,出栈时先判空,不空则读出头部数据节点的数据域,并将该节点删除

 

入栈、出栈操作也可以在链尾进行,但这样需要增加查找链表操作,增加工作量

 

顺序栈代码:

#include <stdio.h>
#include <stdlib.h>

#define MENU_EXIT	0
#define MENU_PUSH	1
#define MENU_POP	2
#define MENU_PRINT	3

#define ERR			-100

typedef struct STACK {
	int aidata[ARRAY_SIZE];
	int iTop;
}T_Stack, *PT_Stack;


int isEmpty(PT_Stack ptStack)
{
	return ptStack->iTop == -1 ? 1 : 0 ;
}

int isFull(PT_Stack ptStack)
{
	return ptStack->iTop == ARRAY_SIZE - 1 ? 1 : 0 ;
}

int pushToStack(int iEle, PT_Stack ptStack)
{
	if (isFull(ptStack))
		return ERR;

	ptStack->iTop++;
	ptStack->aidata[ptStack->iTop] = iEle;
	printf("Push %d to index %d\r\n", iEle, ptStack->iTop);

	return iEle;
}

int popFromStack(PT_Stack ptStack)
{
	int iEle;

	if (isEmpty(ptStack))
		return ERR;

	iEle = ptStack->aidata[ptStack->iTop];
	printf("Pop %d from index %d\r\n", iEle, ptStack->iTop);
	ptStack->iTop--;

	return iEle;
}

PT_Stack createStack(void)
{
	PT_Stack ptStack = NULL;
	int i, iNum, iEle;

	printf("Enter the num of data\r\n");
	scanf_s("%d", &iNum);
	if (iNum > ARRAY_SIZE || iNum < 0)
	{
		printf("Err in the num of data\r\n");
		goto done;
	}

	ptStack = (PT_Stack)malloc(sizeof T_Stack);
	ptStack->iTop = -1;
	if (!ptStack)	
		goto done;

	printf("Enter your data: ");
	for (i = 0; i < iNum; i++)
	{
		scanf_s("%d", &iEle);
		pushToStack(iEle, ptStack);
	}
done:
	return ptStack;
}

void printStack(PT_Stack ptStack)
{
	int i;
	if (isEmpty(ptStack))
	{
		printf("Stack is empty\r\n");
		return;
	}

	printf("\r\n");
	for (i = 0; i <= ptStack->iTop; i++)
		printf("%d ", ptStack->aidata[i]);
	printf("\r\n\r\n");
}


int menu(PT_Stack ptStack)
{
	int iNum, iEle;

	printf("0 to exit\r\n"
		"1 to push\r\n"
		"2 to pop\r\n"
		"3 to print\r\n");

	scanf_s("%d", &iNum);
	switch (iNum)
	{
		case MENU_EXIT:
			return -1;
		case MENU_PUSH:
			printf("Enter the one to be push\r\n");
			scanf_s("%d", &iEle);
			pushToStack(iEle, ptStack);
			break;
		case MENU_POP:
			popFromStack(ptStack);
			break;
		case MENU_PRINT:
			printStack(ptStack);
			break;
	}

	return 0;
}

int main(void)
{
	PT_Stack ptStack;

	ptStack = createStack();
	if (!ptStack)
		return -1;

	while (1)
	{
		if (menu(ptStack) == -1)
			break;
	}

	return 0;
}

 

链栈代码:

#include <stdio.h>
#include <stdlib.h>

#define MENU_EXIT	0
#define MENU_PUSH	1
#define MENU_POP	2
#define MENU_PRINT	3

#define ERR			-100


typedef struct STACK {
	int iData;
	struct STACK *ptNext;
}T_Stack, *PT_Stack;



int isEmpty(PT_Stack ptHead)
{
	return ptHead->ptNext == NULL ? 1 : 0;
}

int pushToStack(int iEle, PT_Stack *pptHead)
{
	PT_Stack ptNew = NULL, ptTmp = NULL;
	
	ptNew = (PT_Stack)malloc(sizeof T_Stack);

	if (!ptNew)
	{
		printf("Err in no memory\r\n");
		return ERR;
	}
	ptNew->iData = iEle;

	ptTmp = (*pptHead)->ptNext;
	if (!ptTmp)
		ptNew->ptNext = NULL;
	else
		ptNew->ptNext = ptTmp;

	(*pptHead)->ptNext = ptNew;

	return iEle;
}

int popFromStack(PT_Stack *pptHead)
{
	PT_Stack ptTmp;
	int iEle;

	if (isEmpty(*pptHead))
		return ERR;

	ptTmp = (*pptHead)->ptNext;
	iEle = ptTmp->iData;
	(*pptHead)->ptNext = ptTmp->ptNext;
	free(ptTmp);
	//printf("Pop %d\r\n", iEle);

	return iEle;
}

PT_Stack createStack(void)
{
	PT_Stack ptHead = NULL;
	int iNum, i, iEle;

	ptHead = (PT_Stack)malloc(sizeof T_Stack);
	if (!ptHead)
	{
		printf("Err in malloc head\r\n");
		goto done;
	}
	ptHead->ptNext = NULL;


	printf("Enter the num of data: ");
	scanf_s("%d", &iNum);

	printf("Enter your data: ");
	for (i = 0; i < iNum; i++)
	{
		scanf_s("%d", &iEle);
		pushToStack(iEle, &ptHead);
	}
	printf("Create a stack with %d nodes\r\n", i);

done:
	return ptHead;
}

void printStack(PT_Stack ptHead)
{
	PT_Stack ptTmp = ptHead;

	if (isEmpty(ptHead))
	{
		printf("Stack is empty\r\n");
		return;
	}

	printf("\r\n\r\n");
	printf("Stack data according to inverted order: ");
	while (!isEmpty(ptTmp))
	{
		ptTmp = ptTmp->ptNext;
		printf("%d ", ptTmp->iData);
	}
	printf("\r\n\r\n");
}


int menu(PT_Stack *pptHead)
{
	int iNum, iEle;

	printf("0 to exit\r\n"
		"1 to push\r\n"
		"2 to pop\r\n"
		"3 to print\r\n");

	scanf_s("%d", &iNum);
	switch (iNum)
	{
	case MENU_EXIT:
		return -1;
	case MENU_PUSH:
		printf("Enter the one to be push\r\n");
		scanf_s("%d", &iEle);
		pushToStack(iEle, pptHead);
		break;
	case MENU_POP:
		popFromStack(pptHead);
		break;
	case MENU_PRINT:
		printStack(*pptHead);
		break;
	}

	return 0;
}

int main(void)
{
	PT_Stack ptHead;

	ptHead = createStack();
	if (!ptHead)
		return -1;

	while (1)
	{
		if (menu(&ptHead) == -1)
			break;
	}

	return 0;
}

 

 

 

 

 

 

 

10、利用智能合约实现公平的私有集合交集 本文探讨了利用智能合约实现公平的私有集合交集(PSI)的多种协议,重点分析了协议 Π 和 Π∗ 的气体成本与性能特点。同时对比了包括 Justitia 和 Anesidora 在内的现有方案,突出了仅使用智能合约实现硬币补偿公平性的优势。文中还介绍了相关密码学基础、安全模型及隐私保障机制,为在不同应用场景下选择高效、安全的 PSI 协议提供了理论支持和实践指导。 阅读详情

相关推荐

Proteus仿真AT89C51驱动DHT11:温湿度数据采集与LCD1602显示的5个调试坑点总结

本文总结了在Proteus仿真环境下使用AT89C51驱动DHT11温湿度传感器并通过LCD1602显示的5个常见调试坑点,包括DHT11时序问题、LCD1602初始化错误、数据校验失败、仿真特有差异及系统稳定性问题,提供了详细的解决方案和优化代码示例,帮助开发者高效完成温湿度采集项目。

weixin_30335575的博客 356

栈 顺序栈 链栈

栈 栈(stack)是一种只能在一端进行插入或删除操作的顺序表。 表中允许进行插入、删除操作的一端称为栈顶(top),表的另一端称为栈底(bottom)。 栈的主要特点是“后进先出”,所以也称为后进先出表。 栈抽象数据类型=逻辑结构+基本运算 例题:给定一个进栈序列看是否能够得到给定的出栈序列 思路:不管第一个出栈序列为什么,直接看第二个出栈元素,如果后一个比前一个大,不用管直接往后看;如果后一个比前一个小,就看这个和前一个出栈元素中间有没有没出栈的元素,如果不存在证明此此序列可出栈,如果存在还

m0_65604564的博客 4273

单细胞专题(1) | 单细胞转录组研究样本准备指南(上)

单细胞RNA测序(scRNA-seq)是目前最前沿,能进行大规模实验的转录组研究技术,为理解细胞组成和动态生物学过程提供了很多新的见解。单细胞研究已经为我们理解发育过程,老化和疾病(如癌症)等提供了大量数据。在这里,小编主要就前期的样本准备与保存需注意问题给大家进行讲解,以备大家在不同的研究场景和研究背景下,走好单细胞转录组学研究的第一步。

bioyigene的博客 4232

栈和队列的判断条件(顺序栈,链栈,环形队列,链队)

顺序栈 栈空:top==-1 栈满:top==maxsize-1 链栈 栈空:s->next==NULL 栈满:不存在 环形队列 队空:p->front==p->rear 队满:(p->rear+1)%maxsize==p->front 链队 队空:q->rear==NULL 队满:不存在

FFFPAG的博客 3447

Linux环境下OpenSSH升级到 OpenSSH_9.8p1(内置保姆级教程并包含openssl升级过程)

2024年7月1日接到安全部门同事邮件通知,目前生产环境及测试环境服务器Openssh存在远程代码执行漏洞(CVE-2024-6387),漏洞等级高,且攻击者可以成功利用该漏洞获得远程root shell最高权限从而执行任意代码及命令,主要受影响版本为8.5p1

菜鸟运维升级之路 2万+

将Python爬取的数据导入钉钉多维表

摘要:本文介绍将Python爬取的数据导入钉钉多维表的完整解决方案。首先通过requests库爬取数据并解析为结构化格式,然后使用钉钉开放平台API对接多维表。关键步骤包括获取app_key、app_secret等凭证,通过OAuth2获取access_token,以及批量写入记录。文章详细说明了参数获取位置、字段类型匹配、权限配置等注意事项,并提供了错误处理建议和性能优化方法。适用于需要将网络数据同步到钉钉多维表的开发场景。

IT深耕十余载,大道之简 2131

关于栈的学习笔记——链栈

链栈的基本操作的实现

p2801514797的博客 2735

FreeRTOS面试题汇总

如果一个低优先级的任务持有一个信号量,高优先级的任务想要用这个信号量,造成的死锁怎么解决。12.FreeRTOS的多任务之间如何去进行通信的,什么方法,它实现原理是什么。任务间数据传输一共有三种形式,用的最多的是消息队列,其次是全局变量和信号量。简历上写了了解RTOS,问了rtos的问题,用过哪些函数。讲解FreeRtos原理,调度机制,底层原理,代码调用。FreeRTOS,你的三个任务控制,请问你是怎么实现的。freertos中EventBits_t是干啥的?freertos使任务切换的方式有哪些?

weixin_45636780的博客 1万+

【图解数据结构】栈全面总结

一、前言 掌握栈这种抽象数据类型的特点,在相应的实际问题中正确应用 掌握栈类型的两种实现方法 二、基本概念 定义:只允许在一端进行插入或删除的线性表 栈顶(top):允许进行插入或删除的一端 栈底(bottom):与栈顶相对应的一端 特点:先进后出 三、栈的表示和实现 1.顺序栈 定义:一组地址连续的存储单元依次存放自栈底到栈顶的数据元素 top :用来表示栈顶元素的位置 top==-1表示空栈 top==NULL表示栈不存在 top>stacksize....

知心宝贝的博客 1万+

开尔文四线法与电桥(uΩ电阻检测)

本文介绍了开尔文四线法与电桥在电阻测量中的应用,特别是针对uΩ级别电阻的精确检测。讨论了基本电桥电路的工作原理,强调了开尔文四线法的优势,它能消除导线和接触电阻的影响。文中还提到了测试设备的介绍,包括不同级别的电阻测试,并详细阐述了uΩ级别电阻测试的步骤和注意事项。此外,对比了惠斯通电桥与开尔文电桥,强调了它们在电阻测量中的作用和计算方法。

让你爱上电路设计 7866

AI产品经理面试宝典第94天:RAG知识库构建与预处理策略面试指南

本文深入解析RAG知识库构建的核心挑战与预处理策略,涵盖文档格式转换、问答对生成及自动化测试全流程,为AI产品经理提供面试必备的实战方法论与避坑指南,助你精准应对技术深度类问题。

打造全国最全的AI Agent开发知识领域的博客 312

数据结构——顺序存储&链式存储的区别用法

目录: 一:顺序存储结构 二:链式存储结构 数据的存储结构应正确反映数据元素之间的逻辑关系 数据元素的存储结构形式有两种:顺序存储和链式存储 一:顺序存储结构 是把数据元素存放在地址连续的存储单元里 其数据间的逻辑关系和物理关系是一致的 二:链式存储结构 是把数据元素存放在任意的存储单元里 这组存储单元可以是连续的 也可以是不连续的 ...

刘鑫磊 3万+

基于STM32设计的老人摔倒检测报警系统【升级版】(235)

在 `235 基于STM32设计的老人摔倒检测报警系统(OneNet+MQTT)` 项目基础上增加了心率、血氧、体温测量3个功能。

1511

[详解栈和队列]数据结构之栈与队列

✅作者简介:大家好,我是Philosophy7?让我们一起共同进步吧!🏆 📃个人主页:Philosophy7的csdn博客 🔥系列专栏: 👑哲学语录: 承认自己的无知,乃是开启智慧的大门 💖如果觉得博主的文章还不错的话,请点赞👍+收藏⭐️+留言📝支持一下博>主哦🤞 文章目录栈和队列1.物理结构和逻辑结构2.什么是栈2.1栈的基本操作3.什么是队列队列的基本操作小结 栈和队列 1.物理结构和逻辑结构 再了解栈和队列之前,我们要先知道什么是逻辑结构和物理结构。 逻辑结构: 按照逻辑结构划分:数据结.

Philosophy7的博客 4195

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

常用数据结构--线性结构

数据结构是计算机存储、组织数据的方式。常见的数据结构分类方式如下图: 常用的线性结构有:线性表,栈,队列,循环队列,数组。线性表中包括顺序表、链表等,其中,栈和队列只是属于逻辑上的概念,实际中不存在,仅仅是一种思想,一种理念;线性表则是在内存中数据的一种组织、存储的方式。   顺序表 顺序表将元素一个接一个的存入一组连续的存储单元中,在内存物理上是连续的。如下图:

袁伏彪 —— 共享,共赢 2万+

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

数据结构——线性结构

数据结构——线性结构 一、线性结构 在学习线性表之前肯定是需要对线性结构进行理解,如果按我个人的经验来说的话对于线性结构的理解是在学习数据结构中最为重要的,几乎后面所有学习结构都或多或少对线性结构进行利用。 线性结构 特点 前提 在数据结构的非空有限集合中 1 存在唯一的一个被称做“第一个”的元素 2 存在唯一的一个被称做“最后一个”的数据元素 3 除最后元素之外,其它...

ZXlxilin 3750

数据结构——栈(C语言:超详细)

栈,一种后进先出的线性数据结构,虽简单却至关重要。它如程序运行的基石,管理函数调用、实现递归,还高效解决括号匹配、表达式求值等问题。栈简化复杂操作,广泛应用于操作系统、编译器等,是计算机科学不可或缺的强大工具,理解它对于掌握编程至关重要。效率,解决复杂问题,是算法的基础,也是程序设计中不可或缺的关键要素。

weixin_74353123的博客 2936

数据结构之线性结构和非线性结构

线性结构和非线性结构一、线性结构1.1 基本概念1.2 部分实现(1)顺序表(顺序存储)(2)链表(链式存储)(3)栈(4)队列二、非线性结构2.1 相关概念(1)二叉树(2)满二叉树(3)完全二叉树2.2 二叉树存储结构(1)顺序存储(2)链式存储2.3 树与二叉树的转换(1)树转二叉树(2)二叉树转树2.4 树的遍历代码实现 一、线性结构 1.1 基本概念 (1)线性结构作为最常用的数据结构,其特点是数据元素之间存在一对一的线性关系。 (2)线性结构拥有两种不同的存储结构,即顺序存储结构和链式存储结构。

weixin_43520450的博客 4736

数据结构:线性结构和非线性结构的理解

我们知道数据结构是计算机存储、组织数据的方式。常见的数据结构分类方式如下图: 我们这里主要说一下线性结构和非线性结构 1. 线性结构 线性结构是什么? 数据结构中线性结构指的是数据元素之间存在着“一对一”的线性关系的数据结构。线性结构是一个有序数据元素的集合。 线性结构特点: 线性结构有唯一的首元素(第一个元素) 线性结构有唯一的尾元素(最后一个元素) 除首元素外,所有的元素都有唯一的“前驱” ...

鄙人kunzhi96,感恩遇见! 3万+

数据结构 线性结构篇——栈和队列

文章目录一、栈1.1 什么是栈1.2 栈的应用1.2.1 无处不在的撤销(undo)操作1.2.1 计算机程序调用的系统栈1.3 栈的实现 一、栈 1.1 什么是栈 栈是一种线性架构 相比数组,栈对应的操作时数组的子集 栈只能从一端添加元素,也只能从一端取出元素,最先放入堆栈中的内容最后被拿出来,最后放入堆栈中的内容最先被拿出来, 被称为 先进后出 、后进先出。 这里说的一端指的就是 栈顶,删除...

牧小农 4244

数据结构与算法基础(一)

大家好 我是makasa 这个栏目呢,我会按照我之前通过视频学习的一个笔记来记录. 同时,通过写这几篇blog来巩固一下我的基础 数据结构与算法,顾名思义,分为两个部分:数据结构、算法。那它们各自具体概述是什么呢。让我们看以下两个图,简单明了。这里大概了解以下即可。 下面我们重点来讲以下线性结构。 首先线性结构分为: 1.以顺序存储方式存储的线性结构: ①数组(最大可取到长度-1、数组长度不可...

Mikasa的博客 7783

数据结构分类之什么是线性结构、非线性结构

什么是线性结构、非线性结构 数据结构分类大多可以有三种分类方式,分别是逻辑结构、物理结构、存储结构。一般来讲大多数都是以逻辑结构进行划分的。 线性结构 简单地说,线性结构就是表中各个结点具有线性关系。如果从数据结构的语言来描述,线性结构应该包括如下几点: 1、线性结构是非空集。 2、线性结构有且仅有一个开始结点和一个终端结点。 3、线性结构所有结点都最多只有一个直接前趋结点和一个直接后继结点。 ...

cy_an的博客 1万+

什么是线性结构,什么是非线性结构?

什么是线性结构,什么是非线性结构? 线性结构是一个有序数据元素的集合。常用的线性结构有:线性表,栈,队列,双队列,数组,串。 非线性结构,其逻辑特征是一个结点元素可能有多个直接前趋和多个直接后继。常见的非线性结构有:二维数组,多维数组,广义表,树(二叉树等)。 一、线性结构: 1、线性结构作为最常用的数据结构,其特点是数据元素之间存在一对一的线性关系。 2、线性结构拥有两种不同的存储结构,即顺序存...

haoqisongshu的博客 7万+

数据结构——栈与队列

数据结构栈与队列相关基础知识详解!!!

m0_57484470的博客 6931

数据结构与算法python版本之线性结构之栈

线性结构是一种有序数据项的集合,其中每个数据项都有唯一的前驱和后继除了第一个没有前驱,最后一个没有后继新的数据项加入到数据集中时,只会加入到原有的某个数据项之前或之后具有这种性能的数据集,就称为线性结构线性结构总有两端,在不同的情况下,两端的称呼也不同,有时候称为左右端、前后端、顶端和底端两端的称呼并不是关键,不同线性结构的关键区别在于数据项增减的方式,有的结构只允许数据项从一端添加,而有的结构则允许数据项从两端移除。

qq_41780297的博客 1075

数据结构——线性结构(线性表)

定义把所有的结点用一根直线穿起来详细定义线性表是具有相同数据类型的n(n≥0)个数据元素的有限序列,其中n为表长,n=0是一个空表。用L表示线性表a1是唯一的第一个数据元素,又称表头元素;an是唯一的最后一个元素,又叫表尾元素。除了第一个元素之外,每个元素有且仅有一个直接前驱。除了最后一个元素外,每个元素有且仅有一个直接后继。n个节点离散分配彼此通过指针相连每个节点只有一个前驱节点,每个节点只有一个后续节点首节点没有前驱节点,尾节点没有后续节点从某种角度而言。............

巧克力布丁的博客 1万+
上一篇: 数据结构(一)线性结构(2)链表
下一篇: 数据结构(一)线性结构(4)队列
floatinglong
博客等级 码龄9年 90粉丝 143原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值