数据结构与算法分析~笔记9内部排序

9.1 排序的基本概念

设有记录序列{R1,R2,…,Rn},其相应的关键字序列为{K1,K2,…,Kn},若存在某种确定的关系Kx≤Ky≤…≤Kz,其中1≤x,y,z≤n且x、y、z各不相同,则将记录序列{R1,R2,…,Rn}排成按关键字有序的序列{Rx,Ry,…,Rz}的操作,称为排序(Sort)。其中排序所依据的关系是任意的,通常使用小于(递增)、大于(递减)等关系。
从操作角度看,排序是线性结构的一种操作,待排序记录可用顺序储存结构或链式储存结构储存。
当待排序元素的关键字各不相同时,排序的结果是唯一的,否则排序的结果可能不唯一。如果待排序列中存在多个关键字相同的元素,经过排序后这些具有相同关键字的元素之间的相对次序保持不变,则称这种排序方法是稳定的(Stable);若经过排序后这些具有相同关键字的元素之间的相对次序发生了变化,则称这种排序方法是不稳定的(Unstable)。
若待排序序列中的记录已按关键字排好序,则称此记录序列为正序(Exact Order);若待排序序列中记录的排列顺序与排序后的排列顺序正好相反,称此记录序列为逆序(Inverse Order)或反序(Anti Order)。
一趟(Pass)是指在排序过程中,将待排序的记录序列扫描一遍。
单关键字排序(Single-key Sort)是根据一个关键字进行的排序;多关键字排序(Mutiple-key Sort)是根据多个关键字进行的排序,多关键字排序主要针对关键字有重复的情况。行的排序,多关键字排序主要针对关键字有重复的情况。设第1个到第m个(m≤s,s为待排序列记录中数据项的个数)关键字分别为k1, k2,…, km,则单关键字排序有以下两种方法。
(1)依次对记录进行m次排序,第一次按k1排序,第二次按k2排序,……这种方法要求各趟排序所用的方法是稳定的。
(2)先将关键字k1,k2,…,km分别视为字符串,将它们依次首尾连接在一起,形成一个新的字符串,然后,对记录序列按新形成的字符串排序。
排序方法根据在排序过程中数据元素是否完全在内存,分为内部排序和外部排序两类。
内部排序是指在排序的整个过程中,待排序的所有记录全部被放置在内存中的排序方法,也简称为内排序外部排序是指由于待排序的记录个数太多,不能同时放置在内存,而需要将一部分记录放置在内存中,另一部分记录放置在外存中,整个排序过程需要在内外存之间多次交换数据才能得到排序结果的排序方法,也简称为外排序
本章介绍的插入排序、交换排序、选择排序、归并排序和基数排序都属于内部排序方法。
可以将排序方法分为基于比较的排序和不基于比较的排序。
基于比较的排序方法主要通过关键字之间的比较、记录的移动这两种操作来实现的排序;不基于比较的排序方法是根据待排序数据的特点所采取的其他方法,通常没有大量的关键字之间的比较和记录的移动这两种操作的排序。
后续介绍的插入排序、交换排序、选择排序和归并排序是基于比较的排序,而基数排序是不基于比较的排序。
为便于讲解各类排序方法,若不加说明,则本章有如下约定:
(1)待排序数据采用顺序储存结构,利用一维数组r存储;
(2)排序都是将待排序的数据序列排列为升序或非降序序列;
(3)为简化算法,数据的数据类型为整型;
(4)待排序的数据个数用n表示;
(5)本章中所涉及的序列{R1,R2,…,Rn}均以其关键字代替,即用{K1,K2,…,Kn}表示。

9.2 插入排序

