【数据结构】二叉树

一、什么是二叉树

            二叉树 (binary tree) 是另一种树型结构,它的特点是每个结点至多只有二棵子 树 (即二叉树中不存在度大于 2的结点 ),并且,二叉树的子树有左右之分,其次序不能任意颠倒 。 二叉树是一种数据结构 ,是一对多的关系。


二、二叉树的创建

      第一步:想要构造一颗二叉树首先要创建二叉树的节点,然后将节点按照二叉树的规则连接起来就构成了一颗二叉树。二叉树的每个节点包含三个元素 ----->左指针域 pLeft ,右指针域 pRight ,数据域 data。

           

如图----->当有孩子时pLeft指向左孩子节点,pRight指向右孩子节点。

--------->当没有节点时指针指向空-->NULL

如何用代码创建节点:(创建一个模板类型的节点)

template<class T>
struct Node
{
	Node()
	{
		LChild = NULL;
		RChild = NULL;
	}
	Node(T d)
	:data(d)
	{
		LChild = NULL;
		RChild = NULL;
	}
	T data;
	Node<T>* LChild;
	Node<T>* RChild;
};template<class T>
struct Node
{
	Node()
	{
		LChild = NULL;
		RChild = NULL;
	}
	Node(T d)
	:data(d)
	{
		LChild = NULL;
		RChild = NULL;
	}
	T data;
	Node<T>* LChild;
	Node<T>* RChild;
};


第二步:
        开辟空间,将节点按照二叉树的规则连接
template<class T>
class BinTree
{
	typedef Node<T>* PNode;
public:
	BinTree()                    //无参构造
		: _pRoot(NULL)
	{}

	BinTree(const T* array, size_t size, const T& invalid)      //有参构造
	{
		size_t index = 0;
		_CreateBinTree(_pRoot, array, size, index, invalid);    //调用创建二叉树函数
	}

	BinTree(const BinTree& bt)             //拷贝构造
	{
		_pRoot = _CopyBinTree(bt._pRoot);        //调用拷贝函数
	}

	BinTree& operator=(const BinTree& bt)    //赋值运算符重载
	{
		if (this == &bt)
			return *this;
		if (_pRoot != NULL)
			_DestroyBinTree(_pRoot);    //调用销毁函数
		_pRoot = _CopyBinTree(bt._pRoot);     //调用拷贝函数
		return *this;
	}

	~BinTree()                         //析构函数
	{
	    _DestroyBinTree(_pRoot);         //调用销毁函数
	}
}
将 创建函数,拷贝函数,销毁函数 定义成私有函数,只允许类的内部成员调用。

private:
	// 根+左子树+右子树 
	void _CreateBinTree(PNode& pRoot, const T* array, size_t size, size_t& index, const T& invalid)
	{
		if (index >= size)
			return;
		if (index < size&&array[index]=='#')
			return;
		char ch = array[index];
		pRoot = new Node<T>(ch);
		_CreateBinTree(pRoot->LChild, array, size, ++index, invalid);
		_CreateBinTree(pRoot->RChild, array, size, ++index, invalid);
	}
	PNode _CopyBinTree(PNode pRoot)             //拷贝一个树
	{
		PNode newTree = NULL;
		if (pRoot)
		{
			newTree = new Node<T>(pRoot->data);
			if (pRoot->LChild)
				newTree->LChild = _CopyBinTree(pRoot->LChild);
			if (pRoot->RChild)
				newTree->RChild = _CopyBinTree(pRoot->RChild);
		}
		return newTree;
	}
	void _DestroyBinTree(PNode& pRoot)       //释放节点
	{
		if (pRoot == NULL)
			return;
		if (pRoot->LChild == NULL&&pRoot == NULL)
		{
			delete pRoot;
			pRoot = NULL;
			return;
		}
		_DestroyBinTree(pRoot->LChild);
		_DestroyBinTree(pRoot->RChild);
		delete pRoot;
		pRoot = NULL;
	}

到此一个二叉树的类就写好了,接下来写二叉树里的接口。

将要实现功能的函数都定义成私有函数,再写一个公有函数调用与其对应功能的私有函数,这样可以使对外接口使用起来更简单。

1.先序遍历

(1)递归实现

