数据结构实验四:查找和排序算法实现

一、实验目的

1、各种排序算法的实现
2、各种查找算法实现

二、使用仪器、器材

微机一台
操作系统:WinXP
编程软件:C++

三、实验内容及原理

1、各种排序算法的实现
用随机函数生成16个2位正整数(10~99),实现插入排序、选择排序、冒泡排序、双向冒泡、快速排序、二路归并排序等多种排序算法,输出排序中间过程、统计关键字的比较次数和记录的移动次数。
2、各种查找算法实现
(1)顺序查找:使用数组或链表结构。用随机函数生成16个不重复的字母(’a’~’z’),键盘输入待查找的字母,返回查找成功与否,若成功则返回该字母所在的位置(序号),并计算比较次数。
(2)折半查找:用数组实现,查找前元素先排序。计算比较次数。分别用查找成功、不成功进行测试。
(3)二叉查找树:手工输入10个字母,生成一棵二叉查找树,用递归算法打印树结构或分别输出先序和中序遍历序列以确认其结构。键盘输入待查找的字母,计算比较次数。分别用查找成功、不成功进行测试。

四、实验过程原始数据记录

1、各种排序算法实现

#include "pch.h"
#include <iostream>
#include<time.h>
#include<math.h>
using namespace std;

//*************************数据元素
class RedType
{
public:
	int key; //关键字项
};
//************************顺序表
class SqList
{
	RedType r[20 + 1]; //顺序表最大长度+1,第0单元闲置或做哨兵
	int length;  //顺序表长度
public:
	void CreatList(); //随机生成16个2位正整数(10-99),创建顺序表
	void ShowResult(); //输出最终结果
	void InsertSort(); //1,直接插入排序,从小到大
	void SelectSort(); //2,选择排序
	void BubbleSort(); //3,冒泡排序
	void DoubleBubbleSort(); //4,双向冒泡排序

	void QuickSort();                //5,快速排序
	int Partition(int low, int high);//5,完成一趟快速排序,并返回 Low 位置
	void QSort(int low, int high);   //5,对子序列 [low.....high] 做快速排序

	void MergeSort();                                                 //6,二路归并排序
	void Merge(RedType R[], RedType T[], int low, int mid, int high); //6,将两个有序表排序后,归并到一个有序表中
	void MSort(RedType R[], RedType T[], int low, int high);          //6,划分有序表,通过 Merge 排序后合并;

	void ShellSort();              //7,希尔排序
	void ShellInsert(int dk);      //7,增量是 dk 的希尔插入排序

	void HeapSort();                  //8,堆排序
	void creatHeap();                 //8,建初堆
	void HeapAjust(int s, int m);     //8,筛选法调整堆
};

int main()
{
	SqList L;
	cout << "注:中间过程的“(”和“)”是括起已经排好序的部分" << endl;
	cout << "直接插入排序: " << endl;
	L.InsertSort();
	cout << "选择排序: " << endl;
	L.SelectSort();
	cout << "冒泡排序: " << endl;
	L.BubbleSort();
	cout << "双向冒泡排序: " << endl;
	L.DoubleBubbleSort();
	cout << "快速排序: " << endl;
	L.QuickSort();
	cout << "二路归并排序: " << endl;
	L.MergeSort();
	cout << "希尔排序: " << endl;
	L.ShellSort();
	cout << "堆排序: " << endl;
	L.HeapSort();
}


void SqList::CreatList()
{
	time_t t;
	srand((unsigned)time(&t));
	this->length = 16;
	cout << "创建随机16个2位正整数(10-99)顺序表: " << endl;
	for (int i = 1; i <= 16; i++)
	{
		this->r[i].key = rand()%89 + 10;
		cout << this->r[i].key << ends;
	}
	cout << endl << endl;
}

void SqList::ShowResult()
{
	cout << "最终结果:";
	for (int i = 1; i <= 16; i++)
	{
		cout << this->r[i].key << ends;
	}
	cout << endl <<endl;
}

