数据结构与算法

这篇博客详细介绍了数据结构的基础知识,包括顺序表、链表(无头单向、有头单向、单向循环)、栈(顺序栈、链栈)、队列(顺序队列、链队列)的实现,以及查找方法(哈希、二分、分块、顺序)和排序算法(快速、选择、插值、冒泡)。示例代码涵盖了这些数据结构和算法的基本操作,如插入、删除、遍历等。此外,还讨论了二叉树的概念和遍历方式,以及哈夫曼树和哈夫曼编码。
摘要由CSDN通过智能技术生成

1、顺序表( 数组,在内存当中连续存储,数据元素个数固定 )

1、顺序存的储的遍历以及、增、删、改、查 ( 在代码中 )

#include<stdio.h>
#include<stdlib.h>
#define N 100
typedef struct
{
    int data[N];
    int last;
}seqlist_t;
///
********************申请空间***********************
//
seqlist_t* createSeqlist_t()
{
    seqlist_t* p = malloc(sizeof(seqlist_t));//申请一个堆空间
	if(p == NULL)//判断是否申请成功
	{
		printf("malloc failed!!");
		return NULL;
	}
	return p;
}
///
*********判断顺序表是否为满或者为空****************
//
int isFullEmptyseqlist(seqlist_t* p,int x)
{
	return p->last == x;
}
///
********************插入元素***********************
//
int insertIntoSeqlist(seqlist_t* p,int post,int x)
{
	int i;
	if(isFullEmptyseqlist(p,N) || post < 1 || post > p->last + 1)//容错判断
	{
		printf("insert failed!!");
		return -1;
	}
	for(i = p->last; i >= post; i--)//移动到要插入的位置
		p->data[i] = p->data[i-1];//元素向后移动
	p->data[post-1] = x;//插入元素
	p->last++;//插入后下标加一
	return 0;
}
///
********************删除元素***********************
//
int deleteFromSeqlist(seqlist_t* p,int post)
{
	int i;
	if(post < 1 || post > p->last || isFullEmptyseqlist(p,0))//容错判断
	{
		printf("delete failed!!");
		return -1;
	}
	for(i = post; i < p->last; i++)//在要删除的位置
		p->data[i-1] = p->data[i];//要删除的元素被后面的覆盖
	p->last--;//下标减一
	return 0;
}
///
********************查找元素***********************
//
int searchDataSeqlist(seqlist_t* p,int x)
{
	int i;
	for(i = 0; i < p->last; i++)//循环遍历
	{
		if(p->data[i] == x)
		{
			return i + 1;	//返回所在位置
		}
	}
	return 0;	//没有这个元素
}
///
********************遍历顺序表*********************
//
void showSeqlist(seqlist_t* p)
{
	int i;
	for(i = 0; i < p->last; i++)
		printf("%d ",p->data[i]);
	printf("\n");
}
///
********************顺序表长度*********************
//
int getLenthlist(seqlist_t* p)
{
	return p->last;
}
///
********************清空顺序表*********************
//
void clearSeqlist(seqlist_t* p)
{
	p->last = 0;
}
int main(int argc,const char* argv[])
{
	seqlist_t* p = createSeqlist_t();
	insertIntoSeqlist(p,1,400);	//在第一个位置插入400
	insertIntoSeqlist(p,1,300);	//在第一个位置插入300
	insertIntoSeqlist(p,1,200);	//在第一个位置插入200
	insertIntoSeqlist(p,1,100);	//在第一个位置插入100
	printf("表长是:%d\n",getLenthlist(p));//计算表长
	showSeqlist(p);	//遍历顺序表
	printf("%d\n",searchDataSeqlist(p,100));	//返回所在位置
	printf("%d\n",searchDataSeqlist(p,1));
	deleteFromSeqlist(p,1);	//删除第一个元素
	deleteFromSeqlist(p,2);	//删除第二个元素
	printf("表长是:%d\n",getLenthlist(p));//计算表长
	showSeqlist(p);	//遍历顺序表
	clearSeqlist(p);//清空顺序表
	showSeqlist(p);	//遍历顺序表
}

2、链表 ( 内存中不连续存储,通过指针将每个节点连接在一起 )

1、无头单向链表

