B树的插入和删除

B树和B+树的插入、删除图文详解 1. B树 1. B树的定义 B树也称B-树,它是一颗多路平衡查找树。我们描述一颗B树时需要指定它的阶数,阶数表示了一个结点最多有多少个孩子结点,一般用字母m表示阶数。当m取2时,就是我们常见的二叉搜索树。 一颗m阶的B树定义如下: 1)每个结点最多有m-1个关键字。 2)根结点最少可以只有1个关键字。 3)非根结点至少有Math.ceil(m/2)-1个关键字。 4)每个结点中的关键字都按照从小到大的顺序排列,每个关键字的左子树中的所有关键字都小于它,而右子树中的所有关键字都大于它。 5) 阅读详情

B-Tree 翻译过来为: B树,B-树
下面代码可以直接运行,我思路还是简单,就是调代码花了好久
供大家参考(除了结构体定义以外,没有参考任何网站,纯自己的思路)

#include<iostream>
#include <vld.h>
#include <queue>
using namespace std;

#define M 5  //奇数
#define MAXNUM (M-1)
#define MINNUM (M/2)
#define KeyType char

class BNode;

typedef struct
{
    BNode *pnode;
    int index;
    bool tag;
}Result;

typedef struct{} Record;

typedef struct
{
    KeyType key;
    Record *recptr;
}ElemType;

