Day13——二叉树深度遍历的栈实现

如果明白了之前递归深度遍历二叉树,那也能容易想到用栈实现二叉树深度遍历。

本篇博客以这棵树为例:
在这里插入图片描述
中序遍历

中序遍历顺序:左子树,当前结点,右子树。

从根结点A开始,先将它压栈,发现它有左孩子,则处理左孩子:在这里插入图片描述
接着是A的左孩子结点B,先将它压栈,它没有左孩子,弹出一个栈顶元素(刚刚压入的B),访问该结点,发现该结点有右孩子,则继续处理右孩子:
在这里插入图片描述
在这里插入图片描述
接着将B的右孩子结点D压栈,D没有左孩子,则弹出一个栈顶元素(刚刚压入的D),访问该结点,发现D没有右孩子,表明此时A的左子树访问结束,弹出A:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
接着是处理A的右子树……(我就不一一赘述了)
通过上面的流程,我们可以抽象出伪代码:

初始化一个栈stack
treeNode=根结点
while(treeNode||栈不为空){
	if(treeNode!=null){
		stack.push(treeNode)
		(这里直接把treeNode.leftChild赋给treeNode,在下次循环时判断值)
		treeNode=treeNode.leftChild
	}else{
		treeNode=stack.pop()
		访问treeNode;
		(这里直接把treeNode.rightChild赋给treeNode,在下次循环时判断值)
		treeNode=treeNode.rightChild
	}
	
}

代码:

/**
	 * 
	 *********************
	 * @Title: inOrderVisitWithStack
	 * @Description: TODO(In-order visit with stack.)
	 *
	 *********************
	 *
	 */
	public void inOrderVisitWithStack() {
		BinaryCharTree tempTree = this;
		ObjectStack tempStack = new ObjectStack();
		while (tempTree != null || !tempStack.isEmpty()) {
			if (tempTree != null) {
				tempStack.push(tempTree);
				tempTree = tempTree.leftChild;
			} else {
				tempTree = (BinaryCharTree) tempStack.pop();
				System.out.print("" + tempTree.value + " ");
				tempTree = tempTree.rightChild;
			} // Of if
		} // Of while
	}// Of inOrderVisitWithStack

先序遍历

先序遍历顺序:访问当前结点,遍历左子树,遍历右子树。
访问根结点A,然后将A压栈(因为还要通过它找到它的右孩子结点),发现A存在左孩子结点:
在这里插入图片描述
在这里插入图片描述
访问A的左孩子结点B,然后将B压栈,但B没有左孩子结点,则从栈里弹出一个元素(会弹出结点B),发现B存在右孩子结点D:
在这里插入图片描述
访问B的右孩子结点D,将D压入栈中,D没有左孩子结点,弹出一个栈顶元素(D),发现D没有右孩子结点,继续弹出一个栈顶元素(A),继续操作A的右子树:
在这里插入图片描述
以同样的方式遍历A的右子树。
根据上面的过程,抽象出伪代码:

初始化一个栈stack
treeNode=根结点
while(treeNode||栈不为空){
	if(treeNode!=null){
		访问treeNode;
		stack.push(treeNode)
		(这里直接把treeNode.leftChild赋给treeNode,在下次循环时判断值)
		treeNode=treeNode.leftChild
	}else{
		treeNode=stack.pop()
		(这里直接把treeNode.rightChild赋给treeNode,在下次循环时判断值)
		treeNode=treeNode.rightChild
	}
	
}

不难发现,中序和先序遍历的不同之处在于:中序是先压栈,弹出的时候访问;先序是先访问,再压栈,因此我们把中序遍历的代码拿来改一改访问语句的位置就可以实现先序遍历了。
代码:

/**
	 * 
	 *********************
	 * @Title: preOrderVisitWithStack
	 * @Description: TODO(Pre-order visit with stack.)
	 *
	 *********************
	 *
	 */
	public void preOrderVisitWithStack() {
		BinaryCharTree tempTree = this;
		ObjectStack tempStack = new ObjectStack();
		while (tempTree != null || !tempStack.isEmpty()) {
			if (tempTree != null) {
				System.out.print("" + tempTree.value + " ");
				tempStack.push(tempTree);
				tempTree = tempTree.leftChild;
			} else {
				tempTree = (BinaryCharTree) tempStack.pop();
				tempTree = tempTree.rightChild;
			} // Of for if
		} // Of for while
	}// Of preOrderVisitWithStack