void SqList::InsertSort()
{
	this->CreatList();
	int movetimes=0; //记录移动次数
	int keyCompare=0;  //记录关键字比较次数
	int sortimes = 0; //记录排序次数
	for (int i = 2; i <= this->length; ++i)
	{
		keyCompare++;
		if (this->r[i].key < this->r[i - 1].key) //上一个值比当前值大
		{
			this->r[0] = this->r[i];
			this->r[i] = this->r[i - 1]; //上一个值向后移
			movetimes++;
			int j = i - 2;
			keyCompare++;  //for循环里至少执行一次
			for (; this->r[0].key < this->r[j].key && j >= 0; --j) //从后向前,直到发现比当前值小的值,在已经排好序的序列里寻找位置
			{
				this->r[j + 1] = this->r[j]; //比当前值大则后移
				movetimes++;
				keyCompare++;
			}
			this->r[j + 1] = this->r[0];

			sortimes++; //排序次数+1
			cout << "第" << sortimes << "次排序:";
			for (int j = 1; j <= 16; j++)
			{
				if(j==i) cout << this->r[j].key <<" )" <<ends;
				else cout << this->r[j].key << ends;
			}
			cout << endl;
		}
	}
	cout << "统计关键字的比较次数、记录的移动次数分别为:" << keyCompare << ends << movetimes << endl;
	this->ShowResult();
}

void SqList::SelectSort()
{
	this->CreatList();
	int movetimes = 0; //记录移动次数
	int keyCompare = 0;  //记录关键字比较次数
	int sortimes = 0;  //记录排序次数
	for (int i = 1; i < this->length; ++i)
	{
		int k = i;
		for (int j = i + 1; j <= this->length; ++j) //从未排序中寻找最小值
		{
			keyCompare++;
			if (this->r[j].key < this->r[k].key) k = j;

		}
		if (k != i)  //不等则交换位置
		{
			RedType t = this->r[i];
			this->r[i] = this->r[k];
			this->r[k] = t;
			movetimes++;
		}

		sortimes++; //排序次数+1
		cout << "第" << sortimes << "次排序:";
		for (int j = 1; j <= 16; j++)
		{
			if (j == i) cout << this->r[j].key << " )" << ends;
			else cout << this->r[j].key << ends;
		}
		cout << endl;
	}

	cout << "统计关键字的比较次数、记录的移动次数分别为:" << keyCompare << ends << movetimes << endl;
	this->ShowResult();
}

void SqList::BubbleSort()
{
	this->CreatList();
	int movetimes = 0; //记录移动次数
	int keyCompare = 0;  //记录关键字比较次数
	int sortimes = 0;  //记录排序次数

	int m = this->length;
	int flag = 1; //用来标记某次排序是否交换过
	while ((m > 0) && (flag = 1))
	{
		flag = 0;
		for (int j = 1; j < m; ++j)
		{
			keyCompare++;
			if (this->r[j].key > this->r[j + 1].key)
			{
				flag = 1;
				RedType t = this->r[j];
				this->r[j] = this->r[j + 1];
				this->r[j + 1] = t;
				movetimes++;
			}
		}
		--m;
		if (flag == 1)
		{
			sortimes++; //排序次数+1
			cout << "第" << sortimes << "次排序:";
			for (int j = 1; j <= 16; j++)
			{
				if (j == m) cout << this->r[j].key << " (" << ends;
				else cout << this->r[j].key << ends;
			}
			cout << endl;
		}
	}
	cout << "统计关键字的比较次数、记录的移动次数分别为:" << keyCompare << ends << movetimes << endl;
	this->ShowResult();
}

