java 数组 树_Java如何通过recursion把一个数组array生成一个二叉树binary tree?

1.题目描述

你好,我需要用recursion的方法把一个array生成一个binary tree with linked structure。比如说给定的array是

6b44f052e488043bdb5da124aa4773c0.png , 需生成的结果:

5cd8e37aea4d0e9b9a6d9d3a6a607d83.png

已经给了10个文件,关系如下:

3d1cb68fda3772e4c3f36ed9252318fe.png

我的任务是需要在IntBST.java中创建一个叫makeBinaryTree的method来实现以上需求,其余所有文件中内容都是提前给定的,不需要修改。题目来源及自己的思路

我的思路是把array中点作为root,用recursion分别把左、右边subarray的中点作为left tree(t1)和right tree(t2)的root,最后再把两边的t1和t2连接起来。intBST class最后makeBinaryTree中//complete this method这行后面是我写的code。我运行出来的有NullPointerException,可能是root那里有错,别的地方可能也有不少问题。作为Java新手小白,我思路有点混乱,请大神指点,该如何修改。不胜感激!相关代码

Queue.javapublic interface Queue {

int size();

boolean isEmpty();

void enqueue(E e);

E first();

E dequeue();

}

LinkedQueue.javapublic class LinkedQueue implements Queue {

public LinkedQueue() { }

@Override

public int size() { return list.size(); }

@Override

public boolean isEmpty() { return list.isEmpty(); }

@Override

public void enqueue(E element) { list.addLast(element); }

@Override

public E first() { return list.first(); }

@Override

public E dequeue() { return list.removeFirst(); }

public String toString() {return list.toString();}

}

Tree.javaimport java.util.Iterator;

/**

* An interface for a tree where nodes can have an arbitrary number of children. * * @author Michael T. Goodrich

* @author Roberto Tamassia

* @author Michael H. Goldwasser

*/public interface Tree extends Iterable {

/**

* Returns the root Position of the tree (or null if tree is empty). * @return root Position of the tree (or null if tree is empty)

*/ Node root();

/**

* Returns the Position of p's parent (or null if p is root). * * @param p A valid Position within the tree

* @return Position of p's parent (or null if p is root)

* @throws IllegalArgumentException if p is not a valid Position for this tree.

*/ Node parent(Node p) throws IllegalArgumentException;

/**

* Returns an iterable collection of the Positions representing p's children. * * @param p A valid Position within the tree

* @return iterable collection of the Positions of p's children

* @throws IllegalArgumentException if p is not a valid Position for this tree.

*/ Iterable> children(Node p)

throws IllegalArgumentException;

/**

* Returns the number of children of Position p. * * @param p A valid Position within the tree

* @return number of children of Position p

* @throws IllegalArgumentException if p is not a valid Position for this tree.

*/ int numChildren(Node p) throws IllegalArgumentException;

/**

* Returns true if Position p has one or more children. * * @param p A valid Position within the tree

* @return true if p has at least one child, false otherwise

* @throws IllegalArgumentException if p is not a valid Position for this tree.

*/ boolean isInternal(Node p) throws IllegalArgumentException;

/**

* Returns true if Position p does not have any children. * * @param p A valid Position within the tree

* @return true if p has zero children, false otherwise

* @throws IllegalArgumentException if p is not a valid Position for this tree.

*/ boolean isExternal(Node p) throws IllegalArgumentException;

/**

* Returns true if Position p represents the root of the tree. * * @param p A valid Position within the tree

* @return true if p is the root of the tree, false otherwise

* @throws IllegalArgumentException if p is not a valid Position for this tree.

*/ boolean isRoot(Node p) throws IllegalArgumentException;

/**

* Returns the number of nodes in the tree. * @return number of nodes in the tree

*/ int size();

/**

* Tests whether the tree is empty. * @return true if the tree is empty, false otherwise

*/ boolean isEmpty();

/**

* Returns an iterator of the elements stored in the tree. * @return iterator of the tree's elements

*/ Iterator iterator();

/**

* Returns an iterable collection of the positions of the tree. * @return iterable collection of the tree's positions

*/ Iterable> positions();

}

AbstractTree.javaimport net.datastructures.Queue;

import net.datastructures.LinkedQueue;