后续遍历
后续遍历的顺序:左子树,右子树,当前结点

从根结点A出发,将A压栈,发现它有左孩结点B:
在这里插入图片描述
处理A的左孩子结点B,将B压栈,发现B没有左孩子结点,但有右孩子结点D:
在这里插入图片描述
将B的右孩子结点D压栈,发现D没有左孩子结点和右孩子结点,则弹出栈顶元素(结点D),访问该结点:
在这里插入图片描述
访问D后,再弹出一个栈顶元素(结点B),访问结点B,由于B的右孩子结点已经访问,则可以直接访问,且不用继续在栈里:
在这里插入图片描述
访问结点B之后,再弹出一个栈顶元素A,但我们发现A的右孩子结点并没有被访问,所以现在还不能访问A,所以需要将A重新压栈:
在这里插入图片描述
将A的右孩子结点C压栈,发现结点C有左孩子结点:
在这里插入图片描述
接着处理C的左孩子,不再赘述了。

通过上述流程,我们可以抽象出伪代码:

初始化一个栈stack
treeNode=根结点
while(treeNode||栈不为空){
	if(treeNode!=null){
		stack.push(treeNode)
		treeNode=treeNode.leftChild
	}else{
		treeNode=stack.pop()
		if(treeNode.rightChild!=null&&treeNode.rightChild没有被访问){
			stack.push(treeNode)//把结点继续压入栈
			treeNode=treeNode.rightChild
		}else{
			//没有右孩子结点或者右孩子结点已经被访问
			访问treeNode;
			标记结点被访问;
			treeNode=null;
		}
	}
}

由上,我们需要给二叉树对象再给一个属性值,用于记录结点是否被访问。
代码:

    /**
	 * To mark the node is visited.
	 */
	Boolean visited;

	/**
	 * 
	 *********************
	 * The first constructor.
	 * 
	 * @param paraName The value.
	 *********************
	 *
	 */
	public BinaryCharTree(char paraName) {
		value = paraName;
		leftChild = null;
		rightChild = null;
		visited = false;
	}// Of the constructor
	/**
	 * 
	 *********************
	 * @Title: postOrderVisitWithStack
	 * @Description: TODO(In-order visit with stack.)
	 *
	 *********************
	 *
	 */
	public void postOrderVisitWithStack() {
		BinaryCharTree tempTree = this;
		ObjectStack tempStack = new ObjectStack();
		while (tempTree != null || !tempStack.isEmpty()) {
			if (tempTree != null) {
				tempStack.push(tempTree);
				tempTree = tempTree.leftChild;
			} else {
				tempTree = (BinaryCharTree) tempStack.pop();
				if (tempTree.rightChild != null && !tempTree.rightChild.visited) {
					tempStack.push(tempTree);
					tempTree = tempTree.rightChild;
				} else {
					System.out.print("" + tempTree.value + " ");
					tempTree.visited = true;
					tempTree = null;
				}

			} // Of if
		} // Of while
	}// Of postOrderVisitWithStack

完整代码:

package day13;

import java.util.Arrays;

import datastruct.ObjectStack;
import day07.CircleIntQueue;
import day11.CircleObjectQueue;;

public class BinaryCharTree {
	/**
	 * The value in char.
	 */
	char value;

	/**
	 * The left child.
	 */
	BinaryCharTree leftChild;

	/**
	 * The right child.
	 */
	BinaryCharTree rightChild;

	/**
	 * To mark the node is visited.
	 */
	Boolean visited;

	/**
	 * 
	 *********************
	 * The first constructor.
	 * 
	 * @param paraName The value.
	 *********************
	 *
	 */
	public BinaryCharTree(char paraName) {
		value = paraName;
		leftChild = null;
		rightChild = null;
		visited = false;
	}// Of the constructor