插入排序(Insert Sort)是一类简单直观的排序算法。
插入排序的工作原理:每次将一个待排序的数据按其关键字的大小插入到一个已经完成排序的有序序列中,直到全部记录排序结束。根据排序的具体执行过程,又可将插入排序细分为直接插入排序、折半插入排序、表插入排序和Shell排序等。
直接插入排序
直接插入排序(Straight Insertion Sort)的算法思路是:通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,从而找到相应的位置并插入。在从后向前扫描过程中,需要反复把已排序的元素逐步向后挪位,为待插入的新元素提供插入空间。
直接插入排序的步骤如下。
Step 1:设置i=2。
Step 2:将待插入记录r[i]放入编号为0的结点(即下标为0的结点),即r[0]=r[i];并令j=i-1,从第j个记录开始向前查找插入位置。
Step 3:若r[0].key≥r[j].key,执行Step 5;否则执行Step 4。
Step 4:将第j个记录后移,即r[j+1]=r[j];并令j=i-1;执行Step 3。
Step 5:完成插入记录:r[j+1]=r[0],i=i+1。若i>n,则排序结束,否则执行Step 2。
则直接插入排序算法执行的流程图如图所示:
在这里插入图片描述
直接插入排序的一个例子:
在这里插入图片描述
算法分析:最好情况的算法的时间复杂度为O(n)。最坏情况的算法的时间复杂度为O(n*n)。直接插入排序算法的平均时间复杂度为O(n2)。
空间复杂度:由于直接插入排序只需要一个作为暂存待插入记录的存储单元,因此其空间复杂度为O(1)。
稳定性:该算法是稳定的排序方法。

折半插入排序
在有序表中确定插入位置,可以不断二分有序表来确定插入位置,即在一次比较中,通过比较待插入记录和有序表中中间记录的关键字,将有序表一分为二,而下一次比较则在其中一个有序子表中进行,将子表再次一分为二。这样继续下去,直到要比较的子表中只有一个记录时,做最后一次比较以确定插入位置。
折半插入排序的步骤如下。
Step 1:设置i=2。
Step 2:顺序表中前i-1个记录有序,将第i个记录插入。令low=1,high=i-1,r[0]=r[i]。
Step 3:若low>high,得到插入位置;执行Step 6;否则执行Step 4。
Step 4:则取有序子表的中点m =[(low+high)/2]。
Step 5:若r[0].key<r[m].key,则插入位置在低半区,令high=m-1;否则插入位置在高半区,令low=m+1;执行Step 3。
Step 6:high+1即为待插入位置,从i-1到high+1的记录,逐个后移,r[high+1]=r[0],i=i+1。若i>n,则排序结束,否则执行Step 2。
在这里插入图片描述
算法分析时间复杂度:折半插入排序移动记录次数与直接插入排序相同,而关键字比较的次数至多为[log2(n+1)]。因此其时间复杂度仍为在这里插入图片描述
空间复杂度:折半插入排序与直接插入排序一样,需要一个作为暂存待插入记录的存储单元,因此空间复杂度为O(1)。
稳定性:折半插入排序是稳定的排序方法。

表插入排序
表插入排序则是一种不移动记录而是通过改变存储结构来进行排序的算法。所谓表插入排序就是通过链接指针、按关键字的大小实现从小到大的链接过程,为此需增设一个指针项。而具体的操作方法与直接插入排序类似,不同的是表插入排序是直接修改链接指针来完成记录的排序.
其具体思想为:首先设置空循环链表,即头结点指针置为0,并在头结点数据中存放比所有记录的关键字都大的整数,然后把结点逐个向链表中插入即可。则表插入排序的步骤如下。
Step 1:进行初始化操作。令L->r[0].key=MAXSIZE;L->r[0].next=1;j=L-> r[0].next;L-> r[1].next=0;i=2;
Step 2:若i=L->length,调整结束;否则根据j对静态链表进行遍历:
(a)当L->r[i].key≤L->r[j+1].key时停止遍历,令L->r[i].next=L->r[j].next;L->r[j].next=i;j=L->r[0].next;i++;执行Step 2。
(b)当L->r[i].key>L->r[j+1].key时,j++,执行(a)。
则表插入排序算法执行的流程图如图所示:
在这里插入图片描述
算法分析
时间复杂度:表插入排序的时间复杂度为O(n2)
空间复杂度:表插入排序需要一个存储单元作为头结点,因此其空间复杂度为O(1)。
稳定性:表插入排序是稳定的排序方法。