void SqList::DoubleBubbleSort()
{
	this->CreatList();
	int movetimes = 0; //记录移动次数
	int keyCompare = 0;  //记录关键字比较次数
	int sortimes = 0;  //记录排序次数

	int m = this->length; //重的下沉
	int n = 0; //轻的上升
	int flag = 1; //用来标记某次排序是否交换过
	while ((m!=n) && (flag = 1))
	{
		flag = 0;
		for (int j = 1; j < m; ++j)
		{
			keyCompare++;
			if (this->r[j].key > this->r[j + 1].key)
			{
				flag = 1;
				RedType t = this->r[j];
				this->r[j] = this->r[j+1];
				this->r[j+1] = t;
				movetimes++;
			}
		}
		for (int j = m-1; j>n; --j)
		{
			keyCompare++;
			if (this->r[j].key > this->r[j + 1].key)
			{
				flag = 1;
				RedType t = this->r[j];
				this->r[j] = this->r[j + 1];
				this->r[j + 1] = t;
				movetimes++;
			}
		}
		--m;
		++n;
		if (flag == 1)
		{
			sortimes++; //排序次数+1
			cout << "第" << sortimes << "次排序:";
			for (int j = 1; j <= 16; j++)
			{
				if (j == n) cout << this->r[j].key << " )" << ends;
				else if (j == m) cout << this->r[j].key << " (" << ends;
				else cout << this->r[j].key << ends;
			}
			cout << endl;
		}
	}
	cout << "统计关键字的比较次数、记录的移动次数分别为:" << keyCompare << ends << movetimes << endl;
	this->ShowResult();
}


int Qmovetimes = 0; //记录移动次数
int QkeyCompare = 0;  //记录关键字比较次数
int Qsortimes = 0;  //记录排序次数
int Qflag = 1;
void SqList::QuickSort()
{
	this->CreatList();
	QSort(1, this->length);
	cout << "统计关键字的比较次数、记录的移动次数分别为:" << QkeyCompare << ends << Qmovetimes << endl;
	this->ShowResult();
}
int SqList::Partition(int low, int high)
{
	Qflag = 0;
	this->r[0] = this->r[low];
	int pivotkey = this->r[low].key;
	while (low < high)
	{
		QkeyCompare++;
		while (low < high && this->r[high].key >= pivotkey)
		{
			QkeyCompare++;
			--high;
		}
		if (low != high)
		{
			this->r[low] = this->r[high]; //low在前,high在后,high向前走,遇到high比low小,将low的值换为high的值
			Qmovetimes++;
			Qflag = 1;
		}
		QkeyCompare++;
		while (low < high && this->r[low].key <= pivotkey)
		{
			QkeyCompare++;
			++low;
		}
		if (low != high)
		{
			this->r[high] = this->r[low]; //low在前,high在后,low向后走,遇到high比low小,将high的值换为low的值
			Qmovetimes++;
			Qflag = 1;
		}
	}
	this->r[low] = this->r[0];
	if (Qflag == 1)
	{
		Qsortimes++; //排序次数+1
		cout << "第" << Qsortimes << "次排序:";
		for (int j = 1; j <= 16; j++)
		{
			cout << this->r[j].key << ends;
		}
		cout << endl;
	}
	return low;
}
void SqList::QSort(int low, int high)
{
	if (low < high)
	{
		int pivotloc = Partition(low, high);
		QSort(low, pivotloc-1);
		QSort(pivotloc + 1, high);
	}
}

int Mmovetimes = 0; //记录移动次数
int MkeyCompare = 0;  //记录关键字比较次数
int Msortimes = 0;  //记录排序次数
int Mflag = 1;
void SqList::MergeSort()
{
	this->CreatList();
	MSort(this->r, this->r, 1, this->length);
	cout << "统计关键字的比较次数、记录的移动次数分别为:" << MkeyCompare << ends << Mmovetimes << endl;
	this->ShowResult();
}
void SqList::Merge(RedType R[], RedType T[], int low, int mid, int high)
{
	int i = low;     //指向 R[low....mid] 的第一个元素
	int j = mid + 1; //指向 R[mid+1....high] 的第一个元素
	int k = low;     //指向元素进入 T[low...high]的位置 
	//cout << "i j k : " << i << ends << j << ends << k << endl;
	while (i <= mid && j <= high)  //直到 R[low....mid]或 R[mid+1....high]的全部元素进 T
	{
		MkeyCompare++;
		Mmovetimes++;
		if (R[i].key <= R[j].key) T[k++] = R[i++];  //值小的在R[low....mid],进 T, T的位置指向下一个,R[low....mid] 也指向下一个元素
		else T[k++] = R[j++];                       //值小的在R[mid+1....high],进 T, T的位置指向下一个,R[mid+1....high] 也指向下一个元素
	}
	while (i <= mid)
	{
		T[k++] = R[i++]; // R[low....mid]剩余元素进 T
		Mmovetimes++;
	}
	while (j <= high)
	{
		T[k++] = R[j++];// R[mid+1....high]剩余元素进 T
		Mmovetimes++;
	}
	if (low == 1)
	{
		Msortimes++; //排序次数+1
		cout << "第" << Msortimes << "趟归并:";
		for (int j = low; j <= high; j++)
		{
			cout << T[j].key << ends;
		}
		cout << endl;
	}
}
void SqList::MSort(RedType R[], RedType T[], int low, int high)
{
	if (low == high) T[low] = R[low];  //序列内只有单个值时返回
	else
	{
		int mid = (low + high) / 2; //划分点 mid
		RedType *S=new RedType[21];
		MSort(R, S, low, mid);     //对子序列 R[low...mid] 递归并排序,结果放入 S[low...mid]中
		MSort(R, S, mid+1, high);  //对子序列 R[mid+1...high] 递归并排序,结果放入 S[mid+1...high]中
		Merge(S, T, low, mid, high);  //将 S[low...mid] 和 S[mid+1...high]合并到 T[low...high]
	}
}