#include<stdio.h>
#include<stdlib.h>
typedef struct node_t
{
	int data;
	struct node_t* next;
}seqLinknode_t;
/*****************无头遍历链表**********************/
void showSeqLinklist(seqLinknode_t* p)
{
	while(p != NULL)
	{
		printf("%d ",p->data);
		p = p->next;
	}
	printf("\n");
}
/********************主函数************************/
int main(int argc,const char* argv[])
{
	seqLinknode_t a = {10,NULL};
	seqLinknode_t b = {20,NULL};
	seqLinknode_t c = {30,NULL};
	seqLinknode_t d = {40,NULL};
	seqLinknode_t e = {50,NULL};
	a.next = &b;
	b.next = &c;
	c.next = &d;
	d.next = &e;
	seqLinknode_t* p = &a;
	WshowSeqLinklist(p);
}

2、有头单向链表

 有头链表与无头链表的区别就是差一个结构体,有头链表第一个结构体的数据域是无效的,而无头链表没有无效的数据域

#include<stdio.h>
#include<stdlib.h>
typedef struct node_t
{
	int data;
	struct node_t* next;
}seqLinknode_t;
/********************申请空间***********************/
seqLinknode_t* createSeqLinknode_t()
{
    seqLinknode_t* p = malloc(sizeof(seqLinknode_t));//申请一块堆空间
	if(p == NULL)//判断是否申请成功
	{
		printf("malloc failed!!");
		return NULL;
	}
	p->next = NULL;
	return p;
}
/*****************有头遍历链表**********************/
void showSeqLinklist(seqLinknode_t* p)
{
	while(p->next != NULL)
	{
		p = p->next;
		printf("%d ",p->data);
	}
	printf("\n");
}
/****************判断链表是否为空*******************/
int isEmptySeqLinklist(seqLinknode_t* p)
{
	return p->next == NULL;
}
/*******************链表长度************************/
int getLenthLinklist(seqLinknode_t* p)
{
	int i;
	for(i = 0; p->next != NULL; i++)
		p = p->next;
	return i;
}
/********************插入元素***********************/
int insertIntoSeqLinklist(seqLinknode_t* p,int post,int x)
{
	int i;
	if(post < 1 || post > getLenthLinklist(p) + 1)//容错判断
	{
		printf("插入失败!!");
		return -1;
	}
	for(i = 1; i < post; i++)//移动到要插入的节点位置
		p = p->next;
	seqLinknode_t* pnew = createSeqLinknode_t();//插入节点
	pnew->data = x;//对数据域进行赋值
	pnew->next = p->next;//先让新节点的指针域指向要插入位置的下一个节点
	p->next = pnew;//然后让插入位置的前一个节点的指针域指向新节点
	return 0;
}
/********************删除元素***********************/
int deleteFromSeqLinklist(seqLinknode_t* p,int post)
{
	int i;
	if(isEmptySeqLinklist(p) || post < 1 || post > getLenthLinklist(p))//容错判断
	{
		printf("删除失败!!");
		return -1;
	}
	for(i = 1; i < post; i++)//移动到要删除节点的前一个位置
		p = p->next;
	p->next = p->next->next;//将要删除的前一个节点的指针域 指向 要删除节点的指针域
	free(q);
	q = NULL;
	return 0;
}
/********************清空链表**********************/
void clearSeqLinklist(seqLinknode_t* p)
{
	seqLinknode_t* q;
	while(p->next != NULL)
	{
		q = p->next;
		p->next = p->next->next;//流水线切东西
		free(q);
		q = NULL;
	}
}
/********************查找元素***********************/
int searchDataSeqLinklist(seqLinknode_t* p,int x)
{	
	int i;
	for(i = 0; p->next != NULL; i++)
	{
		p = p->next;
		if(p->data == x)
			return i + 1;
	}
	return -1;
}
/********************主函数************************/
int main(int argc,const char* argv[])
{
	seqLinknode_t* p = createSeqLinknode_t();
	insertIntoSeqLinklist(p,1,400);
	insertIntoSeqLinklist(p,1,300);
	insertIntoSeqLinklist(p,1,200);
	insertIntoSeqLinklist(p,1,100);
	showSeqLinklist(p);
	deleteFromSeqLinklist(p,1);
	deleteFromSeqLinklist(p,3);
	showSeqLinklist(p);
	printf("%d\n",searchDataSeqLinklist(p,300));
	clearSeqLinklist(p);
	showSeqLinklist(p);	
}