import java.util.Iterator;

import java.util.List; // for use as snapshot iterator

import java.util.ArrayList; // for use as snapshot iterator

/**

* An abstract base class providing some functionality of the Tree interface. * * The following three methods remain abstract, and must be * implemented by a concrete subclass: root, parent, children. Other * methods implemented in this class may be overridden to provide a * more direct and efficient implementation. * * @author Michael T. Goodrich

* @author Roberto Tamassia

* @author Michael H. Goldwasser

*/public abstract class AbstractTree implements Tree {

/**

* Returns true if Node p has one or more children. * * @param p A valid Node within the tree

* @return true if p has at least one child, false otherwise

* @throws IllegalArgumentException if p is not a valid Node for this tree.

*/ @Override

public boolean isInternal(Node p) { return numChildren(p) > 0; }

/**

* Returns true if Node p does not have any children. * * @param p A valid Node within the tree

* @return true if p has zero children, false otherwise

* @throws IllegalArgumentException if p is not a valid Node for this tree.

*/ @Override

public boolean isExternal(Node p) { return numChildren(p) == 0; }

/**

* Returns true if Node p represents the root of the tree. * * @param p A valid Node within the tree

* @return true if p is the root of the tree, false otherwise

*/ @Override

public boolean isRoot(Node p) { return p == root(); }

/**

* Returns the number of children of Node p. * * @param p A valid Node within the tree

* @return number of children of Node p

* @throws IllegalArgumentException if p is not a valid Node for this tree.

*/ @Override

public int numChildren(Node p) {

int count=0;

for (Node child : children(p)) count++;

return count;

}

/**

* Returns the number of nodes in the tree. * @return number of nodes in the tree

*/ @Override

public int size() {

int count=0;

for (Node p : positions()) count++;

return count;

}

/**

* Tests whether the tree is empty. * @return true if the tree is empty, false otherwise

*/ @Override

public boolean isEmpty() { return size() == 0; }

//---------- support for computing depth of nodes and height of (sub)trees ----------

/** Returns the number of levels separating Node p from the root.

* * @param p A valid Node within the tree

* @throws IllegalArgumentException if p is not a valid Node for this tree.

*/ public int depth(Node p) throws IllegalArgumentException {

if (isRoot(p))

return 0;

else return 1 + depth(parent(p));

}

/** Returns the height of the tree.

* * Note: This implementation works, but runs in O(n^2) worst-case time. */ private int heightBad() { // works, but quadratic worst-case time

int h = 0;

for (Node p : positions())

if (isExternal(p)) // only consider leaf positions

h = Math.max(h, depth(p));

return h;

}

/**

* Returns the height of the subtree rooted at Node p. * * @param p A valid Node within the tree

* @throws IllegalArgumentException if p is not a valid Node for this tree.

*/ public int height(Node n) throws IllegalArgumentException {

int h = 0; // base case if p is external

for (Node c : children(n))

h = Math.max(h, 1 + height(c));

return h;

}

//---------- support for various iterations of a tree ----------

//---------------- nested ElementIterator class ---------------- /* This class adapts the iteration produced by positions() to return elements. */ private class ElementIterator implements Iterator {

Iterator> posIterator = positions().iterator();

public boolean hasNext() { return posIterator.hasNext(); }

public E next() { return posIterator.next().getElement(); } // return element!

public void remove() { posIterator.remove(); }

}

/**

* Returns an iterator of the elements stored in the tree. * @return iterator of the tree's elements

*/ @Override

public Iterator iterator() { return new ElementIterator(); }

/**

* Returns an iterable collection of the positions of the tree. * @return iterable collection of the tree's positions

*/ @Override

public Iterable> positions() { return preorder(); }

/**

* Adds positions of the subtree rooted at Node p to the given * snapshot using a preorder traversal * @param p Node serving as the root of a subtree

* @param snapshot a list to which results are appended

*/ private void preorderSubtree(Node p, List> snapshot) {

snapshot.add(p); // for preorder, we add position p before exploring subtrees

for (Node c : children(p))

preorderSubtree(c, snapshot);

}