希尔排序
希尔排序
(Shell Sort)又称缩小增量排序。
希尔排序的基本思想:先将整个待排序记录分成若干个子序列,在子序列内分别进行直接插入排序;直到整个序列基本有序时,再对全体记录进行一次直接插入排序。与直接插入排序方法的区别是,希尔排序不是每次一个元素挨着一个元素比较,而是初期选用大跨步(增量较大)间隔比较,使记录跳跃式接近它的排序位置;然后增量逐步缩小,最后增量为1。
希尔排序的操作步骤如下。
Step 1:选择一个步长序列T1,T2,…,tk,其中tk=1且当i<j时,ti>tj。
Step 2:按步长序列个数k,对序列执行k次Step 3。
Step 3:每次排序,根据对应的步长ti,将待排序列分成若干个子序列,分别对各子序列进行直接插入排序。当步长为1(即tk)时,整个序列作为一个表来处理,表长度即为整个序列的长度。
则希尔排序算法的执行流程图如图所示:
在这里插入图片描述
算法分析
希尔排序的时间性能在O(n2)O(nlog2n)之间,当n在某个特定范围时,希尔排序算法的时间复杂度约为O(n1.3)
空间复杂度:空间复杂度为O(1)。
稳定性:希尔排序是不稳定的排序方法。

9.3 交换排序

交换排序的特点是:将关键字较大的记录向序列的一端移动,而关键字较小的记录向序列的另一端移动。
冒泡排序
冒泡排序(Bubble Sort)也称为起泡排序,它是交换排序中常用的排序方法。冒泡排序的基本思想:通过对待排序元素中相邻元素间关键字的比较和交换,使关键字最大的元素如气泡一样逐渐“上浮”。冒泡排序的具体操作步骤如下。
Step 1:从存储n个待排序元素的表尾开始,并令j=n。
Step 2:若j<2,则排序结束。
Step 3:从第一个元素开始进行两两比较,令i=1。
Step 4:若i≥j,则一趟冒泡排序结束,j=j-1;待排序表的记录数-1,转Step 2。
Step 5:比较r[i].key与r[i+1].key,若r[i].key≤r[i+1].key,则不交换,转Step 7。
Step 6:当r[i].key>r[i+1].key时,将r[i]与r[i+1]交换。
Step 7:i=i+1,转Step 4继续比较。
算法分析
平均时间复杂度为在这里插入图片描述
空间复杂度:冒泡排序只需要一个记录的辅助空间,用来作为记录交换的暂存单元。
冒泡排序是一种稳定的排序方法。因为比较和交换是在相邻单元进行的,如果关键字值相同,则不发生交换。

快速排序
快速排序(Quick Sort)也称为分区交换排序。快速排序的基本思想:通过对关键字的比较和交换,以待排序列中的某个数据为支点(或称枢轴量),将待排序列分成两个部分,其中左半部分数据小于等于支点,右半部分数据大于等于支点。然后,对左右两部分分别进行快速排序的递归处理,直到整个序列按关键字有序为止。
如图所示为快速排序的基本思想的图示,其中将待排序列按关键字以支点分成两个部分的过程称为一次划分。
在这里插入图片描述
可将快速排序视为对冒泡排序的一种改进。快速排序的操作步骤如下。
Step 1:如果待排子序列中元素的个数等于1,则排序结束;否则以r[low]为支点,按如下方法进行一次划分:
1.1 设置两个搜索指针:low是向后搜索指针,初始指向序列第一个结点;high是向前搜索指针,初始指向最后一个结点;取第一个记录为支点,low位暂时取值为支点pivotkry=r[low]key。
1.2 若low=high,枢轴空位确定为low,一次划分结束。
1.3 若low<high且r[high].key≥pivotkry,则从high所指定的位置向前搜索:high=high-1,重新执行1.3;否则若有low<high并且有r[high].key<pivotkry,则设置high为新的支点位置,并交换r[high].key和r[low].key,然后令low=low+1,执行1.4;若有low≥high,则执行1.2。
1.4 若low<high且r[high].key≤pivotkry。则从low所指的位置开始向后搜索:low=low+1,重新执行1.4;否则若有low<high并且有r[low].key>pivotkry,则设置low为新的支点位置,并交换r[high].key和r[low].key,然后令high=high-1,执行1.3;若有low≥high,则执行1.2。
Step 2:对支点左半子序列重复Step 1。
Step 3:对支点右半子序列重复Step 1。
其中快速排序的每一趟排序的流程图如图所示:
在这里插入图片描述
算法分析
时间复杂度:快速排序通常被认为是在同数量级(O(nlog2n))排序算法中平均性能最好的算法。
空间复杂度:由于快速排序的过程是一个递归的过程,每层递归时都需要用栈来存放指针和相应的参数,且递归的层数与其二叉树的深度一致。因此其空间复杂度平均为O(log2n)。
稳定性:快速排序是不稳定的排序方法。