3、单向循环链表 

  单向循环链表解决约瑟夫问题

#include<stdio.h>
#include<stdlib.h>
typedef struct node_t
{
	int data;
	struct node_t* next;
}seqLinknode_t;
/*****************无头遍历链表**********************/
void showSeqLinklist(seqLinknode_t* p)
{
	while(p != NULL)
	{
		printf("%d ",p->data);
		p = p->next;
	}
	printf("\n");
}
/********************主函数************************/
int main(int argc,const char* argv[])
{
	seqLinknode_t a = {10,NULL};
	seqLinknode_t b = {20,NULL};
	seqLinknode_t c = {30,NULL};
	seqLinknode_t d = {40,NULL};
	seqLinknode_t e = {50,NULL};
	a.next = &b;
	b.next = &c;
	c.next = &d;
	d.next = &e;
	seqLinknode_t* p = &a;
	WshowSeqLinklist(p);
}

4、双向链表

3、栈 

思想:先进后出,后进后出。 

1、顺序栈 

#include<stdio.h>
#include<stdlib.h>
#define N 100
typedef struct 
{
	int data[N];
	int top;
}seqtack_t,*seqTackList_t;
int insertIntotack(seqTackList_t p,int x)
{
	if(p->top == N)
	{
		printf("插入失败,栈满!!!\n");
		return -1;
	}
	p->data[p->top] = x;
	p->top++;
	return 0;
}
int deleteFromtack(seqTackList_t p)
{
	if(p->top == 0)
	{
		printf("删除失败,栈空!!!\n");
		return -1;
	}
	p->top--;
	return p->data[p->top];
}
void showSeqtack_list(seqTackList_t p)
{
	int i;
	for(i = 0; i < p->top; i++)
		printf("%d ",p->data[i]);
	printf("\n");
}
int main(int argc,const char* argv[])
{
	seqTackList_t p = malloc(sizeof(seqtack_t));
	if(p != NULL)
	{
		int i;
		insertIntotack(p,100);
		insertIntotack(p,200);
		insertIntotack(p,300);
		insertIntotack(p,400);
		insertIntotack(p,500);
		showSeqtack_list(p)
		for(i = 0; i < 5;i++ )
		printf("%d\n",deleteFromtack(p));
		return 0;
	}
	else
	{
		return -1;
	}
}

2、链栈

#include<stdio.h>
#include<stdlib.h>
typedef struct node_t
{
	int data;
	struct node_t* next;
}seqtacknode_t,*seqnodelist_t;

seqnodelist_t createEmptylist()
{
	seqnodelist_t p = malloc(sizeof(seqtacknode_t));
	if(p == NULL)
	{
		printf("malloc failed!!");
		return NULL;
	}
	p->next = NULL;
	return p;
}
void insertIntoSeqtacknode_t(seqnodelist_t p,int x)
{
	seqnodelist_t pnew = createEmptylist();
	pnew->data = x;
	pnew->next = p->next;
	p->next = pnew;
}
int deleteFromtack(seqnodelist_t p)
{
	int count;
	if(p->next == NULL)
	{
		printf("删除失败,栈空!!");
		return -1;
	}
	seqnodelist_t q = p->next;
	count = q->data;
	p->next = p->next->next;
	free(q);
	q = NULL;
	return count;
}
void showSeqTacklist(seqnodelist_t p)
{
	while(p->next != NULL)
	{
		p = p->next;
		printf("%d ",p->data);
	}
	printf("\n");
}
int main(int argc,const char* argv[])
{
	seqnodelist_t p = createEmptylist();
	insertIntoSeqtacknode_t(p,100);
	insertIntoSeqtacknode_t(p,200);
	insertIntoSeqtacknode_t(p,300);
	insertIntoSeqtacknode_t(p,400);
	insertIntoSeqtacknode_t(p,500);
	showSeqTacklist(p);
	while(p->next != NULL)
	printf("%d ",deleteFromtack(p));
	printf("\n");
	return 0;
}

4、队列 

思想:先进先出,后进后出。 