void _PreOrder(PNode pRoot)      //先序遍历  根--->根的左子树---->根的右子树 
	{
		if (pRoot != NULL)
		{
			cout << pRoot->data << " ";
			_PreOrder(pRoot->LChild);
			_PreOrder(pRoot->RChild);
		}
	}
(2)非递归

void _XPreOder(PNode pRoot)
	{
		if (pRoot == NULL)
			return;
		stack<PNode> s;
		s.push(pRoot);
		while (!s.empty())
		{
			PNode ret = s.top();
			s.pop();
			while (ret)
			{
				cout << ret->data << " ";
				if (ret->RChild)
					s.push(ret->RChild);
				ret = ret->LChild;
			}
		}
	}

2.中序遍历

(1)递归形式

void _InOrder(PNode pRoot)    //中序遍历  左子树--->根节点--->右子树 
	{
		if (pRoot != NULL)
		{
			_InOrder(pRoot->LChild);
			cout << pRoot->data << " ";
			_InOrder(pRoot->RChild);
		}
	} 
(2)非递归形式

void _XInOder(PNode pRoot)
	{
		if (pRoot == NULL)
			return;
		stack<PNode> s;
		PNode ret = pRoot;
		while (ret || !s.empty())
		{
			while (ret)
			{
				s.push(ret);
				ret = ret->LChild;
			}
			ret = s.top();
			cout << ret->data << " ";
			s.pop();
			ret = ret->RChild;
		}
	}
3.后序遍历

(1)递归形式

void _PostOrder(PNode pRoot)     //后序遍历  左子树--->右子树--->根节点 
	{
		if (pRoot != NULL)
		{
			_PostOrder(pRoot->LChild);
			_PostOrder(pRoot->RChild);
			cout << pRoot->data<<" ";
		}
	}
(2)非递归形式

void _XPostOder(PNode pRoot)
	{
		if (pRoot == NULL)
			return;
		stack<PNode> s;
		PNode ret = pRoot;
		PNode flag = NULL;
		while (ret || !s.empty())
		{
			
			while (ret)
			{
				s.push(ret);
				ret = ret->LChild;
			}

			ret = s.top();
			if (ret->RChild == NULL || flag == ret->RChild)
			{
				cout << ret->data << " ";
				flag = ret;
				s.pop();
				ret = NULL;
			}
			else
			ret =s.top()->RChild;
		}

	}
4.层序遍历



层序遍历就是一层一层访问

void _LevelOrder(PNode pRoot)      //层序遍历
	{
		if (pRoot == NULL)
			return;
		PNode ret = NULL;
		queue<PNode> q;
		q.push(pRoot);
		while (!q.empty())
		{
			ret = q.front();
			cout << ret->data <<" ";
			q.pop();
			if (ret->LChild)
				q.push(ret->LChild);
			if (ret->RChild)
				q.push(ret->RChild);
		}
	}
5.总节点个数

size_t _Size(PNode pRoot)
	{
		if (pRoot == NULL)
			return 0;
		if (pRoot->LChild == NULL&&pRoot->RChild == NULL)
			return 1;
		return _Size(pRoot->LChild) + _Size(pRoot->RChild)+1;
	}

6.叶子节点的总个数

size_t _GetLeefCount(PNode pRoot)
	{
		if (pRoot == NULL)
			return 0;
		if (pRoot->LChild == NULL&&pRoot->RChild == NULL)
			return 1;
		return _GetLeefCount(pRoot->LChild) + _GetLeefCount(pRoot->RChild);
	}

7.获取第k层节点的个数

size_t _GetKLevelCount(PNode pRoot,size_t k)
	{
		if (pRoot == NULL || k < 1)
			return 0;
		if (k == 1)
			return 1;
		return _GetKLevelCount(pRoot->LChild, k - 1) + _GetKLevelCount(pRoot->RChild, k - 1);
	}

8.树的高度

size_t _Height(PNode pRoot)
	{
		if (pRoot == NULL)
			return 0;
		if (pRoot->LChild == NULL&&pRoot->RChild == NULL)
			return 1;
		size_t Left = _Height(pRoot->LChild);
		size_t Right = _Height(pRoot->RChild);
		return (Left > Right ? Left + 1 : Right + 1);
	}