9.4 选择排序

选择排序(Selection Sort)是一类借助“选择”进行排序的方法。
选择排序的基本思想:每一趟从待排序列中选取一个关键字最小的记录,也即第一趟从n个记录中选取关键字最小的记录,第二趟从剩下的n-1个记录中选取关键字最小的记录,直到全部元素排序完毕。由于选择排序每一趟总是从待排序序列中选取最小(或最大)的关键字,所以选择排序适用于从大量的元素中选择一部分排序元素的应用。如从50000个元素中选择出前10个关键字最小的元素等。

简单选择排序
简单选择排序(Simple Selection Sort)是选择排序中最简单的一种排序算法。
简单选择排序的基本思想:第一趟从n个记录中选出关键字最小的记录和第一个记录交换;第二趟从第二个记录开始的n-1个记录中再选出关键字最小的记录与第二个记录交换;如此第i趟则从第i个记录开始的n-i+1个记录中选出关键字最小的记录与第i个记录交换,直到整个序列按关键字有序。
简单排序的操作步骤如下:
Step 1:创建一个辅助变量j用于存放每次遍历关键字最小的记录的下标。设置变量i=1。
Step 2:遍历第i个记录到第L.length个记录。选择一个关键字最小的记录,将其下标保存至j中。
Step 3:若第i个记录的关键字小于j中保存的记录的关键字,则交换这两个记录。
Step 4:i=i+1,若i<L.length,则执行Step 2;否则排序结束。
简单选择排序算法的执行流程图:
在这里插入图片描述
算法分析
时间复杂度:算法的时间复杂度为在这里插入图片描述
空间复杂度:其空间复杂度为O(1)。
稳定性:简单选择排序是稳定的排序方法。

树形选择排序
树形选择排序(Tree Selection Sort)又称为锦标赛排序(Tournament Sort),它是一种按照锦标赛的思想设计的选择排序算法。
树形选择排序的基本思想:将n个参赛选手视为完全二叉树的叶子结点,则该完全二叉树有2n或2n-1个结点。首先,叶子结点进行两两比较,胜出(在本节示例中,关键字较小者胜出)的结点在兄弟结点之间再两两比较,直至产生第一名;接下来将作为第一名的结点视为最差的,并从该结点开始,沿该结点到根路径上,依次进行各分支结点孩子之间的比较,胜出的就是第二名(因为和它比赛的均是刚刚输给第一名的结点)。这样继续下去,直到所有选手的名次排定。
树形选择排序的操作步骤如下:
Step 1:从最底层的叶子结点开始,逐层进行兄弟间的比赛,关键字较小者上升为双亲结点,直到树根为止。
Step 2:将树的根结点输出,并将底层叶子结点中的一个值与输出结点值相同的结点设为MAX。
Step 3:如果输出的结点总数小于初始树的叶子结点数,则重复步骤1;否则结束排序。

树形选择排序算法的执行流程图:
在这里插入图片描述
算法分析
时间复杂度:时间复杂度为O(nlog2n)。
空间复杂度:空间复杂度为O(n)。
稳定性:树形选择排序是稳定的排序方法。