int Smovetimes = 0; //记录移动次数
int SkeyCompare = 0;  //记录关键字比较次数
int Ssortimes = 0;  //记录排序次数
void SqList::ShellSort()
{
	//"增量为 7 5 3 1" 
	this->CreatList();
	for (int k = 7; k >0;)
	{
		ShellInsert(k);
		k -= 2;
	}
	this->ShowResult();
}
void SqList::ShellInsert(int dk)
{
	for (int i = dk + 1; i <= this->length; i++)
	{
		SkeyCompare++;
		if (this->r[i].key < this->r[i - dk].key)
		{
			this->r[0] = this->r[i];
			int j = i - dk;
			SkeyCompare++;
			for ( j; j > 0 && this->r[0].key < this->r[j].key; j -= dk)
			{
				this->r[j + dk] = this->r[j];
				Smovetimes++;
				SkeyCompare++;
			}
			this->r[j + dk] = this->r[0];
			Smovetimes++;
		}
	}
	Ssortimes++; //排序次数+1
	cout << "第" << Ssortimes << "趟增量为"<<dk<<"的排序:";
	for (int j = 1; j <= 16; j++)
	{
		 cout << this->r[j].key << ends;
	}
	cout << endl;
}


int Hmovetimes = 0; //记录移动次数
int HkeyCompare = 0;  //记录关键字比较次数
int Hsortimes = 0;  //记录排序次数
void SqList::HeapSort()
{
	this->CreatList();
	creatHeap(); //建大根堆
	int i = this->length;
	for (; i > 1; i--)
	{
		RedType x = this->r[1];  //栈顶与未排序序列的最后一个,即最小值,对换
		this->r[1] = this->r[i];
		this->r[i] = x;
		Hmovetimes++;
		HeapAjust(1, i - 1);  //重新调整大根堆
	}
	cout << "统计关键字的比较次数、记录的移动次数分别为:" << HkeyCompare << ends << Hmovetimes << endl;
	this->ShowResult();
}
void SqList::creatHeap()
{
	int n = this->length;
	for (int i = n / 2; i > 0; i--)
		HeapAjust(i, n); //初始时,未进行排列,故未排列序列一直等于初始序列长
}
void SqList::HeapAjust(int s, int m)
{
	RedType rc = this->r[s];
	for (int j = 2 * s; j <= m; j *= 2) //逐层遍历
	{
		HkeyCompare++;
		if (j < m&&this->r[j].key < this->r[j + 1].key) ++j; //指向另一个儿子
		HkeyCompare++;
		if (rc.key >= this->r[j].key) break;  //rc的值比它的儿子大,无需调换
		this->r[s] = this->r[j];           //儿子比它大,换位
		s = j;
		Hmovetimes++;
	}
	this->r[s] = rc;
	Hmovetimes++;
	if (m != this->length)
	{
		Hsortimes++; //排序次数+1
		cout << "第" << Hsortimes << "次交换操作以及调整栈堆之后:";
		for (int j = 1; j <= 16; j++)
		{
			cout << this->r[j].key << ends;
		}
		cout << endl;
	}
}

2、各种查找算法实现