class BNode
{
public:
    BNode(ElemType et)
    {
        data[1] = et;
        num = 1;
        parent = NULL;
        for (int i = 0; i <= M; i++)
            sub[i] = NULL;
    }
    BNode(BNode *left, int first, int end)
    {
        num = end - first + 1;
        parent = NULL;
        /*改sub*/
        for (int i = 0; i <= num; i++)
        {
            sub[i] = NULL;
            if (left->sub[first - 1 + i])
            {
                sub[i] = left->sub[first - 1 + i];
                left->sub[first - 1 + i]->parent = this;
            }
        }
        for (int i = 1; i <= num; i++)
            data[i] = left->data[first++];
    }
    ~BNode(){}
public:
    int num;
    BNode *parent;
    ElemType data[M + 1];
    BNode *sub[M + 1];
};
class BTree
{
private:
    BNode *root;
public:
    BTree() :root(NULL){}
    Result findValue(KeyType kx)
    {
        ////////////////////////////////////LaoYang Programing////////////////////////////////////////////////
        Result res = { NULL, -1, false };
        BNode *ptr = root;
        while (ptr)
        {
            ptr->data[0].key = kx;
            int i = ptr->num;
            while (kx < ptr->data[i].key)
                --i;
            res.pnode = ptr;
            res.index = i;
            if (i > 0 && ptr->data[i].key == kx)
            {
                res.tag = true;
                break;
            }
            ptr = ptr->sub[i];
        }
        return res;
    }
    Result SearchValue(BNode *ptr, KeyType kx)
    {
        Result res = { NULL, -1, false };
        if (ptr != NULL)
        {
            ptr->data[0].key = kx;
            int i = ptr->num;
            while (kx < ptr->data[i].key)
                i--;
            res.index = i;
            res.pnode = ptr;
            if (i > 0 && ptr->data[i].key == kx)
                res.tag = true;
            else if (ptr->sub[i])
                res = SearchValue(ptr->sub[i], kx);
        }
        return res;
    }
    bool Insert(ElemType et)
    {
        if (root == NULL)
        {
            root = new BNode(et);
            return true;
        }
        //Result res = SearchValue(root, et.key); 
        Result res = findValue(et.key);
        if (res.tag)
            return false;
        BNode *pa = res.pnode;
        //把数据插入到node中
        insert_data(pa, et);

        if (pa->num == M)//如果已经满了
            split(pa);//要分裂
        return true;
    }
    void split(BNode *node)
    {
        if (node)
        {
            //改变原节点
            node->num = 2;
            //创建右节点
            BNode *right = new BNode(node, M / 2 + 2, M);

            BNode *pa = node->parent;
            /*分裂到了root*/
            if (!pa)
            {
                BNode *newRoot = new BNode(node->data[M / 2 + 1]);
                newRoot->sub[0] = node;
                newRoot->sub[1] = right;
                node->parent = newRoot;
                right->parent = newRoot;
                node->num = M / 2;
                root = newRoot;
            }
            else //没有分裂到root
            {
                //把et插入到父节点数据域中
                int index = insert_data(pa, node->data[3]);
                pa->sub[index] = right;
                right->parent = pa;
                //判断是否需要向上继续分裂
                if (pa->num > MAXNUM)
                    split(pa);
            }
        }
    }
    int insert_data(BNode *node, ElemType et)
    {
        int i = node->num;
        while (node->data[i].key > et.key && i > 0)
        {
            node->data[i + 1] = node->data[i];
            node->sub[i + 1] = node->sub[i];
            i--;
        }
        node->data[i + 1] = et;
        node->sub[i + 1] = NULL;
        node->num++;
        return i + 1;
    }
    void InOrder(BNode *ptr)
    {
        if (ptr)
        {
            InOrder(ptr->sub[0]);
            for (int i = 1; i <= ptr->num; i++)
            {
                cout << ptr->data[i].key << "  ";
                InOrder(ptr->sub[i]);
            }
        }
    }
    void InOrder()
    {
        InOrder(root);
    }
    void layer_print()
    {
        queue<BNode*> q;
        BNode* node;
        if (!root)
        {
            cout << "没有节点了" << endl;
            return;
        }
        q.push(root);
        while (!q.empty())
        {
            node = q.front();
            q.pop();
            for (int i = 0; i <= node->num; i++)
            {
                if (node->sub[i])
                    q.push(node->sub[i]);
            }
            for (int i = 1; i <= node->num; i++)
                cout << node->data[i].key << "  ";
            cout << endl;
        }
    }
    //////////////////////////////删除//////////////////////////////////////////////
    bool Remove(ElemType et)
    {
        if (!root) return false;

        Result res = findValue(et.key);
        BNode *node = res.pnode;
        BNode *pre = FindPrev(node, res.index);
        BNode *next = FindNext(node, res.index);
        BNode *adjNode = remove_key(node,pre,next,res.index,et.key);

        if (adjNode->parent && adjNode->num < MINNUM)
            Adjust_Leaf(adjNode);
        else if (!adjNode->parent && !adjNode->num)
        {
            delete root;
            root = NULL;
        }
    }
    void remove_key_pre(BNode *node, BNode *pre, int index, KeyType k)
    {
        node->data[index] = pre->data[pre->num];
        pre->num--;
    }
    void remove_key_next(BNode *node, BNode *next, int index, KeyType k)
    {
        node->data[index] = next->data[1];
        for (int i = 1; i < next->num; i++)
            next->data[i] = next->data[i + 1];
        next->num--;
    }
    BNode* remove_key(BNode *node, BNode *pre, BNode *next, int index, KeyType k)
    {
        if (pre && pre->num > MINNUM)
        {
            remove_key_pre(node, pre, index, k);
            return pre;
        }
        else if (next && next->num > MINNUM)
        {
            remove_key_next(node, next, index, k);
            return next;
        }
        else if (pre)
        {
            remove_key_pre(node, pre, index, k);
            return pre;
        }
        else if (next)
        {
            remove_key_next(node, next, index, k);
            return next;
        }
        else
        {
            //叶节点
            while (index != node->num)
            {
                node->data[index] = node->data[index + 1];
                index++;
            }
            node->num--;
            return node;
        }
    }
    BNode *FindPrev(BNode *ptr,int index)
    {
        if (ptr = ptr->sub[index - 1])
        {
            while (ptr->sub[ptr->num])
                ptr = ptr->sub[ptr->num];
            return ptr;
        }
        return NULL;
    }
    BNode *FindNext(BNode *ptr, int index)
    {
        if (ptr = ptr->sub[index])
        {
            while (ptr->sub[0])
                ptr = ptr->sub[0];
            return ptr;
        }
        return NULL;
    }
    void borrow_left(BNode *node, BNode *left,BNode *pa,int index)
    {
        node->data[0] = pa->data[index];
        pa->data[index] = left->data[left->num];
        for (int i = node->num; i >= 0; i--)
        {
            node->data[i + 1] = node->data[i];
            node->sub[i + 1] = node->sub[i];
        }
        node->sub[0] = left->sub[left->num];
        if (left->sub[left->num])
            left->sub[left->num]->parent = node;

        node->num++;
        left->num--;
    }
    void borrow_right(BNode *node, BNode *right, BNode *pa, int index)
    {
        node->data[node->num + 1] = pa->data[index];
        pa->data[index] = right->data[0];
        node->sub[node->num + 1] = right->sub[0];
        if (right->sub[0])
            right->sub[0]->parent = node;
        for (int i = 1; i < right->num; i++)
            right->data[i] = right->data[i + 1];
        for (int i = 0; i < right->num; i++)
            right->sub[i] = right->sub[i + 1];

        node->num++;
        right->num--;
    }
    void mergeNode(BNode *left,BNode *right,BNode* pa, int index)
    {
        if (!left)
            left = new BNode(pa->data[index + 1]);
        else
            left->data[++left->num] = pa->data[index + 1];
        int num = left->num;
        if (right)
        {
            //调整left兄弟
            for (int i = 1; i <= right->num; i++)
                left->data[num + i] = right->data[i];
            for (int i = 0; i <= right->num; i++)
            {
                left->sub[num + i] = right->sub[i];
                if (right->sub[i])
                    right->sub[i]->parent = left;
            }
            left->num += right->num;
        }
        //调整父节点
        if (pa->num == 1)
        {
            //这时候要换根节点
            left->parent = NULL;
            root = left;
            //不能在里面删除当前root
            //delete pa;
            //pa = NULL;
            pa->num = -1;//标记
        }
        else
        {
            for (int i = index + 1; i < pa->num; i++)
            {
                pa->data[i] = pa->data[i + 1];
                pa->sub[i] = pa->sub[i + 1];
            }
            pa->num--;
        }
        delete right;
    }
    void Adjust_Leaf(BNode *node)
    {
        BNode *leftBro = NULL, *rightBro = NULL, *parent = NULL;
        parent = node->parent;
        //找出node在父节点中的index
        int index = find_index(node,parent);

        if (index - 1 >= 0)
            leftBro = parent->sub[index - 1];
        if (index + 1 <= node->num)
            rightBro = parent->sub[index + 1];

        if (index - 1 < 0)
        {
            //没有左兄弟   向右借
            if (rightBro->num > MINNUM)
                borrow_right(node, rightBro, parent, index);
            //右兄弟没钱,和右兄弟合并
            else
                mergeNode(node, rightBro, parent, index);
        }
        else if (index + 1 <= MAXNUM)
        {
            //没有右兄弟   向左借
            if (leftBro->num > MINNUM)
                borrow_left(node, leftBro, parent, index);
            //左兄弟没钱,和左兄弟合并
            else
                mergeNode(leftBro, node, parent, index - 1);
        }
        else
        {
            //有两兄弟,优先向左借
            if (leftBro->num > MINNUM)
                borrow_left(node, leftBro, parent, index);
            else if (rightBro->num > MINNUM)
                borrow_right(node, rightBro, parent, index);
            else
                mergeNode(leftBro, node, parent, index);
        }
        if (parent->num == -1)
        {
            delete parent;
            parent = NULL;
            return;
        }
        if (parent->num < MINNUM && parent->parent)
            Adjust_Leaf(parent);
    }
    //找出ptr在父节点中的index
    int find_index(BNode *ptr, BNode *pa)
    {
        KeyType min = ptr->data[1].key;
        int i;
        for (i = 1; i <= pa->num; i++)
        {
            if (min < pa->data[i].key)
            {
                return i - 1;
            }
        }
        return i - 1;
    }
};