/**

* Returns an iterable collection of positions of the tree, reported in preorder. * @return iterable collection of the tree's positions in preorder

*/ public Iterable> preorder() {

List> snapshot = new ArrayList<>();

if (!isEmpty())

preorderSubtree(root(), snapshot); // fill the snapshot recursively

return snapshot;

}

/**

* Adds positions of the subtree rooted at Node p to the given * snapshot using a postorder traversal * @param p Node serving as the root of a subtree

* @param snapshot a list to which results are appended

*/ private void postorderSubtree(Node p, List> snapshot) {

for (Node c : children(p))

postorderSubtree(c, snapshot);

snapshot.add(p); // for postorder, we add position p after exploring subtrees

}

/**

* Returns an iterable collection of positions of the tree, reported in postorder. * @return iterable collection of the tree's positions in postorder

*/ public Iterable> postorder() {

List> snapshot = new ArrayList<>();

if (!isEmpty())

postorderSubtree(root(), snapshot); // fill the snapshot recursively

return snapshot;

}

/**

* Returns an iterable collection of positions of the tree in breadth-first order. * @return iterable collection of the tree's positions in breadth-first order

*/ public Iterable> breadthfirst() {

List> snapshot = new ArrayList<>();

if (!isEmpty()) {

Queue> fringe = new LinkedQueue<>();

fringe.enqueue(root()); // start with the root

while (!fringe.isEmpty()) {

Node p = fringe.dequeue(); // remove from front of the queue

snapshot.add(p); // report this position

for (Node c : children(p))

fringe.enqueue(c); // add children to back of queue

}

}

return snapshot;

}

}

BinaryTree.javapublic interface BinaryTree extends Tree {

/**

* Returns the Node of p's left child (or null if no child exists). * * @param p A valid Node within the tree

* @return the Node of the left child (or null if no child exists)

* @throws IllegalArgumentException if p is not a valid Node for this tree

*/ Node left(Node p) throws IllegalArgumentException;

/**

* Returns the Node of p's right child (or null if no child exists). * * @param p A valid Node within the tree

* @return the Node of the right child (or null if no child exists)

* @throws IllegalArgumentException if p is not a valid Node for this tree

*/ Node right(Node p) throws IllegalArgumentException;

/**

* Returns the Node of p's sibling (or null if no sibling exists). * * @param p A valid Node within the tree

* @return the Node of the sibling (or null if no sibling exists)

* @throws IllegalArgumentException if p is not a valid Node for this tree

*/ Node sibling(Node p) throws IllegalArgumentException;

}

AbstractBinaryTree.javaimport java.util.List;

import java.util.ArrayList;

/**

* An abstract base class providing some functionality of the BinaryTree interface. * * The following five methods remain abstract, and must be implemented * by a concrete subclass: size, root, parent, left, right. * * @author Michael T. Goodrich

* @author Roberto Tamassia

* @author Michael H. Goldwasser

*/public abstract class AbstractBinaryTree extends AbstractTree

implements BinaryTree {

/**

* Returns the Node of p's sibling (or null if no sibling exists). * * @param p A valid Node within the tree

* @return the Node of the sibling (or null if no sibling exists)

* @throws IllegalArgumentException if p is not a valid Node for this tree

*/ @Override

public Node sibling(Node p) {

Node parent = parent(p);

if (parent == null) return null; // p must be the root

if (p == left(parent)) // p is a left child

return right(parent); // (right child might be null)

else // p is a right child

return left(parent); // (left child might be null)

}

/**

* Returns the number of children of Node p. * * @param p A valid Node within the tree

* @return number of children of Node p

* @throws IllegalArgumentException if p is not a valid Node for this tree.

*/ @Override

public int numChildren(Node p) {

int count=0;

if (left(p) != null)

count++;

if (right(p) != null)

count++;

return count;

}

/**

* Returns an iterable collection of the Nodes representing p's children. * * @param p A valid Node within the tree

* @return iterable collection of the Nodes of p's children

* @throws IllegalArgumentException if p is not a valid Node for this tree.

*/ @Override

public Iterable> children(Node p) {

List> snapshot = new ArrayList<>(2); // max capacity of 2

if (left(p) != null)

snapshot.add(left(p));

if (right(p) != null)

snapshot.add(right(p));

return snapshot;

}

/**

* Adds positions of the subtree rooted at Node p to the given * snapshot using an inorder traversal * @param p Node serving as the root of a subtree

* @param snapshot a list to which results are appended

*/ private void inorderSubtree(Node p, List> snapshot) {

if (left(p) != null)

inorderSubtree(left(p), snapshot);

snapshot.add(p);

if (right(p) != null)

inorderSubtree(right(p), snapshot);

}

/**

* Returns an iterable collection of positions of the tree, reported in inorder. * @return iterable collection of the tree's positions reported in inorder

*/ public Iterable> inorder() {

List> snapshot = new ArrayList<>();

if (!isEmpty())

inorderSubtree(root(), snapshot); // fill the snapshot recursively

return snapshot;

}

/**

* Returns an iterable collection of the positions of the tree using inorder traversal * @return iterable collection of the tree's positions using inorder traversal

*/ @Override

public Iterable> positions() {

return inorder();

}

}