#include "pch.h"
#include <iostream>
#include<time.h>
#include<math.h>
using namespace std;

class SSTable
{
	char *keys = new char[17];  //使用数组结构
	int length;
public:
	int compare;
public:
	void creatsstable();    //用随机函数生成16个不重复的字母(’a’~’z’)
	int Search_seq(char k);  //顺序查找,若成功则返回位置(序号)
	void InsertSort();        //插入排序
	int Search_bin();  //折半查找
	
};
int main()
{
	SSTable ST;
	ST.creatsstable();
	
	cout << "顺序查找:" << endl ;
	char k = 1;
	while (k!='0')
	{
		cout << "请输入要查找的字母( 范围为 a-z, 按0退出):";
		cin >> k;
		if (k >= 'a'&&k <= 'z')
		{
			int position = ST.Search_seq(k);
			if (position == 0)
			{
				cout << "查找" << ST.compare << "次,"<<"查无此值! ";
			}
			else cout << "查找" << ST.compare << "次," << "该值在第" << position << " 个位置(序号)" << endl ;
		}
		else if (k == '0') break;
		else  cout << "输入错误 ! ";
	}

	cout << endl<< "折半查找:" << endl ;
	ST.Search_bin();
}

void SSTable::creatsstable()
{
	time_t t;
	srand((unsigned)time(&t));
	this->length = 16;
	this->compare = 0;
	cout << "创建随机16个不重复的字母('a'- 'z')顺序表: " << ends;
	for (int i = 1; i <= 16; i++)
	{
		char k;
		int flag = 0;
		while (flag == 0)
		{
			flag = 1;
			k = 'a' + rand() % ('z' - 'a' + 1);
			for (int j = 1; j < i; j++)
			{
				if (k == this->keys[j]) flag = 0;
			}
		}
		this->keys[i] = k;
		cout << this->keys[i] << ends;
	}
	cout << endl << endl;
}

int SSTable::Search_seq(char k)
{
	this->compare = 1; //至少比较一次
	int i = this->length;
	for (; i >= 1; --i)
	{
		this->compare++;
		if (this->keys[i] == k) return i;
	}
	return 0;
}

void SSTable::InsertSort()
{
	
	for (int i = 2; i <= this->length; ++i)
	{
		if (this->keys[i] < this->keys[i-1]) //上一个值比当前值大
		{
			this->keys[0] = this->keys[i];
			this->keys[i] = this->keys[i - 1]; //上一个值向后移
			int j = i - 2;
			for (; this->keys[0] < this->keys[j] && j >= 0; --j) //从后向前,直到发现比当前值小的值,在已经排好序的序列里寻找位置
			{
				this->keys[j + 1] = this->keys[j]; //比当前值大则后移
			}
			this->keys[j + 1] = this->keys[0];
		}
	}
	cout << "排序后的数组:";
	for (int j = 1; j <= 16; j++)
	{
		 cout << this->keys[j] << ends;
	}
	cout << endl;
}

int SSTable::Search_bin()
{
	char k = 1;
	this->InsertSort();
	while (k != '0')
	{
		cout << "请输入要查找的字母( 范围为 a-z, 按0退出):";
		cin >> k;
		if (k >= 'a'&&k <= 'z')
		{
			this->compare = 0; //至少比较一次
			int position = 0;
			//*******************************************************开始查找
			int low = 1, high = this->length;
			while ((low <= high)&&position==0)
			{
				int mid = (low + high) / 2;
				this->compare++;
				if (k == this->keys[mid]) position = mid;
				else if (k < this->keys[mid]) high = mid - 1;
				else low = mid + 1;
			}
			cout << "比较" << this->compare << "次,";
			//*****************************************************查找结束
			if (position == 0)
			{
				cout << "查无此值! ";
			}
			else cout << "该值在第" << position << " 个位置(序号)" << endl;
		}
		else if (k == '0') break;
		else  cout << "输入错误 ! ";
	}
	return 0;
}

二叉查找树

// (3)二叉查找树:手工输入10个字母,生成一棵二叉查找树,
//     用递归算法打印树结构或分别输出先序和中序遍历序列以确认其结构。
//     键盘输入待查找的字母,计算比较次数。分别用查找成功、不成功进行测试。