int main()
{
    KeyType ar[] = "QWERTYUIOPASDFGHJKLZXCVBNM";
    int n = sizeof(ar) / sizeof(ar[0]) - 1;
    ElemType item;
    BTree root;
    for (int i = 0; i < n; i++)
    {
        item.key = ar[i];
        item.recptr = NULL;
        root.Insert(item);
        root.InOrder();
        /*cout << "★★" << endl;
        root.layer_print();*/
        cout << endl << "------------------------------------添加--------------------------------------" << ar[i] << endl;
    }
    for (int i = 0; i < n; i++)
    {
        item.key = ar[i];
        item.recptr = NULL;
        root.Remove(item);
        root.InOrder();
        /*cout << "★★" << endl;
        root.layer_print();*/
        cout << endl << "------------------------------------删除--------------------------------------" << ar[i] << endl;
    }
    system("pause");
}
B-树的性质及插入和删除操作 阅读详情

相关推荐

2025虚幻游戏逆向工程解包尝试

2025虚幻游戏逆向工程解包指南 本文详细介绍了虚幻引擎5游戏逆向解包的完整流程,主要包括获取AES密钥、生成映射文件和导出资源三个关键步骤。作者在实际操作中遇到诸多难题:AES密钥获取工具存在加壳保护问题,映射文件生成器依赖复杂的VS编译环境,DLL注入工具的使用也存在技术门槛。通过多次尝试,作者发现部分游戏可直接搜索现成的AES密钥,而映射文件生成需要额外下载Memcury依赖库才能正常编译。文章提供了相关工具的下载链接和具体操作说明,但同时也指出每个环节都可能出现意外状况,逆向工程实际执行过程远比理论