9.查找某节点的位置

PNode _Find(PNode pRoot, const T& data)
	{
		if (pRoot == NULL)
			return NULL;
		if (pRoot->data == data)
			return pRoot;
		if (_Find(pRoot->LChild, data))
		return _Find(pRoot->LChild,data);
		if (_Find(pRoot->RChild, data))
		return _Find(pRoot->RChild,data);
		return NULL;
	}

10.查找指定节点的双亲节点

PNode _Parent(PNode pRoot, PNode pNode)
	{
		if (pRoot == NULL)
			return NULL;
		if (pRoot->LChild == pNode || pRoot->RChild == pNode)
			return pRoot;
		if (_Parent(pRoot->LChild, pNode))
			return _Parent(pRoot->LChild,pNode);
		if (_Parent(pRoot->RChild, pNode))
			return _Parent(pRoot->RChild, pNode);
		return NULL;
	}

11.查找指定节点的左孩子节点

PNode LeftChild(PNode pNode)     //查找指定节点的左孩子节点
		{
			return pNode->LChild;
		}

12.查找指定节点的右孩子节点

PNode RightChild(PNode pNode)     //查找指定节点的右孩子节点
		{
			return pNode->RChild;
		}
13.二叉树镜像


(1)递归实现

void _BinTreeMirror(PNode &pRoot)        //递归实现
	{
		if (pRoot == NULL)
			return;
		swap(pRoot->LChild, pRoot->RChild);
		_BinTreeMirror(pRoot->LChild);
		_BinTreeMirror(pRoot->RChild);
	}

(2)非递归实现

void _XBinTreeMirror(PNode &pRoot)          //层序遍历实现
	{
		if (pRoot == NULL)
			return;
		queue<PNode> q;
		q.push(pRoot);
		PNode ret = NULL;
		while (!q.empty())
		{
			ret = q.front();
			q.pop();
			swap(ret->LChild, ret->RChild);
			if (ret->LChild)
				q.push(ret->LChild);
			if (ret->RChild)
				q.push(ret->RChild);
		}
	}

14.判断是否是完全二叉树

首先,分析二叉树

(1)当二叉树为空时,是完全二叉树

(2)当二叉树只有一个节点时,是完全二叉树

(3)当二叉树有多个节点时---->

        创建一个队,将根节点入队,然后进入循环;当对不为空,继续循环。

在循环外创建一个标记flag=false,在循环内使用;当false为true时,并且(ret->left!=NULL||ret->Right!=NULL)二叉树不是完全二叉树。

           a.左右子树都存在,入队

b.只有左子树,没有右子树;不饱和点,将左子树入队,将标记flag=true;

c.只有右子树,没有左子树,不是完全二叉树

d.没有左子树,没有右子树;不饱和点,将标记flag=true

bool _IsComplateBinTree(PNode pRoot)        //判断是否是完全二叉树
	{
		if (pRoot == NULL)
			return true;
		queue<PNode> q;
		q.push(pRoot);
		bool flag = false;
		PNode ret = NULL;
		while (!q.empty())
		{
			ret = q.front();
			q.pop();
			if (flag==true&&(ret->LChild||ret->RChild))
				return false;
			else
			{
				if (ret->LChild&&ret->RChild)
				{
					q.push(ret->LChild);
					q.push(ret->RChild);
				}
				else if (ret->LChild&&ret->RChild == NULL)
				{
					q.push(ret->LChild);
					flag = true;
				}
				else if (ret->LChild == NULL&&ret->RChild)
					return false;
				else
				{
					flag = true;
				}
			}
		}
		return true;
	}


三、完整的二叉树代码

#include<iostream>
#include<queue>
#include<stack>
using namespace std;

template<class T>
struct Node
{
	Node()
	{
		LChild = NULL;
		RChild = NULL;
	}
	Node(T d)
	:data(d)
	{
		LChild = NULL;
		RChild = NULL;
	}
	T data;
	Node<T>* LChild;
	Node<T>* RChild;
};

template<class T>
class BinTree
{
	typedef Node<T>* PNode;
public:
	BinTree()
		: _pRoot(NULL)
	{}