#include "pch.h"
#include <iostream>
using namespace std;
#define OK 1
#define ERROR 0
typedef char Status;

typedef struct
{
	char key;
}ElemType;
typedef struct BSTNode
{
	ElemType data;
	struct BSTNode *lchild, *rchild;
}BSTNode, *BSTree;


//********************************************插入新结点
void InsertBBS(BSTree &T, ElemType e)
{
	if ( T==NULL )
	{
		BSTNode *s=new BSTNode;
		s->data = e;
		s->lchild = s->rchild = NULL;
		T = s;
		cout << T->data.key << "插入成功" << endl;
	}
	else if (e.key < T->data.key)	{InsertBBS(T->lchild, e);}
	else if (e.key > T->data.key)	{InsertBBS(T->rchild, e);}
	else if (e.key == T->data.key)
	{
		cout << T->data.key << "相等" << endl;
		BSTNode *s = new BSTNode;
		BSTNode *p = new BSTNode;
		p = T->lchild;
		s->data = e;
		s->lchild = p;
		s->rchild = NULL;
		T->lchild = s;
	}
}

//******************************************手动输入10个字母生成二叉树
void creatBSTree(BSTree &T)
{
	for (int i = 0; i < 10; i++)  //十个字母
	{
		cout << "请输入第" << i+1 << "个字母( 范围为 a-Z ):";
		char k = 0;
		while (k == 0)  //输入是字母时跳出循环
		{
			cin >> k;
			ElemType e;
			e.key = k;
			if (k >= 'A'&& k <= 'z') { InsertBBS(T, e); }
			else { k = 0; cout << "输入错误 ! 请重新输入: "; }
		}
	}
	cout << "二叉排序树创建成功" << endl;
}

//*********************************************中序遍历输出结构
void InOrder(BSTree T)
{
	if (T != NULL)
	{
		InOrder(T->lchild);
		cout << T->data.key << ends;
		InOrder(T->rchild);
	}
}
//*********************************************先序遍历输出结构
void PreOrder(BSTree T)
{
	if (T != NULL)
	{
		cout << T->data.key << ends;
		PreOrder(T->lchild);
		PreOrder(T->rchild);
	}
}

//************************************************二叉排序树的查找
int compare ;
BSTree SearchBBT(BSTree T, char k)
{
	compare++;
	if (T == NULL || k == T->data.key) return T;  //成功则返回T,失败返回空指针
	else if (k < T->data.key) { return SearchBBT(T->lchild, k); }  //比T小,在左儿子找
	else   return SearchBBT(T->rchild, k);   //比T小,在右儿子找}
}


int main()
{
	BSTree T = NULL;
	creatBSTree(T);
	cout << "先序遍历:";
	PreOrder(T);
	cout << endl;
	cout << "中序遍历:";
	InOrder(T);
	cout << endl;

	char k = 1;
	while (k != '0')
	{
		cout << "请输入要查找的字母(按0退出):";
		cin >> k;
		if (k >= 'A'&& k <= 'z')
		{
			BSTNode *p = new BSTNode;
			compare = 0;
			p = SearchBBT(T, k);
			if (p) cout << "比较" << compare << "次," << p->data.key << "查找成功!" << endl << endl;
			else  cout << "比较" << compare << "次," << "查无此值! ";
		}
		else if (k == '0') break;
		else  cout << "输入错误 ! ";
	}
}

五、实验结果及分析

1、各种排序算法的实现
(1)插入排序
在这里插入图片描述
(2)选择排序
在这里插入图片描述
(3)冒泡排序
在这里插入图片描述
(4)双向冒泡排序
在这里插入图片描述
(5)快速排序
在这里插入图片描述
(6)二路归并排序
在这里插入图片描述
(7)希尔排序
在这里插入图片描述
(8)堆排序
在这里插入图片描述
2,各种查找算法的实现
(1)顺序查找和折半查找
在这里插入图片描述
(2)二叉查找树
在这里插入图片描述
一开始是用class写二叉查找树的,结果无法写入在main里定义好的树T,T无法扩展左右儿子,只好用结构写了。

  • 13
    点赞
  • 71
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值