Node.javapublic class Node {

private E element; // an element stored at this node

private Node parent; // a reference to the parent node (if any)

private Node left; // a reference to the left child (if any)

private Node right; // a reference to the right child (if any)

/**

* Constructs a node with the given element and neighbors. * * @param e the element to be stored

* @param above reference to a parent node

* @param leftChild reference to a left child node

* @param rightChild reference to a right child node

*/ public Node(E e, Node above, Node leftChild,

Node rightChild) {

element = e;

parent = above;

left = leftChild;

right = rightChild;

}

// accessor methods

public E getElement() { return element; }

public Node getParent() { return parent; }

public Node getLeft() { return left; }

public Node getRight() { return right; }

// update methods

public void setElement(E e) { element = e; }

public void setParent(Node parentNode) { parent = parentNode; }

public void setLeft(Node leftChild) { left = leftChild; }

public void setRight(Node rightChild) { right = rightChild; }

}

NodeBinaryTree.javaimport java.util.Stack;

/**

* Concrete implementation of a binary tree using a node-based, linked * structure. * * @author Michael T. Goodrich

* @author Roberto Tamassia

* @author Michael H. Goldwasser

*/public class NodeBinaryTree extends AbstractBinaryTree {

/** Factory function to create a new node storing element e. */

protected Node createNode(E e, Node parent, Node left, Node right) {

return new Node(e, parent, left, right);

}

// NodeBinaryTree instance variables

/** The root of the binary tree */

public Node root = null; // root of the tree

/** The number of nodes in the binary tree */

// private int size = 0; // number of nodes in the tree

private int size = 0;

// constructor

/** Construts an empty binary tree. */

public NodeBinaryTree() { } // constructs an empty binary tree

// nonpublic utility /**

* Verifies that a Node belongs to the appropriate class, and is not one * that has been previously removed. Note that our current implementation does * not actually verify that the position belongs to this particular list * instance. * * @param p a Node (that should belong to this tree)

* @return the underlying Node instance for the position

* @throws IllegalArgumentException if an invalid position is detected

*/ /*

* protected Node validate(Node p) throws IllegalArgumentException { if * (!(p instanceof Node)) throw new * IllegalArgumentException("Not valid position type"); Node node = (Node) * p; // safe cast if (node.getParent() == node) // our convention for defunct * node throw new IllegalArgumentException("p is no longer in the tree"); return * node; } */

// accessor methods (not already implemented in AbstractBinaryTree) /**

* Returns the number of nodes in the tree. ** @return number of nodes in the tree

*/ @Override

public int size() {

return size;

}

/**

* Returns the root Node of the tree (or null if tree is empty). ** @return root Node of the tree (or null if tree is empty)

*/ @Override

public Node root() {

return root;

}

/**

* Returns the Node of p's parent (or null if p is root). * * @param n A valid Node within the tree

* @return Node of p's parent (or null if p is root)

* @throws IllegalArgumentException if p is not a valid Node for this tree.

*/ @Override

public Node parent(Node n) throws IllegalArgumentException {

return n.getParent();

}

/**

* Returns the Node of p's left child (or null if no child exists). * * @param n A valid Node within the tree

* @return the Node of the left child (or null if no child exists)

* @throws IllegalArgumentException if p is not a valid Node for this tree

*/ @Override

public Node left(Node n) throws IllegalArgumentException {

return n.getLeft();

}

/**

* Returns the Node of p's right child (or null if no child exists). * * @param n A valid Node within the tree

* @return the Node of the right child (or null if no child exists)

* @throws IllegalArgumentException if p is not a valid Node for this tree

*/ @Override

public Node right(Node n) throws IllegalArgumentException {

return n.getRight();

}

// update methods supported by this class

/**

* Places element e at the root of an empty tree and returns its new Node. * * @param e the new element

* @return the Node of the new element

* @throws IllegalStateException if the tree is not empty

*/ public Node addRoot(E e) throws IllegalStateException {

if (!isEmpty())

throw new IllegalStateException("Tree is not empty");

root = createNode(e, null, null, null);

size = 1;

return root;

}

/**

* Creates a new left child of Node p storing element e and returns its * Node. * * @param n the Node to the left of which the new element is inserted

* @param e the new element

* @return the Node of the new element

* @throws IllegalArgumentException if p is not a valid Node for this tree

* @throws IllegalArgumentException if p already has a left child

*/ public Node addLeft(Node n, E e) throws IllegalArgumentException {

Node parent = n;

if (parent.getLeft() != null)

throw new IllegalArgumentException("n already has a left child");

Node child = createNode(e, parent, null, null); // node child's parent is n,left is null, right is null

parent.setLeft(child); // node child becomes the left child of parent node

size++;

return child;

}

/**

* Creates a new right child of Node p storing element e and returns its * Node. * * @param n the Node to the right of which the new element is inserted

* @param e the new element

* @return the Node of the new element

* @throws IllegalArgumentException if p is not a valid Node for this tree.

* @throws IllegalArgumentException if p already has a right child

*/ public Node addRight(Node n, E e) throws IllegalArgumentException {

Node parent = n;

if (parent.getRight() != null)

throw new IllegalArgumentException("n already has a right child");

Node child = createNode(e, parent, null, null);

parent.setRight(child);

size++;

return child;

}

/**

* Replaces the element at Node p with element e and returns the replaced * element. * * @param n the relevant Node

* @param e the new element

* @return the replaced element

* @throws IllegalArgumentException if p is not a valid Node for this tree.

*/ public E set(Node n, E e) throws IllegalArgumentException {

E temp = n.getElement();

n.setElement(e);

return temp;

}

/**

* Attaches trees t1 and t2, respectively, as the left and right subtree of the * leaf Node n. As a side effect, t1 and t2 are set to empty trees. * * @param n a leaf of the tree

* @param t1 an independent tree whose structure becomes the left child of n

* @param t2 an independent tree whose structure becomes the right child of n

* @throws IllegalArgumentException if p is not a valid Node for this tree

* @throws IllegalArgumentException if p is not a leaf

*/ public void attach(Node n, NodeBinaryTree t1, NodeBinaryTree t2) throws IllegalArgumentException {

if (isInternal(n))

throw new IllegalArgumentException("p must be a leaf");

size += t1.size() + t2.size();

if (!t1.isEmpty()) { // attach t1 as left subtree of node

t1.root.setParent(n); // node n becomes to t1's root parent

n.setLeft(t1.root); // t1's root becomes to the left child of n

t1.root = null; // remove original t1 for garbage collection

t1.size = 0; // remove original t1 for garbage collection

}

if (!t2.isEmpty()) { // attach t2 as right subtree of node

t2.root.setParent(n);

n.setRight(t2.root);

t2.root = null;

t2.size = 0;

}

}

/**

* Removes the node at Node p and replaces it with its child, if any. * * @param n the relevant Node

* @return element that was removed

* @throws IllegalArgumentException if n is not a valid Node for this tree.

* @throws IllegalArgumentException if n has two children.

*/ public E remove(Node n) throws IllegalArgumentException {

if (numChildren(n) == 2)

throw new IllegalArgumentException("p has two children");

Node child = (n.getLeft() != null ? n.getLeft() : n.getRight());

if (child != null)

child.setParent(n.getParent()); // child's grandparent becomes its parent

if (n == root)

root = child; // child becomes root

else {

Node parent = n.getParent();

if (n == parent.getLeft())

parent.setLeft(child);

else parent.setRight(child);

}

size--;

E temp = n.getElement();

n.setElement(null); // help garbage collection

n.setLeft(null);

n.setRight(null);

n.setParent(n); // our convention for defunct node

return temp;

}

/**

* Print a binary tree horizontally * Modified version of https://stackoverflow.com/questions/4965335/how-to-print-binary-tree-diagram * Modified by Keith Gutfreund * @param n Node in tree to start printing from

*/ void print(Node n){

print ("", n);

}

public void print(String prefix, Node n){

if (n != null){

print(prefix + " ", right(n));

System.out.println (prefix + ("|-- ") + n.getElement());

print(prefix + " ", left(n));

}

}

}