	BinTree(const T* array, size_t size, const T& invalid)
	{
		size_t index = 0;
		_CreateBinTree(_pRoot, array, size, index, invalid);
	}

	BinTree(const BinTree& bt)
	{
		_pRoot = _CopyBinTree(bt._pRoot);
	}

	BinTree& operator=(const BinTree& bt)
	{
		if (this == &bt)
			return *this;
		if (_pRoot != NULL)
			_DestroyBinTree(_pRoot);
		_pRoot = _CopyBinTree(bt._pRoot);
		return *this;
	}

	~BinTree()                         //析构函数
	{
	    _DestroyBinTree(_pRoot);
	}

	void PreOrder()   //先序遍历
	{
		_PreOrder(_pRoot);
	}
	void InOrder()    //中序遍历
	{
		_InOrder(_pRoot);
	}
	void PostOrder()     //后序遍历
	{
		_PostOrder(_pRoot);
	}
	void LevelOrder()      //层序遍历
	{
		_LevelOrder(_pRoot);
	}
	///
	//非递归遍历
	void XPreOder()    //非递归前序遍历
	{
		_XPreOder(_pRoot);
	}
	void XInOder()     //非递归中序遍历
	{
		_XInOder(_pRoot);
	}
	void XPostOder()    //非递归后序遍历
	{
		_XPostOder(_pRoot);
	}
	///
	//二叉树镜像
	void BinTreeMirror()    //递归实现
	{
		_BinTreeMirror(_pRoot);
	}
	void XBinTreeMirror()      //层序遍历实现
	{
		_XBinTreeMirror(_pRoot);
	}
	///
	size_t Size()    //总结点个数
	{
		return _Size(_pRoot);
	}
	size_t GetLeefCount()    //叶子节点的总个数
	{
		return _GetLeefCount(_pRoot);
	}
		
	size_t GetKLevelCount(size_t K)      // 获取第K层结点的个数 
	{
		return _GetKLevelCount(_pRoot, K);
	}

		size_t Height()          //树的高度
		{
			return _Height(_pRoot);
		}
		PNode Find(const T& data)   //查找某个节点的位置
		{
			return _Find(_pRoot, data);
		}
		PNode Parent(PNode pNode)      //查找指定位置的双亲节点
		{
			return _Parent(_pRoot, pNode);
		}
		PNode LeftChild(PNode pNode)     //查找指定节点的左孩子节点
		{
			return pNode->LChild;
		}
		PNode RightChild(PNode pNode)     //查找指定节点的右孩子节点
		{
			return pNode->RChild;
		}
		bool IsComplateBinTree()               //判断是否是完全二叉树
		{
			return _IsComplateBinTree(_pRoot);     
		}
private:
	// 根+左子树+右子树 
	void _CreateBinTree(PNode& pRoot, const T* array, size_t size, size_t& index, const T& invalid)
	{
		if (index >= size)
			return;
		if (index < size&&array[index]=='#')
			return;
		char ch = array[index];
		pRoot = new Node<T>(ch);
		_CreateBinTree(pRoot->LChild, array, size, ++index, invalid);
		_CreateBinTree(pRoot->RChild, array, size, ++index, invalid);
	}
	PNode _CopyBinTree(PNode pRoot)             //拷贝一个树
	{
		PNode newTree = NULL;
		if (pRoot)
		{
			newTree = new Node<T>(pRoot->data);
			if (pRoot->LChild)
				newTree->LChild = _CopyBinTree(pRoot->LChild);
			if (pRoot->RChild)
				newTree->RChild = _CopyBinTree(pRoot->RChild);
		}
		return newTree;
	}
	void _DestroyBinTree(PNode& pRoot)       //释放节点
	{
		if (pRoot == NULL)
			return;
		if (pRoot->LChild == NULL&&pRoot->RChild == NULL)
		{
			delete pRoot;
			pRoot = NULL;
			return;
		}
		_DestroyBinTree(pRoot->LChild);
		_DestroyBinTree(pRoot->RChild);
		delete pRoot;
		pRoot = NULL;
	}