1、 顺序队列

#include<stdio.h>
#include<stdlib.h>
#define N 100
typedef struct 
{
	int data[N];
	int rear;
	int front;
}sequeuelist_t;
sequeuelist_t* createSequeuelist()//申请空间
{
	sequeuelist_t* p = malloc(sizeof(sequeuelist_t));
	if(p == NULL)
	{
		printf("malloc failed!!!");
		return NULL;
	}
	p->rear = p->front = 0;
	return p;
}
int insertIntoSequeuelist(sequeuelist_t* p,int x)//插入,排队操作操作
{
	if(getLenthSequeuelist(p,N))
	{
		printf("插入失败,队列满");
		return -1;
	}
	p->data[p->rear] = x;
	p->rear++;
}
int getLenthSequeuelist(sequeuelist_t* p,int x)
{
	return (p->rear - p->front + N)%N == x;
}
int deleteFromSequeuelist(sequeuelist_t* p)//删除,买完东西走操作
{
	int count;
	if(p->rear == p->front)
	{
		printf("队列为空!!!");
		return -1;
	}
	count = p->data[p->front];
	p->front++;
	return count;
}
void showSequeuelist(sequeuelist_t* p)
{
	int i;
	for(i = p->front; i < (p->rear + N)%N; i++)
	{
		printf("%d\n",p->data[i]);
	}
}
int main(int argc,const char* argv[])
{
	int i;
	sequeuelist_t* p = createSequeuelist();
	insertIntoSequeuelist(p,100);
	insertIntoSequeuelist(p,200);
	insertIntoSequeuelist(p,300);
	insertIntoSequeuelist(p,400);
	insertIntoSequeuelist(p,500);
	showSequeuelist(p);
	//printf("----------------------------------------\n");
	for(i = 0; i < 3; i++)
	{
		printf("%d\n",deleteFromSequeuelist(p));
	}
	//printf("-------------------------------------------\n");
	showSequeuelist(p);
	return 0;
}

2、链队列

#include<stdio.h>
#include<stdlib.h>
typedef struct node_t
{
	int data;
	struct node_t* next;
}sequeue_node_list_t,*sequeue_node_t;
sequeue_node_t createEmptySequeuelist()
{
	sequeue_node_t p = malloc(sizeof(sequeue_node_list_t));
	if(p == NULL)
	{
		printf("malloc failed!!");
		return NULL;
	}
	return p;
}
void insertIntoSequeuelist(sequeue_node_t* p,int x)
{
	sequeue_node_t pnew = createEmptySequeuelist();
	pnew->data = x;
	pnew->next = (*p)->next;
	(*p)->next = pnew;
	*p = (*p)->next;
}
int deleteFromSequeuelist(sequeue_node_t p)
{
	if(p->next == NULL)
	{
		printf("删除失败,队列为空!!");
		return -1;
	}
	sequeue_node_t q = p->next;
	int count = q->data;
	p->next = p->next->next;
	free(q);
	q = NULL;
	return count;
}
void showSequeuelist(sequeue_node_t p)
{
	while(p->next != NULL)
	{
		p = p->next;
		printf("%d ",p->data);
	}
	printf("\n");
}
int main(int argc,const char* argv[])
{
	int i;
	sequeue_node_t phead = createEmptySequeuelist();
	sequeue_node_t ptail = phead;
	insertIntoSequeuelist(&ptail,100);
	insertIntoSequeuelist(&ptail,200);
	insertIntoSequeuelist(&ptail,300);
	insertIntoSequeuelist(&ptail,400);
	insertIntoSequeuelist(&ptail,500);
	showSequeuelist(phead);
	for(i = 0; i < 5; i++)
	printf("%d ",deleteFromSequeuelist(phead));
	printf("\n");
	return 0;
}

5、查找方法(哈希(散列)、二分、分块(索引)、顺序)

查找速度:哈希查找  >  二分法查找  >  分块法查找  >  顺序查找 

 1、哈希查找(散列)

int hashFun(int key)
{
	int post = key*key % 100000 / 100;
	return post;
}
//存储数据
void saveNum(int *hash_list, int key)
{
	int post = hashFun(key);
	hash_list[post] = key;
}
//取数据
int getNum(int *hash_list,int key)
{
	int post = hashFun(key);
	return hash_list[post];
}