堆排序
堆排序(Heap Sort)是利用堆的特性进行排序的方法。n个元素的序列{k1,k2,…,kn},当且仅当任一ki满足以下关系时,称之为堆:
在这里插入图片描述
其中,i=1,2,…,[n/2],分别称为小顶堆和大顶堆。根据堆的定义,它也是完全二叉树,且具有下列性质之一:
(1)每个结点的值都小于或等于其左右孩子结点的值,称之为小顶堆;
(2)每个结点的值都大于或等于其左右孩子结点的值,称之为大顶堆。
堆的示例:
在这里插入图片描述
堆排序的基本思想:首先用待排序的记录序列构造出一个堆,此时选出了堆中所有记录的最小者为堆顶,随后将它从堆中移走(通常是将堆顶记录和堆中最后一个记录交换),并将剩余的记录再调整成堆,这样又找出了次小的记录,依次类推,直到堆中只有一个记录为止。
堆排序的操作步骤如下:
Step 1:i=1,基于顺序表L[1,2…,L.lentgh-i+1]中的元素先建一个小顶堆。
Step 2:将堆顶元素和L[L.lentgh-i+1]交换。
Step 3:i=i+1,若i<L.lentgh,则再对L[1,2…,L.lentgh-i+1]进行调整,形成新的小顶堆,执行Step 2;若i≥L.lentgh,则排序结束。
堆排序算法的执行流程图:
在这里插入图片描述
基于n个元素建立堆的方法如下:对于一个含有n个结点的完全二叉树,其最后一个结点是第[n/2]个结点的孩子结点。对第[n/2]个结点及其孩子结点进行调整(交换结点关键字),使之满足堆的定义,之后再向前依次对各个结点为根的子树进行调整,最终整个完全二叉树为一个堆。
在完成建堆之后,只需将根结点的值输出,再用最后一个结点代替根结点,再从根结点开始对不满足堆定义的分支进行调整即可再次获得一个堆。依次类推,直到所有结点都输出,这时得到的输出序列就是所求的有序序列。

算法分析
时间复杂度:堆排序总的时间复杂度为O(nlog2n)。
空间复杂度:堆排序只需要用到一个用来交换的存储单元,因此其空间复杂度为O(1)。
稳定性:堆排序是不稳定的排序方法。

9.5 归并排序

归并排序(Merge Sort)是一类借助“归并”进行排序的方法。归并的含义是将两个或两个以上的有序序列归并成一个有序序列的过程。归并排序按所合并的表的个数可分为二路归并排序和多路归并排序。
二路归并排序(2-way Merge Sort)的基本思想是:将待排序的n个元素看成是n个有序的子序列,每个子序列的长度为1,然后两两归并,得到[插图]个长度为2或1(最后一个有序序列的长度可能为1)的有序子序列;再两两归并,得到[插图]个长度为4或小于4(最后一个有序序列的长度可能小于4)的有序子序列;再两两归并,……直至得到一个长度为n的有序序列。

二路归并排序的操作步骤如下:
Step 1:将待排序列划分为两个长度相当的子序列。
Step 2:若子序列长度大于1,则对子序列执行一次归并排序。
Step 3:执行下列步骤对子序列两两合并成有序序列。
3.1 创建一个辅助数组temp[]。假设两个子列的长度分别为u、v,两个子列的下标为0~u,u+1~v+u+1。设置两个子表的起始下标和辅助数组的起始下标:i=0;j=u+1;k=0。
3.2 若i>u或j>v+u+1,说明其中一个子表已经合并完毕,直接执行3.4。
3.3 选取r[i]和r[j]中关键字较小的存入辅助数组temp[]:若r[i].key<r[j].key,则temp[k]=r[i];i++;k++;否则temp[k]=r[j];j++;k++,返回执行3.2。
3.4 将尚未处理完的子表元素依次存入temp[],结束合并,并将结果返回。则一趟归并操作流程图如图所示。
在这里插入图片描述
算法分析
时间复杂度:整个二路归并排序的时间复杂度为O(nlog2n)。
空间复杂度:空间复杂度为O(n)。
稳定性:归并排序是稳定的排序方法。

9.6 基数排序

基数排序(Radix Sort)算法与之前所讨论的排序算法不同,它并不利用关键字之间的比较和移动操作来进行排序,而是通过多关键字排序的思想,根据关键字每个位上的有效数字的取值,借助分配和收集两种操作对单关键字进行排序。
多关键字的排序
多关键字排序是应用在多关键字的序列上的排序方法,最常见的多关键字序列的排序方法是最低优先法。最低优先法的基本思想:首先按照最低位在这里插入图片描述进行排序,再对高一位关键字在这里插入图片描述进行排序,依次类推直到所有关键字都排序完毕。这种排序方法不通过比较关键字大小,而是通过分配和收集来实现。其最有代表性的例子便是扑克牌的排序。其中可以将扑克牌的52张牌按花色和值分成两个关键字,其关系大小为:花色:梅花<方块<红桃<黑桃
值:2<3<4<5<6<7<8<9<10<J<Q<K<A
且花色关键字等级高于值关键字。如果按扑克牌的花色和值进行升序排序,则可得如下序列:梅花2<梅花3<…<梅花A<方块2<方块3<…<方块A<红桃2<红桃3<…<红桃A<黑桃2<黑桃3<…<黑桃A。即对于两张牌,不论值多少,花色高的牌大于花色低的牌,而只有当花色相同时,才由值来确定大小。