	void _PreOrder(PNode pRoot)      //先序遍历  根--->根的左子树---->根的右子树 
	{
		if (pRoot != NULL)
		{
			cout << pRoot->data << " ";
			_PreOrder(pRoot->LChild);
			_PreOrder(pRoot->RChild);
		}
	}
	void _InOrder(PNode pRoot)    //中序遍历  左子树--->根节点--->右子树 
	{
		if (pRoot != NULL)
		{
			_InOrder(pRoot->LChild);
			cout << pRoot->data << " ";
			_InOrder(pRoot->RChild);
		}
	} 
	void _PostOrder(PNode pRoot)     //后序遍历  左子树--->右子树--->根节点 
	{
		if (pRoot != NULL)
		{
			_PostOrder(pRoot->LChild);
			_PostOrder(pRoot->RChild);
			cout << pRoot->data<<" ";
		}
	}
	void _LevelOrder(PNode pRoot)      //层序遍历
	{
		if (pRoot == NULL)
			return;
		PNode ret = NULL;
		queue<PNode> q;
		q.push(pRoot);
		while (!q.empty())
		{
			ret = q.front();
			cout << ret->data <<" ";
			q.pop();
			if (ret->LChild)
				q.push(ret->LChild);
			if (ret->RChild)
				q.push(ret->RChild);
		}
	}
	//
	//非递归遍历函数定义
	void _XPreOder(PNode pRoot)
	{
		if (pRoot == NULL)
			return;
		stack<PNode> s;
		s.push(pRoot);
		while (!s.empty())
		{
			PNode ret = s.top();
			s.pop();
			while (ret)
			{
				cout << ret->data << " ";
				if (ret->RChild)
					s.push(ret->RChild);
				ret = ret->LChild;
			}
		}
	}
	void _XInOder(PNode pRoot)
	{
		if (pRoot == NULL)
			return;
		stack<PNode> s;
		PNode ret = pRoot;
		while (ret || !s.empty())
		{
			while (ret)
			{
				s.push(ret);
				ret = ret->LChild;
			}
			ret = s.top();
			cout << ret->data << " ";
			s.pop();
			ret = ret->RChild;
		}
	}
	void _XPostOder(PNode pRoot)
	{
		if (pRoot == NULL)
			return;
		stack<PNode> s;
		PNode ret = pRoot;
		PNode flag = NULL;
		while (ret || !s.empty())
		{
			
			while (ret)
			{
				s.push(ret);
				ret = ret->LChild;
			}

			ret = s.top();
			if (ret->RChild == NULL || flag == ret->RChild)
			{
				cout << ret->data << " ";
				flag = ret;
				s.pop();
				ret = NULL;
			}
			else
			ret =s.top()->RChild;
		}

	}

	//
	//二叉树镜像
	void _BinTreeMirror(PNode &pRoot)        //递归实现
	{
		if (pRoot == NULL)
			return;
		swap(pRoot->LChild, pRoot->RChild);
		_BinTreeMirror(pRoot->LChild);
		_BinTreeMirror(pRoot->RChild);
	}
	void _XBinTreeMirror(PNode &pRoot)          //层序遍历实现
	{
		if (pRoot == NULL)
			return;
		queue<PNode> q;
		q.push(pRoot);
		PNode ret = NULL;
		while (!q.empty())
		{
			ret = q.front();
			q.pop();
			swap(ret->LChild, ret->RChild);
			if (ret->LChild)
				q.push(ret->LChild);
			if (ret->RChild)
				q.push(ret->RChild);
		}
	}

	//
	size_t _GetKLevelCount(PNode pRoot,size_t k)
	{
		if (pRoot == NULL || k < 1)
			return 0;
		if (k == 1)
			return 1;
		return _GetKLevelCount(pRoot->LChild, k - 1) + _GetKLevelCount(pRoot->RChild, k - 1);
	}