int main(int argc, const char *argv[])
{
	int i;
	int a[] = {100,110,1010,1001,111}; //key
	int hash_list[1000] = { 0 };//哈希表
	for(i = 0; i < sizeof(a)/sizeof(a[0]); i++)
		saveNum(hash_list,a[i]);
	for(i = 0; i < sizeof(a)/sizeof(a[0]); i++)
		printf("post:%3d --- %d\n",hashFun(a[i]),getNum(hash_list,a[i]));
	return 0;
}

2、二分法查找

 只能查找排好序的,递增序列或者递减序列

int findByHalf(int* p, int n, int x)
{
	int how = 0;
	int high = n - 1;
	int midled;
	while(low <= high)
	{
		midled = (low + high) / 2;
		if(p[midled] == x)
			return midled;
		else if(p[midled] < x)
			low = midled + 1;
		else if(p[midled] > x)
			high = midled - 1;
	}
	return -1
}

3、分块查找(索引)

typedef struct
{
	int max; //每一块的最大值
	int post;//每一块在数组中的起始下标
}index_t; 								  块数  元素个数
int findByBlock(int* a, index_t* b, int x,int n,int m)  
{
	int start,end;//用来保存起始位置和终止位置的下标
	//1.先通过索引表,快速确定x可能在哪一块中
	int i;
	for(i = 0; i < n; i++)
	{
		if(x <= b[i].max)//如果x比第i块的最大值小,说明可能在这一块中
			break;//没有必要继续和下一块的最大值做比较
	}
	if(i == n)//说明是自然结束,没有break,说明这个数x,比所有块的最大值还大
		return -1;//不存在
	//2.在这一块中顺序查找是否有x 
	//锁定这块的起始位置和终止位置的下标
	start = b[i].post;
	if(i == n-1)//说明在最后一块,因为最后一块,没有下一块
		end = m-1;//元素个数n-1
	else
		end = b[i+1].post - 1;//后一块的起始位置的下标 - 1 的到当前第i块的终止下标
	//有了这一块的起始和终止位置的下标,就可以顺序查找
	for(i = start; i <= end; i++)
	{
		if(a[i] == x)
			return i;
	}
	return -1;
}
int main(int argc, const char *argv[])
{
	//源数据表    0   1  2  3  4   5   6   7   8   9   10  11  12 13   14  15   16  17  18  
	int a[19] = {18, 10, 9, 8, 16, 20, 38, 42, 19, 50, 84, 72, 56, 55, 76, 100, 90, 88, 108};
	//索引表,索引表的目的就是快速的锁定,你可能在哪一块中
	index_t b[4] = {{18,0},{50,5},{84,10},{108,15}};
	int i;
	for(i = 0; i < 19; i++)
	{
		int ret = findByBlock(a,b,a[i]);
		if(ret == -1)
			printf("not find!!\n");
		else 
			printf("%d的位置是%d\n",a[ret],ret);
	}
	printf("%d\n",findByBlock(a,b,51));
	return 0;
}

4、顺序查找

int searchDataSeqlist(seqLinknode_t* p,int x)
{	
	int i;
	for(i = 0; p!= NULL; i++)
	{
		if(p->data == x)
			return i;
		p = p->next;
	}
	return -1;
}

6、树 

1、二叉树 

(1)性质

(1)二叉树第k(k>=1) 层上的节点最多  2^(k-1) 个。//2的k-1次幂
(2)深度为k(k>=1)的二叉树最多有 2^k - 1 个节点。//2的k次幂再-1
(3)在任意一棵二叉树中,树叶的数目比度数为2的节点的数目多一。(度数为2的 = 度数为0的 - 1)   
(4)满二叉树: 深度为k(k>=1)时节点为2^k - 1(2的k次幂-1)            
(5)完全二叉树:在满二叉树的最后一层,自右向左连续缺失若干个节点,保证最后一层剩余的节点都在左侧(深度为k(k>=1)时节点为2^(k - 1) (2的k-1次幂) )    

(2) 二叉树的遍历

前序遍历: 根 左 右
中序遍历: 左 根 右
后序遍历: 左 右 根     