IntBST.javaimport java.util.ArrayList;

import java.util.Arrays;

import java.util.List;

// binary search tree storing integers

public class IntBST extends NodeBinaryTree {

private int size = 0;

public IntBST() {

}

public int size() {

return size;

}

public void setSize(int s) {

size = s;

}

public boolean isEmpty() {

return size() == 0;

}

/**

* Places element e at the root of an empty tree and returns its new Node. * * @param e the new element

* @return the Node of the new element

* @throws IllegalStateException if the tree is not empty

*/

public Node addRoot(Integer e) throws IllegalStateException {

if (size != 0)

throw new IllegalStateException("Tree is not empty");

root = createNode(e, null, null, null);

size = 1;

return root;

}

/**

* Print a binary tree horizontally Modified version of * https://stackoverflow.com/questions/4965335/how-to-print-binary-tree-diagram * Modified by Keith Gutfreund * * @param n Node in tree to start printing from

*/

public void print(Node n) {

print("", n);

}

public void print(String prefix, Node n) {

if (n != null) {

print(prefix + " ", right(n));

System.out.println(prefix + ("|-- ") + n.getElement());

print(prefix + " ", left(n));

}

}

public void inorderPrint(Node n) {

if (n == null)

return;

// Node n = validate(p);

inorderPrint(n.getLeft());

System.out.print(n.getElement() + " ");

inorderPrint(n.getRight());

}

public Iterable> children(Node n) {

List> snapshot = new ArrayList<>(2); // max capacity of 2

if (left(n) != null)

snapshot.add(left(n));

if (right(n) != null)

snapshot.add(right(n));

return snapshot;

}

public int height(Node n) throws IllegalArgumentException {

if (isExternal(n)) {

return 0;

}

int h = 0; // base case if p is external

for (Node c : children(n)) h = Math.max(h, height(c));

return h + 1;

}

// Receives an array of integers and creates a binary tree

// Input: an array of integers, a; size of a is 2^k - 1, k = 1, 2, . . . // integers in the array are sorted in non-decreasing order // Output: an IntBST, which is a "complete" binary tree with all integers in the array a

public static IntBST makeBinaryTree(int[] a) {

// complete this method

// base case

IntBST tree = new IntBST();

int middle = (a.length - 1) / 2;

Node rootNode = new Node(a[middle],null,null,null);

if (a.length == 1) {

tree.root.setParent(rootNode);

return tree;

}

while (a.length > 1){

int[] leftSubArray = Arrays.copyOfRange(a,0, middle);

int[] rightSubArray = Arrays.copyOfRange(a, middle + 1, a.length);

IntBST t1 = makeBinaryTree(leftSubArray);

IntBST t2 = makeBinaryTree(rightSubArray);

// attach t1 and t2 with root

if (!t1.isEmpty()) {

t1.root.setParent(rootNode);

rootNode.setLeft(t1.root);

}

if (!t2.isEmpty()) {

t2.root.setParent(rootNode);

rootNode.setRight(t2.root);

}

}

return tree;

}

}

Hw5_P7.javapublic class Hw5_P7 {

public static void main(String[] args) {

IntBST t = new IntBST();

int[] a1 = {10};

int[] a2 = {10, 20, 30};

int[] a3 = {10, 20, 30, 40, 50, 60, 70};

int[] a4 = {10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150};

t = IntBST.makeBinaryTree(a4);

System.out.println("Tree size: " + t.size());

System.out.println("Tree height: " + t.height(t.root));

System.out.println("");

t.print(t.root);

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值