链式基数排序
对于单关键字的序列,也可以通过将关键字拆分成若干项,每一项都看作是一个新的关键字,则可以用上述多关键字排序方法对单关键字的序列进行排序。
比如对于一个2位的整数,可以将其按照位数拆分成2项。这样拆分后,每个关键字的范围都相同(均为0~9),这样的关键字可能出现的符号个数称为“基”,例如,二进制数的基为2,十进制数的基为10。基于这样的设定,可以通过多关键字排序的方法方便地进行单关键字序列排序。本节所介绍的基数排序是用到了单链表作为分配的“容器”,所以称之为链式基数排序
链式基数排序的操作步骤如下:
Step 1:建立待排序列的静态链表SL和分配记录用的若干个单链表。
Step 2:从最低位关键字开始,按关键字将SL中记录分配到各个单链表中。
Step 3:按照关键字的值从小到大从各个单链表中收集记录到静态链表SL中,重复Step2直至排序完成。
则链式基数排序算法的流程图如图所示:
在这里插入图片描述
算法分析
时间复杂度:设待排序列有n个记录,d个关键字,每个关键字的取值范围(基)为r,进行一趟分配的时间复杂度为O(n),一趟收集的时间复杂度为O®,总共要进行d趟分配和收集,因此链式基数排序的时间复杂度为O(d(n+r))。
空间复杂度:链式基数排序需要2r个指向队列的辅助空间,且需要n个用于静态链表的指针,因此其空间复杂度为O(n+rd)。
稳定性:链式基数排序是稳定的排序方法。

9.7 各种内部排序方法的比较讨论

列举出一些关于常见算法特点的结论。
(1)快速排序、堆排序、归并排序的平均时间复杂度最好。其中快速排序在平均时间性能上被认为是最优的一种排序算法,然而在最坏情况下,快速排序的时间性能比不上堆排序和归并排序。并且在待排序列的记录个数较多时,归并排序比快速排序要更快,但其所需要的辅助空间更多。
(2)直接插入排序思路明了、算法简单,是一种很常用的排序算法。并且当待排序列基本有序或者待排序列的记录数量较小时,它是最优的排序算法。因此直接插入排序经常会与快速排序、归并排序这类平均时间性能优良的排序算法结合起来使用。
(3)基数排序的时间复杂度为O(d(rd+n)),因此当待排序列的记录数量n很大而关键字长度较小时,其时间性能较好。
(4)从空间复杂度上看,大多数的排序算法所需要的辅助空间为O(1)。但快速排序和归并排序例外,分别为O(nlog2n)和O(n)。而基数排序的空间复杂度则与关键字的数量d以及基数r有关。
(5)从稳定性上看,属于稳定排序算法的有直接插入排序、简单选择排序、归并排序和基数排序,属于不稳定排序算法的有希尔排序、快速排序和堆排序。
(6)从算法本身的复杂度上看,直接插入排序、简单选择排序较容易理解,属于简单算法,其时间性能理论上较差;而另一类像希尔排序、快速排序、堆排序和归并排序这样较为复杂的算法,属于改进算法,其时间性能理论上较好。
(7)从待排记录个数n的角度看,当n越小时,采用简单排序算法更为合适;而当n很大时,采用改进算法更加合适。这是因为当n较小时,O(n2)与O(nlog2n)的差距不是很大,此时使用简单算法在程序设计上将更为方便。表9.2给出了本章所讨论的几种算法的时间复杂度和空间复杂度。

几种内部排序算法性能的比较:
在这里插入图片描述
其中,在基数排序中,待排序列有n个记录,d个关键字,每个关键字的取值范围为r。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值