	/**
	 * 
	 *********************
	 * The second constructor. The parameters must be correct since no validity
	 * check is undertaken.
	 * 
	 * @param paraDataArry     The array for data.
	 * @param paraIndicesArray The array for indices.
	 *********************
	 *
	 */
	public BinaryCharTree(char[] paraDataArry, int[] paraIndicesArray) {
		// Step 1. Use a sequential list to store all nodes;
		int tempNumNodes = paraDataArry.length;
		BinaryCharTree[] tempAllNodes = new BinaryCharTree[tempNumNodes];
		for (int i = 0; i < tempNumNodes; i++) {
			tempAllNodes[i] = new BinaryCharTree(paraDataArry[i]);
		} // Of for i

		// Step 2. Link these nodes.
		for (int i = 0; i < tempNumNodes - 1; i++) {
			for (int j = i + 1; j < tempNumNodes; j++) {
				if (paraIndicesArray[i] * 2 + 1 == paraIndicesArray[j]) {
					System.out.println("Linking number " + paraIndicesArray[i] + " with number " + paraIndicesArray[j]);
					tempAllNodes[i].leftChild = tempAllNodes[j];
				} else if (paraIndicesArray[i] * 2 + 2 == paraIndicesArray[j]) {
					System.out.println("Linking number " + paraIndicesArray[i] + " with number " + paraIndicesArray[j]);
					tempAllNodes[i].rightChild = tempAllNodes[j];
					break;
				} else if (paraIndicesArray[i] * 2 + 2 < paraIndicesArray[j]) {
					break;
				} // Of if
			} // Of for j
		} // Of for i;

		// Step 3. The root is the first node.
		value = tempAllNodes[0].value;
		leftChild = tempAllNodes[0].leftChild;
		rightChild = tempAllNodes[0].rightChild;
	}// Of BinaryCharTree

	/**
	 * 
	 *********************
	 * @Title: preOrderVisit
	 * @Description: TODO(Pre-order visit.)
	 *
	 *********************
	 *
	 */
	public void preOrderVisit() {
		System.out.print("" + value + " ");

		if (leftChild != null) {
			leftChild.preOrderVisit();
		} // Of if

		if (rightChild != null) {
			rightChild.preOrderVisit();
		} // Of if
	}// Of preOderVisit

	/**
	 * 
	 *********************
	 * @Title: preOrderVisitWithStack
	 * @Description: TODO(Pre-order visit with stack.)
	 *
	 *********************
	 *
	 */
	public void preOrderVisitWithStack() {
		BinaryCharTree tempTree = this;
		ObjectStack tempStack = new ObjectStack();
		while (tempTree != null || !tempStack.isEmpty()) {
			if (tempTree != null) {
				System.out.print("" + tempTree.value + " ");
				tempStack.push(tempTree);
				tempTree = tempTree.leftChild;
			} else {
				tempTree = (BinaryCharTree) tempStack.pop();
				tempTree = tempTree.rightChild;
			} // Of for if
		} // Of for while
	}// Of preOrderVisitWithStack

	/**
	 * 
	 *********************
	 * @Title: inOrderVisit
	 * @Description: TODO(In-order visit.)
	 *
	 *********************
	 *
	 */
	public void inOrderVisit() {

		if (leftChild != null) {
			leftChild.inOrderVisit();
		} // Of if

		System.out.print("" + value + " ");

		if (rightChild != null) {
			rightChild.inOrderVisit();
		} // Of if
	}// Of inOrderVisit

	/**
	 * 
	 *********************
	 * @Title: inOrderVisitWithStack
	 * @Description: TODO(In-order visit with stack.)
	 *
	 *********************
	 *
	 */
	public void inOrderVisitWithStack() {
		BinaryCharTree tempTree = this;
		ObjectStack tempStack = new ObjectStack();
		while (tempTree != null || !tempStack.isEmpty()) {
			if (tempTree != null) {
				tempStack.push(tempTree);
				tempTree = tempTree.leftChild;
			} else {
				tempTree = (BinaryCharTree) tempStack.pop();
				System.out.print("" + tempTree.value + " ");
				tempTree = tempTree.rightChild;
			} // Of if
		} // Of while
	}// Of inOrderVisitWithStack

	/**
	 * 
	 *********************
	 * @Title: postOrderVisit
	 * @Description: TODO(Post-order visit.)
	 *
	 *********************
	 *
	 */
	public void postOrderVisit() {
		if (leftChild != null) {
			leftChild.postOrderVisit();
		} // Of if

		if (rightChild != null) {
			rightChild.postOrderVisit();
		} // Of if

		System.out.print("" + value + " ");
	}// Of postOrderVisit