前序遍历:A B D F E C G H I
中序遍历:D B E F A G H C I
后序遍历:D E F B H G I C A

由遍历推图的方法:由前序遍历的第一个元素(或后序遍历的最后一个元素)可知他是跟节点,然后去中序遍历中找到这个跟节点,在这个跟节点左面的所有元素就是这个跟节点左分支上的元素,右面的所有元素就是这个跟节点右分支上的,然后在回到前序遍历中找离跟节点最近的元素,然后再去中序遍历中分元素。(循环这个操作,操作如下

前序遍历:A B D F E C G H I
中序遍历:D B E F A G H C I     //跟节点是 A,A左面为A左分支上的节点,A右面为右分支的节点

前序遍历:A B D F E C G H I
中序遍历:D B E F A G H C I        //根据前序遍历确认A节点的左儿子 B 作为新的跟节点
能确定B的左儿子是 D

前序遍历:A B D F E C G H I
中序遍历:D B E F A G H C I        //根据前序遍历确认B节点的右儿子 F 作为新的跟节点
能确定F的左儿子是 E

前序遍历:A B D F E C G H I
中序遍历:D B E F A G H C I        //根据前序遍历确认A节点的右儿子 C 作为新的跟节点
能确定C的右儿子是 I
        
前序遍历:A B D F E C G H I
中序遍历:D B E F A G H C I        //根据前序遍历确认C节点的右儿子 G 作为新的跟节点
能确定G的右儿子是 H

(3)赫夫曼树(最短路径) 

1、 由权值分别为 3,8,6,2 的叶子生成一棵哈夫曼树,它的带权路径长度为 ( 35 ) 。  
//对元素进行排序,然后把最小的两个元素加起来形成个小树,在排序在生成树(循环这个过程)

 2、 哈夫曼编码  
A,B,C,D,E五个字符,出现的频率(即权值)分别为 5,4,3,2,1 所以各字符对应的编码为?


        左 0 右 1                         (或左 1 右 0 )
 A::11                                A:00
 B::10                                B:01
 C: 01                                C:10
  D:001                                D:110
  E:000                                E:111

7、排序方法(快排、选择、插值、冒泡)

1、 快速排序

void quickSort(int* p, int low, int high)
{
	int i = low;
	int j = high;
	int flag = p[low];
	while(i < j)
	{
		while(p[j] >= flag&&i < j)
			j--;
		if(i < j)
		{
			p[i] = p[j];
			i++;
		}
		while(p[i] <= flag&&i < j)
			i++;
		if(i < j)
		{
			p[j] = p[i];
			j--;
		}
	}
	p[i] = flag;
	if(low < i-1)
	{
		quickSort(p,low,i-1);
	}
	if(i+1 < high)
	{
		quickSort(p,i+1,high);
	}
}

2、插值排序

void zhicha(int* p,int n)
{
	int i,j,temp;
	for(i = 1; i < n; i++)
	{
		for(j = i; j > 0; j--)
		{
			if(p[j] < p[j-1])
			{
				temp = p[j];
				p[j] = p[j-1];
				p[j-1] = temp;
			}
			else
			{
				break;
			}
		}
	}
}

3、冒泡排序 

void maopao(int* p,int n)
{
	int i,j,temp;
	for(i = 0; i < n-1; i++)
	{
		for(j = 0; j < n-1-i; j++)
		{
			if(p[j] > p[j+1])
			{
				temp = p[j];
				p[j] = p[j+1];
				p[j+1] = temp;
			}
			
		}
	}
}

4、 选择排序

void xuanze(int* p,int n)
{
	int i,j,temp;
	for(i = 0; i < n-1; i++)
	{
		for(j = i+1; j < n; j++)
		{
			if(p[i] > p[j])
			{
				temp = p[i];
				p[i] = p[j];
				p[j] = temp;
			}
		}
	}
}
/************************//*************************************
升级版选择排序/
************************//************************************/
void xuanze(int* p,int n)
{
	int i,j,min,temp;
	for(i = 0; i < n-1; i++)
	{
		min = i;
		for(j = i+1; j < n; j++)
		{
			if(p[min] > p[j])
				min = j;
		}
		if(i != min)
		{
			temp = p[i];
			p[i] = p[min];
			p[min] = temp;
		}
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值