	size_t _Size(PNode pRoot)
	{
		if (pRoot == NULL)
			return 0;
		if (pRoot->LChild == NULL&&pRoot->RChild == NULL)
			return 1;
		return _Size(pRoot->LChild) + _Size(pRoot->RChild)+1;
	}
	size_t _GetLeefCount(PNode pRoot)
	{
		if (pRoot == NULL)
			return 0;
		if (pRoot->LChild == NULL&&pRoot->RChild == NULL)
			return 1;
		return _GetLeefCount(pRoot->LChild) + _GetLeefCount(pRoot->RChild);
	}
	size_t _Height(PNode pRoot)
	{
		if (pRoot == NULL)
			return 0;
		if (pRoot->LChild == NULL&&pRoot->RChild == NULL)
			return 1;
		size_t Left = _Height(pRoot->LChild);
		size_t Right = _Height(pRoot->RChild);
		return (Left > Right ? Left + 1 : Right + 1);
	}
	PNode _Find(PNode pRoot, const T& data)
	{
		if (pRoot == NULL)
			return NULL;
		if (pRoot->data == data)
			return pRoot;
		if (_Find(pRoot->LChild, data))
		return _Find(pRoot->LChild,data);
		if (_Find(pRoot->RChild, data))
		return _Find(pRoot->RChild,data);
		return NULL;
	}
	PNode _Parent(PNode pRoot, PNode pNode)
	{
		if (pRoot == NULL)
			return NULL;
		if (pRoot->LChild == pNode || pRoot->RChild == pNode)
			return pRoot;
		if (_Parent(pRoot->LChild, pNode))
			return _Parent(pRoot->LChild,pNode);
		if (_Parent(pRoot->RChild, pNode))
			return _Parent(pRoot->RChild, pNode);
		return NULL;
	}
	bool _IsComplateBinTree(PNode pRoot)        //判断是否是完全二叉树
	{
		if (pRoot == NULL)
			return true;
		queue<PNode> q;
		q.push(pRoot);
		bool flag = false;
		PNode ret = NULL;
		while (!q.empty())
		{
			ret = q.front();
			q.pop();
			if (flag==true&&(ret->LChild||ret->RChild))
				return false;
			else
			{
				if (ret->LChild&&ret->RChild)
				{
					q.push(ret->LChild);
					q.push(ret->RChild);
				}
				else if (ret->LChild&&ret->RChild == NULL)
				{
					q.push(ret->LChild);
					flag = true;
				}
				else if (ret->LChild == NULL&&ret->RChild)
					return false;
				else
				{
					flag = true;
				}
			}
		}
		return true;
	}
private:
	PNode _pRoot;
};
void test1()      ///从此开始下面的函数是测试函数
{
	char *p = "ABC###DE##F";
	BinTree<char> t1(p, strlen(p), '#');
	/*t1.PreOrder();
	cout << endl;
	t1.InOrder();
	cout << endl;
	t1.PostOrder();
	cout << endl;*/
	//BinTree<char> t2(t1);
	BinTree<char> t3;
	t3 = t1;
}
void test2()
{
	char *p = "ABC###DE##FG";
	BinTree<char> t1(p, strlen(p), '#');
	BinTree<char> t2;

	cout << t1.Size() << endl;
	cout << t1.GetLeefCount() << endl;

	cout << t1.Height() << endl;
	//char ret = 'F';     
	//if (t1.Find(ret))   //找节点
	//{
	//	cout << t1.Find(ret)->data << endl;
	//}
	cout << t1.Parent(t1.Find('D'))->data << endl;      //找双亲节点
	cout << t1.GetKLevelCount(4) << endl;
	t1.LevelOrder();
}
void test3()
{
	char *p = "ABC###DE##F";
	BinTree<char> t1(p, strlen(p), '#');
	t1.PreOrder();
	cout << endl;
	t1.XPreOder();
	cout << endl;
	t1.InOrder();
	cout << endl;
	t1.XInOder();
	cout << endl;
	t1.PostOrder();
	cout << endl;
	t1.XPostOder();

}
void test4()               //测试镜像
{
	char *p = "ABC###DE##FG";
	BinTree<char> t1(p, strlen(p), '#');
	char *p2 = "ABC##D##EF###";
	BinTree<char> t2(p2, strlen(p2), '#');
	t1.PreOrder();
	cout << endl;
	t2.PreOrder();
	cout << endl;
	/*t1.BinTreeMirror();
	t1.PreOrder();
	cout << endl;
	t1.XBinTreeMirror();
	t1.PreOrder();*/
	cout << t1.IsComplateBinTree() << endl;
	cout << t2.IsComplateBinTree() << endl;

}
int main()
{
	//test1();
	//test2();
	//test3();
	test4();

	system("pause");
	return 0;
}

























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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值