	/**
	 * 
	 *********************
	 * @Title: postOrderVisitWithStack
	 * @Description: TODO(In-order visit with stack.)
	 *
	 *********************
	 *
	 */
	public void postOrderVisitWithStack() {
		BinaryCharTree tempTree = this;
		ObjectStack tempStack = new ObjectStack();
		while (tempTree != null || !tempStack.isEmpty()) {
			if (tempTree != null) {
				tempStack.push(tempTree);
				tempTree = tempTree.leftChild;
			} else {
				tempTree = (BinaryCharTree) tempStack.pop();
				if (tempTree.rightChild != null && !tempTree.rightChild.visited) {
					tempStack.push(tempTree);
					tempTree = tempTree.rightChild;
				} else {
					System.out.print("" + tempTree.value + " ");
					tempTree.visited = true;
					tempTree = null;
				}

			} // Of if
		} // Of while
	}// Of postOrderVisitWithStack

	/**
	 * 
	 *********************
	 * @Title: getDepth
	 * @Description: TODO(Get the depth of the binary tree.)
	 *
	 * @return The depth of the tree.
	 *********************
	 *
	 */
	public int getDepth() {
		// It is a leaf.
		if (leftChild == null && rightChild == null) {
			return 1;
		} // Of if
			// Get the depth both of left child and right child. 0 for without the child.
		int leftDepth = 0, rightDepth = 0;

		if (leftChild != null) {
			leftDepth = leftChild.getDepth() + 1;
		} // Of if

		if (rightChild != null) {
			rightDepth = rightChild.getDepth() + 1;
		} // Of if

		return leftDepth > rightDepth ? leftDepth : rightDepth;
	}// Of getDepth

	/**
	 * 
	 *********************
	 * @Title: getNumNodes
	 * @Description: TODO(Get the number of nodes)
	 *
	 * @return The number of nodes.
	 *********************
	 *
	 */
	public int getNumNodes() {
		// It is a leaf.
		if (leftChild == null && rightChild == null) {
			return 1;
		} // Of if

		int leftChildNodes = 0, rightChildNodes = 0;

		// Get the number of nodes of the left child.
		if (leftChild != null) {
			leftChildNodes = leftChild.getNumNodes();
		} // Of if

		// Get the number of nodes of the right child.
		if (rightChild != null) {
			rightChildNodes = rightChild.getNumNodes();
		} // Of if

		// The total number of nodes.
		return leftChildNodes + rightChildNodes + 1;
	}// Of getNumNodes

	/**
	 * The values of nodes according to breadth first traversal.
	 */
	char[] valuesArray;

	/**
	 * The indices in the complete binary tree.
	 */
	int[] indicesArray;

	/**
	 * 
	 *********************
	 * @Title: toDataArrays
	 * @Description: TODO(Convert the tree to data arrays, including a char array
	 *               and an int array. The results are stored in two member
	 *               variables)
	 * 
	 * @see #valuesArray
	 * @see #indicesArray
	 *
	 *********************
	 *
	 */
	public void toDataArrays() {
		// Initialize arrays.
		int tempLength = getNumNodes();

		valuesArray = new char[tempLength];
		indicesArray = new int[tempLength];
		int i = 0;

		// Traverse and convert at the same time.
		CircleObjectQueue tempQueue = new CircleObjectQueue();
		tempQueue.enqueue(this);
		CircleIntQueue tempIntQueue = new CircleIntQueue();
		tempIntQueue.enqueue(0);

		BinaryCharTree tempTree = (BinaryCharTree) tempQueue.dequeue();
		int tempIndex = tempIntQueue.dequeue();
		while (tempTree != null) {
			valuesArray[i] = tempTree.value;
			indicesArray[i] = tempIndex;
			i++;

			if (tempTree.leftChild != null) {
				tempQueue.enqueue(tempTree.leftChild);
				tempIntQueue.enqueue(tempIndex * 2 + 1);
			} // Of if

			if (tempTree.rightChild != null) {
				tempQueue.enqueue(tempTree.rightChild);
				tempIntQueue.enqueue(tempIndex * 2 + 2);
			} // Of if

			tempTree = (BinaryCharTree) tempQueue.dequeue();
			tempIndex = tempIntQueue.dequeue();
		} // Of while
	}// Of toDataArrays