wsdchong的博客 6146

B树的插入、删除操作

一、简介 B树是什么? 1970年,R.Bayer和E.mccreight提出了一种适用于外查找的树,它是一种平衡的多叉树,称为B树(或B-树、B_树)。 一棵m阶B树(balanced tree of order m)是一棵平衡的m路搜索树。它或者是空树,或者是满足下列性质的树: 1、根结点至少有两个子女; 2、每个非根节点所包含的关键字个数 j 满足:┌m/2┐ - 1 <= j <= m - 1; 3、除根结点以外的所有结点(不包括叶子结点)的度数正好是关键字总数加1,故内部子树个数

qq_44654974的博客 5523

遥感SCI期刊模板下载教程———IEEE TGRS、GRSL、JSTARS

IEEE下的期刊模板下载,以IEEE TGRS 为例。

海淀小天的blog 2万+

B树的插入与删除

B树的删除(仅考虑阶数m>=3的情形) 在非叶节点中删除关键码,只需从关键码右侧指针指向的子树中寻找最小关键码(沿最左侧指针向下走到叶节点,叶节点最左侧关键码即是)替换该关键码,并从最小关键码所在叶节点删除该最小关键码即可。这样只讨论在叶节点中删除关键码。 在叶节点中删除给定关键码,先删去该关键码及其右侧空指针,然后若该叶节点为根节点,则删除操作结束(删除后的B树可能为空树),若该叶节点不为根节点且关键码数大于等于ceil(m/2)-1,则删除操作结束。若该叶节点不为根节点且关键码数等于ceil(

naturerun的博客 2037

带挂牵引车前向运动模型推导及仿真实现

牵引车-半挂车的车辆结构与普通的车辆相比增加了一个半挂车,它们之间通过鞍座相连接,为了分析半挂牵引车运动过程中的位姿和状态,本文将基于车辆的机械结构建立对应的运动学模型,该模型基于以下假设: 车辆行驶过程中,道路平坦且无凸凹; 车辆低速行驶,且运行过程中车身无侧倾和俯仰运动; 车辆行驶过程中,轮胎无形变,无侧向滑动,且无侧向力; 牵引车和半挂车均满足阿克曼转向几何原理; 牵引车与半挂车不会发现折叠。

jianmo的博客 3181

【Oracle数据库】Oracle11g数据库下载与安装教程(超详细安装图解)

Oracle11g是Oracle公司出的一个比较轻量版的数据库,这里重点说一下在window系统上如何安装Oracle11g, Oracle11g是很早之前的安装包,win7 系统安装时不会遇到环境不满足最低要求的提示,win11系统安装时会提醒环境不满足,修改配置文件即可(注意:先安装oracle服务端/oracle客户端,再安装第三方工具(PL/ SQL Developer,DBeaver等)服务器端环境概述:ORACLE数据库版本:Oracle 11g 64位(11.2.0)

qq_34463511的博客 1万+

【数据结构日记】(一) B树的插入和删除

B树,Balanced Tree,平衡的多叉树

qq_41428696的博客 731

【STM32】STM32 CANFD外设的几种消息接收过滤模式

在控制器区域网络(CAN)系统中,正确配置消息过滤器对于有效管理网络通信至关重要。特别是在使用Flexible Data-rate Controller Area Network(FDCAN)时,选择合适的过滤器类型可以大大提高网络效率和消息处理速度。

林愿留的博客 6225

B树(插入、删除)

B树(插入、删除)

m0_65213200的博客 2369

华为OD机试2025C卷 - 精准核酸检测 (C++ & Python & JAVA & JS & GO)

华为OD机试2025C卷 精准核酸检测,提供Java、C++、Python、Go、JavaScript源码实现,并提供完整思路讲解

qq_45776114的博客 1707

信号完整性之串扰

1.前言 串扰(Crosstalk)是指信号线之间由互感、互容而引起的耦合,由于这种耦合的存在,当某一信号线发生电平翻转时,在附近的信号线上将感应到一定程度的噪声。 2. 电路设计中抑制串扰的方法 2.1 控制高速信号线之间的间距和平行走线的长度 多个高速信号长距离平行走线时,其间距应遵循3W原则,如下图所示: 3W原则指两相邻信号线的中心间距不少于信号线宽度的3倍,当满足3W原则时,信号线之间...

sinat_15677011的博客 1万+

【数据结构】B树的介绍及结点的插入删除

B树的概念与特点,B树的结点删除与插入操作

mrqiuwen的博客 2919

在 Eclipse 中接入 DeepSeek:开启 Java 开发新效率

DeepSeek 能够根据自然语言描述,精准生成高质量的 Java 代码片段。无论是简单的方法编写,比如 “编写一个 Java 方法,用于计算两个整数的乘积”,还是复杂的类和功能模块创建,例如 “创建一个 Java 类,实现文件的读写操作,并包含异常处理机制”,它都能快速给出合理且可运行的代码示例。DeepSeek 生成的代码不仅实现了基本功能,还遵循 Java 的编码规范,添加了必要的注释,让代码更易于理解和维护,大大节省了开发者从头编写代码的时间和精力。

远程部署调试 运行安装 项目调试 二次开发 项目技术新 持续迭代 部分源码免费分享 4065

B树和B+树的插入、删除

树也称树,它是一颗多路平衡查找树。我们描述一颗树时需要指定它的阶数,阶数表示了一个结点最多有多少个孩子结点,用字母表示阶数。当取时,就是我们常见的二叉搜索树。一颗阶的每个结点最多有个关键字。根结点最少可以只有个关键字。非根结点至少有个关键字。每个结点中的关键字都按照从小到大的顺序排列,每个关键字的左子树中的所有关键字都小于该结点,而右子树中的所有关键字都大于该结点。所有叶子结点都位于同一层,或者说根结点到每个叶子结点的长度都相同。上图是一颗阶数为的树。

weixin_45092290的博客 4621

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

B树和B+树的插入和删除

https://www.jianshu.com/p/52ad1ae8aedb B树和B+树的插入和删除 一. B树 1.1B树的定义 B树也称B-树,它是一颗多路平衡查找树。我们描述一颗B树时需要指定它的阶数,阶数表示了一个结点最多有多少个孩子结点,一般用字母m表示阶数。当m取2时,就是我们常见的二叉搜索树。 一颗m阶的B树定义如下: 每个结点最多有m-1个关键字。 根结点最少可以只有1个关键字。 非根结点至少有Math.ceil(m/2)-1个关键字。 每个结点中的关键字都按照.

yygr的博客 2004

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

【数据库】B树和B+树的插入删除的实现过程

知识准备 在总结B树和B+树插入和删除的过程之前,首先要明确一下B树和B+树的几个性质: 对于B树和B+树的根节点都至少有一个根节点; 对于B树和B+树的非根节点元素,每个节点中的关键字的个数的范围为:(假设一个m阶的B/B+树)[m/2,m-1]。(闭区间) 对于每个节点中的关键字都按照升序进行排列。 对于B树,每个关键字的左子树中的所有关键字都小于它,而右子树中的所有关键字都大于它。 对于B树,所有叶子结点都位于同一层,或者说根结点到每个叶子结点的长度都相同。 除此之外B+树还有如下性质: B+

xiongchu的博客 1881

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

7.12.B树的插入和删除

以上述图片的5阶B树为例,首先删除关键字60,由于60位于终端结点,所以直接删除即可,并且删除60之后,当前所操作的结点的关键字个数为3并没有低于5阶B树所要求的下限2,如下图:如上图,接下来删除关键字80,80位于非终端结点中,且80删除之后根结点就不存在了,之后该怎么做呢?可以找到80的直接前驱或直接后继来顶替80的位置,先看用80的直接前驱来顶替80的位置,80的直接前驱是77(找直接前驱的方法详情见"5.11.在线索二叉树中找前驱和后继"),如下图:如上图,

ADCvbV的博客 1273

B树和B+树的插入、删除图文详解(转)

转载自:https://www.cnblogs.com/nullzx/p/8729425.html 简介:本文主要介绍了B树和B+树的插入、删除操作。写这篇博客的目的是发现没有相关博客以举例的方式详细介绍B+树的相关操作,由于自身对某些细节也感到很迷惑,通过查阅相关资料,对B+树的操作有所顿悟,写下这篇博客以做记录。由于是自身对B+树的理解,肯定有考虑不周的情况,或者理解错误的地方,请留言指出。 ...

如是说的博客 1720

数据结构(C):B-树的插入和删除

1.B-树 B-树定义:一种平衡的多路查找树。用作索引组织文件,可减少访问外存次数,提高访问速度、减少时间。一棵m阶B-树或为空树,或满足下列特性: 1、树中每个结点至多有m个子树;(结点中的关键字个数最多m-1) 2、若根结点不是叶子结点,至少有两棵子树(根至少有一个关键字) 3、除根结点外,其余非叶子结点至少有m/2(下取整)棵子树。(比关键字个数多一个) 4.关键字的个数,范围是: m/2...

i6223671的博客 6808

B树和B+树的插入删除详解

前言:本文主要介绍了B树和B+树的插入、删除操作。写这篇博客的目的是发现没有相关博客以举例的方式详细介绍B+树的相关操作,由于自身对某些细节也感到很迷惑,通过查阅相关资料,对B+树的操作有所顿悟,写下这篇博客以做记录,希望对有需要的读者有所帮助。 1. B树 1.1 B树的定义 B树也称B-树,它是一颗多路平衡查找树。我们描述一颗B树时需要指定它的阶数,阶数表示了一个结点最多有多少个孩子结...

kingsir2020的博客 536

转:B树和B+树的插入、删除

转自: https://blog.youkuaiyun.com/qq_26222859/article/details/80631121?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonec

仅做个人笔记 276
上一篇: 蓝桥杯练习题P1001(大数乘法)
下一篇: 36辆车,6条跑道,无计时器,最少几次比赛可以选出前三
帅东
博客等级 码龄11年 676粉丝 88原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值