	/**
	 * 
	 *********************
	 * @Title: toDataArraysObjectQueue
	 * @Description: TODO(Convert the tree to data arrays, including a char array
	 *               and an int array. The results are stored in two member
	 *               variables)
	 * 
	 * @see #valuesArray
	 * @see #indicesArray
	 *
	 *********************
	 *
	 */
	public void toDataArraysObjectQueue() {
		// Initialize arrays.
		int tempLength = getNumNodes();

		valuesArray = new char[tempLength];
		indicesArray = new int[tempLength];
		int i = 0;

		// Traverse and convert at the same time.
		CircleObjectQueue tempQueue = new CircleObjectQueue();
		tempQueue.enqueue(this);
		CircleObjectQueue tempIntQueue = new CircleObjectQueue();
		Integer tempIndexInteger = Integer.valueOf(0);
		tempIntQueue.enqueue(tempIndexInteger);

		BinaryCharTree tempTree = (BinaryCharTree) tempQueue.dequeue();
		int tempIndex = ((Integer) tempIntQueue.dequeue()).intValue();
		while (tempTree != null) {
			valuesArray[i] = tempTree.value;
			indicesArray[i] = tempIndex;
			i++;

			if (tempTree.leftChild != null) {
				tempQueue.enqueue(tempTree.leftChild);
				tempIndexInteger = Integer.valueOf(tempIndex * 2 + 1);
				tempIntQueue.enqueue(tempIndexInteger);
			} // Of if

			if (tempTree.rightChild != null) {
				tempQueue.enqueue(tempTree.rightChild);
				tempIndexInteger = Integer.valueOf(tempIndex * 2 + 2);
				tempIntQueue.enqueue(tempIndexInteger);
			} // Of if

			tempTree = (BinaryCharTree) tempQueue.dequeue();
			if (tempTree == null) {
				break;
			} // Of if

			tempIndex = ((Integer) tempIntQueue.dequeue()).intValue();
		} // Of while
	}// Of toDataArraysObjectQueue

	/**
	 * 
	 *********************
	 * @Title: manualConstructTree
	 * @Description: TODO(Manually construct a tree. Only for testing.)
	 *
	 * @return A binary tree.
	 *********************
	 */
	public static BinaryCharTree manualConstructTree() {
		// Step 1. Construct a tree with only one node.
		BinaryCharTree resultTree = new BinaryCharTree('a');

		// Step 2. Construct all nodes. The first node is the root.
		BinaryCharTree tempTreeB = new BinaryCharTree('b');
		BinaryCharTree tempTreeC = new BinaryCharTree('c');
		BinaryCharTree tempTreeD = new BinaryCharTree('d');
		BinaryCharTree tempTreeE = new BinaryCharTree('e');
		BinaryCharTree tempTreeF = new BinaryCharTree('f');
		BinaryCharTree tempTreeG = new BinaryCharTree('g');

		// Step 3. Link all nodes.
		resultTree.leftChild = tempTreeB;
		resultTree.rightChild = tempTreeC;
		tempTreeB.rightChild = tempTreeD;
		tempTreeC.leftChild = tempTreeE;
		tempTreeD.leftChild = tempTreeF;
		tempTreeD.rightChild = tempTreeG;

		return resultTree;
	}// Of manualConstructTree

	/**
	 * 
	 *********************
	 * @Title: main
	 * @Description: TODO(The entrance of the program.)
	 *
	 * @param args Not used now.
	 *********************
	 *
	 */
	public static void main(String args[]) {
		BinaryCharTree tempTree = manualConstructTree();
		System.out.println("\r\nPreorder visit:");
		tempTree.preOrderVisit();
		System.out.println("\r\nInorder visit:");
		tempTree.inOrderVisit();
		System.out.println("\r\nPostorder visit:");
		tempTree.postOrderVisit();

		System.out.println("\r\n\r\nThe depth is: " + tempTree.getDepth());
		System.out.println("The number of nodes is: " + tempTree.getNumNodes());

		tempTree.toDataArrays();
		System.out.println("The values are: " + Arrays.toString(tempTree.valuesArray));
		System.out.println("The indices are: " + Arrays.toString(tempTree.indicesArray));

		tempTree.toDataArraysObjectQueue();
		System.out.println("Only object queue.");
		System.out.println("The values are: " + Arrays.toString(tempTree.valuesArray));
		System.out.println("The indices are: " + Arrays.toString(tempTree.indicesArray));

		char[] tempCharArray = { 'A', 'B', 'C', 'D', 'E', 'F' };
		int[] tempIndicesArray = { 0, 1, 2, 4, 5, 12 };
		BinaryCharTree tempTree2 = new BinaryCharTree(tempCharArray, tempIndicesArray);

		System.out.println("\r\nPreorder visit:");
		tempTree2.preOrderVisit();
		System.out.println("\r\nInorder visit:");
		tempTree2.inOrderVisit();
		System.out.println("\r\nPostorder visit:");
		tempTree2.postOrderVisit();

		System.out.println("\r\nPre-Order visit with stack:");
		tempTree2.preOrderVisitWithStack();
		System.out.println("\r\nIn-Order visit with stack:");
		tempTree2.inOrderVisitWithStack();

		System.out.println("\r\nPost-Order visit with stack:");
		tempTree2.postOrderVisitWithStack();

	}// Of main

}// Of class BinaryCharTree

运行结果:
在这里插入图片描述

  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
二叉树遍历可以使用实现,这里我以中序遍历为例进行说明。下面是使用实现中序遍历的C代码: ```c #include <stdio.h> #include <stdlib.h> // 二叉树结点的定义 struct TreeNode { int data; struct TreeNode* left; struct TreeNode* right; }; // 的定义 struct Stack { int top; int capacity; struct TreeNode** array; }; // 创建一个新的 struct Stack* createStack(int capacity) { struct Stack* stack = (struct Stack*)malloc(sizeof(struct Stack)); stack->top = -1; stack->capacity = capacity; stack->array = (struct TreeNode**)malloc(stack->capacity * sizeof(struct TreeNode*)); return stack; } // 判断是否为空 int isEmpty(struct Stack* stack) { return stack->top == -1; } // 判断是否已满 int isFull(struct Stack* stack) { return stack->top == stack->capacity - 1; } // 入操作 void push(struct Stack* stack, struct TreeNode* item) { if (isFull(stack)) { return; } stack->array[++stack->top] = item; } // 出操作 struct TreeNode* pop(struct Stack* stack) { if (isEmpty(stack)) { return NULL; } return stack->array[stack->top--]; } // 获取顶元素 struct TreeNode* peek(struct Stack* stack) { if (isEmpty(stack)) { return NULL; } return stack->array[stack->top]; } // 中序遍历二叉树(非递归) void inorderTraversal(struct TreeNode* root) { if (root == NULL) { return; } struct Stack* stack = createStack(100); // 创建一个容量为100的 struct TreeNode* current = root; while (current != NULL || !isEmpty(stack)) { // 遍历左子树并入 while (current != NULL) { push(stack, current); current = current->left; } // 弹出顶元素并访问 current = pop(stack); printf("%d ", current->data); // 遍历右子树 current = current->right; } free(stack); } // 测试 int main() { // 创建一个二叉树 struct TreeNode* root = (struct TreeNode*)malloc(sizeof(struct TreeNode)); root->data = 1; root->left = (struct TreeNode*)malloc(sizeof(struct TreeNode)); root->left->data = 2; root->left->left = NULL; root->left->right = NULL; root->right = (struct TreeNode*)malloc(sizeof(struct TreeNode)); root->right->data = 3; root->right->left = NULL; root->right->right = NULL; // 中序遍历二叉树 printf("中序遍历结果:"); inorderTraversal(root); // 释放内存 free(root->left); free(root->right); free(root); return 0; } ``` 这段代码实现了中序遍历的非递归算法,通过来辅助遍历二叉树。首先定义了树结点的结构体 `TreeNode` 和的结构体 `Stack`,然后实现的基本操作(创建、判断是否为空、判断是否已满、入、出、获取顶元素)。最后,在 `inorderTraversal` 函数中实现了中序遍历的非递归算法。在 `main` 函数中创建了一个二叉树,并调用 `inorderTraversal` 函数进行中序遍历。 你可以根据需要修改代码来实现其他遍历方式,比如前序遍历和后序遍历。希望这能帮到你!如果有其他问题,请继续提问。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值