日撸代码300行(11-20天,线性数据结构)

11-20天,线性数据结构

原文:日撸代码300行(11-20天,线性数据结构)_minfanphd的博客-CSDN博客

11.顺序表(一)

package day20;

/**
 * Day 11: 顺序表
 *
 * @author pzf
 */
public class SequentialList {
    final int MAX_LENGTH = 5;
    int length;
    int[] data;

    /**
     * 无参构造方法
     */
    public SequentialList() {
        length = 0;
        data = new int[MAX_LENGTH];
    }// Of SequentialList

    /**
     * 带参数的构造方法
     *
     * @param paraLength 数组
     */
    public SequentialList(int[] paraLength) {
        data = new int[MAX_LENGTH];
        
        // 参数数组长度是否超出MAX_LENGTH
        length = paraLength.length > MAX_LENGTH ? MAX_LENGTH : paraLength.length;

        for (int i = 0; i < length; i++) {
            data[i] = paraLength[i];
        }// Of for
    }// Of SequentialList with parameter

    /**
     * 重写toString
     *
     * @return 字符串
     */
    public String toString() {
        String res = ""; // 空串

        if (length == 0) {
            return "Empty";
        }// Of if

        for (int i = 0; i < length - 1; i++) {
            res += data[i] + ", ";
        }// Of for
        res += data[length - 1];
        return res;
    }// Of toString

    /**
     * 重置线性表
     */
    public void reset() {
        length = 0;
    }// Of reset

    /**
     * main 测试用
     *
     * @param args
     */
    public static void main(String[] args) {
        int[] testArr = {1, 2, 3, 5, 6, 9}; // 超出MAX_LENGTH
        int[] testArr2 = {1, 3}; // 正常
        SequentialList seqList1 = new SequentialList(testArr);
        SequentialList seqList2 = new SequentialList(testArr2);
        System.out.println("SeqList1:" + seqList1);
        System.out.println("SeqList2:" + seqList2);
        seqList1.reset();
        System.out.println("SeqList1 after reset:" + seqList1);
    }// Of main
}// Of class SequentialList

效仿闵老师代码写了一遍。

做了哪些事:
1.定义最大长度(这里偷懒定义为5,方便测试),定义属性:长度、值
2.构造方法,无参+有参。顺便检查了长度是否超出最大长度,超出的截取前面。
3.重写toString,格式为 “1, 2, 3”
4.reset方法,清空线性表

可以改进的地方:
1.代码规范,变量的命名感觉不够规范
2.对常用内置类不熟悉,经提醒,一些地方实现方式可以调用已有的函数。如:为了防止构造方法中参数数组长度大于最大长度时报错,用三目运算符简单处理,其实可以Math.min();构造方法内复制数据用arrayCopy.
3.toString里用StringBuffer,免得一直在那+++拼接

12.顺序表(二)

    /**
     * 查找给定元素所处的位置. 找不到就返回 -1.
     *
     * @param paraValue 要查找的值
     * @return 位置
     */
    public int indexOf(int paraValue) {
        int resPosition = -1;
        for (int i = 0; i < length; i++) {
            if (paraValue == data[i]) {
                resPosition = i;
                break;
            }// Of if
        }// Of for
        return resPosition;
    }// Of indexOf

        /**
     * 在给定位置增加元素. 如果线性表已满, 或位置不在已有位置范围之内, 就拒绝增加.
     * 该位置可以是在最后一个元素之后一个.
     *
     * @param paraValue    插入值
     * @param paraPosition 位置,从0开始
     * @return 是否插入成功
     */
    public boolean insert(int paraValue, int paraPosition) {
        //1.位置是否合法
        if (paraPosition > length || paraPosition < 0) {
            System.out.println("Invalid input.");
            return false;
        }// Of if
        //2.线性表是否还有空位
        if (length == MAX_LENGTH) {
            System.out.println("List full.");
            return false;
        }// Of if
        //3.正确插入,后移后面元素
        for (int i = length; i > paraPosition; i--) {
            data[i] = data[i - 1];
        }// Of for
        data[paraPosition] = paraValue;
        length++;
        return true;
    }//Of insert

        /**
     * 删除定定位置的元素. 要处理给定位置不合法的情况. 该位置必须是已经有数据的.
     *
     * @param paraPosition 指定元素的位置,从0开始
     * @return 是否成功
     */
    public boolean delete(int paraPosition) {
        //1.检查位置是否合法
        if (paraPosition > length || paraPosition < 0) {
            System.out.println("Invalid input");
            return false;
        }// Of if

        //2.正常删除
        for (int i = paraPosition ; i < length - 1; i++) {
            data[i] = data[i + 1];
        }// Of for

        length--;
        return true;
    }// Of delete

在day11代码基础上新增3个新方法

这里如果从用户出发,那么自然插入、删除等操作的下标应该从1开始,代码中就要把位置的参数-1,但是为了理解和敲代码方便,还是从0开始了

13.链表

package day20;

/**
 * Day 13: 链表
 *
 * @author pzf
 */
public class LinkedList {
    /**
     * 节点类
     */
    class Node{
        int data; // 值
        Node next; // 指针

        /**
         * 构造方法
         *
         * @param paraValue 值
         */
        public Node(int paraValue) {
            data = paraValue;
            next = null;
        }// Of the constructor
    }//Of class Node
    Node headNode;

    /**
     * 构造方法 头结点赋值 -1
     */
    public LinkedList(){
        headNode = new Node(-1);
    }// Of the constructor

    /**
     * 重写toString
     *
     * @return 字符串
     */
    public String toString(){
        String res = "";

        //1.判空
        if(headNode.next == null){
            return "Empty List";
        }// Of if

        //2.正常处理
        Node tempNode = headNode.next;
        while(tempNode.next!=null){
            res += tempNode.data + " -> ";
            tempNode = tempNode.next;
        }// Of while

        res += tempNode.data;
        return res;
    }// Of toString

    /**
     * 在指定位置插入
     *
     * @param paraPosition 指定位置
     * @param paraValue 插入值
     * @return true:成功 false:失败
     */
    public boolean insert(int paraPosition, int paraValue){
        // 1.找位置+判断位置是否合法
        Node tempNode = headNode;
        for (int i = 0; i < paraPosition; i++) {
            if(tempNode.next == null){
                System.out.println("Invalid input");
                return false;
            }// Of if

            tempNode = tempNode.next;
        }// Of for

        // 2.插入
        Node insertNode = new Node(paraValue);

        insertNode.next = tempNode.next;
        tempNode.next = insertNode;

        return true;
    }// Of insert

    /**
     * 重置链表
     */
    public void reset(){
        headNode.next = null;
    }// Of reset

    /**
     * 删除指定位置的节点
     *
     * @param paraPosition 指定位置
     * @return true:成功删除 false:删除失败
     */
    public boolean delete(int paraPosition){
        // 1. 判空
        if(headNode.next == null){
            System.out.println("Cannot delete element from an empty list.");
            return false;
        }// Of if

        Node tempPreNode = headNode;
        Node tempNode = headNode.next;

        // 2.判断合法性,定位
        for (int i = 0; i < paraPosition; i++) {
            if(tempNode.next == null){
                System.out.println("Invalid input");
                return false;
            }// Of if

            tempNode = tempNode.next;
            tempPreNode = tempPreNode.next;
        }// Of for

        // 3.执行删除
        tempPreNode.next = tempNode.next;
        return true;

    }// Of delete

    //定位

    /**
     * 返回参数值的位置,如果没有,返回 -1
     *
     * @param paraValue 要查找的值
     * @return int 找到:位置  没找到:-1
     */
    public int locate(int paraValue){
        Node tempNode = headNode.next;
        int res = 0;
        while(tempNode!=null){
            if(paraValue == tempNode.data){
                return res;
            }// Of if
            res++;
            tempNode = tempNode.next;
        }// Of while
        return -1;
    }// Of locate

    /**
     * main 测试用
     *
     * @param args
     */
    public static void main(String[] args) {
        LinkedList list = new LinkedList();

        for (int i = 0; i < 5; i++) {
            list.insert(0,i);
        }
        System.out.println(list);
        System.out.println(list.locate(0));
        for (int i = 4; i >=0; i--) {
            list.delete(i);
            System.out.println(list);
        }
    }// Of main
}// Of class LinkedList

测试结果:测试结果

做了哪些事:
1.定义节点内部类,包含值和指针2个属性
2.构造方法
3.重写toString
4.增删查、重置链表的方法

反思:
Java注意要空指针的异常,增删查在遍历指针的时候一不小心就会有少写next的情况,会造成无限循环或者空指针报错

备考过程中一直看的C,现在回到Java有点不适应了,总在想参数是不是应该把链表加进去,构造方法不看老师代码都写不出来

14.栈

package day20;

/**
 * Day14: Stack
 *
 * @author pzf
 */
public class CharStack {
    //attributes
    final int MAX_DEPTH = 30;
    int depth;
    char[] data;

    /**
     * Constructor
     */
    public CharStack() {
        depth = 0;
        data = new char[MAX_DEPTH];
    }// Of constructor

    /**
     * Push
     *
     * @param paraValue The given char
     * @return Success:true  fail: false
     */
    public boolean push(char paraValue) {
        //1. full ?
        if (depth == MAX_DEPTH) {
            System.out.println("Full");
            return false;
        }// Of if

        //2. push
        data[depth++] = paraValue;
        return true;
    }// Of push

    /**
     * Pop
     *
     * @return The element on the top of stack
     */
    public char pop() {
        // 1. is empty stack ?
        if (depth == 0) {
            System.out.println("Empty");
            return '\0';
        }// Of if

        // 2. pop
        return data[--depth];
    }// Of pop

    /**
     * Reset stack
     */
    public void reset() {
        depth = 0;
    }// Of reset

    /**
     * Override toString
     *
     * @return Format stack
     */
    public String toString() {
        String res = "";
        for (int i = 0; i < depth; i++) {
            res += data[i];
        }// Of for

        return res;
    }// Of toString

    /**
     * main
     * 
     * @param args
     */
    public static void main(String[] args) {
        CharStack tempStack = new CharStack();
        for (int i = 0; i < 10; i++) {
            tempStack.push((char)(i+97));
        }// Of for
        System.out.println(tempStack);
        System.out.println(tempStack.pop());
        tempStack.pop();
        tempStack.pop();
        System.out.println(tempStack);
        tempStack.reset();
        System.out.println(tempStack);
    }// Of main
    
}// Of class CharStack

运行截图:
运行结果-栈

做了哪些事:
1.定义类,属性有常量:最大深度,变量:深度、栈顶元素
2.构造方法
3.push and pop
3.reset、重写toString

反思:英文的注释好难写,水平不够,想要简短地表达意思比写一大段话更难

15.括号匹配(栈的应用)

package day20;

import day20.CharStack;

/**
 * Day 15: bracket matching
 *
 * @author pzf
 */
public class StackTest {
    /**
     * Is the bracket matching?
     *
     * @param paraString The given parameter
     * @return True or false
     */
    public  static boolean bracketMatching(String paraString) {
        CharStack tempStack = new CharStack();

        for (int i = 0; i < paraString.length(); i++) {
            char tempChar = paraString.charAt(i);
            switch (tempChar) {
                case '(':
                case '[':
                case '{':
                    tempStack.push(tempChar);
                    break;
                case ')':
                    if (tempStack.pop() != '(') {
                        return false;
                    }
                    break;
                case ']':
                    if (tempStack.pop() != '[') {
                        return false;
                    }
                    break;
                case '}':
                    if (tempStack.pop() != '{') {
                        return false;
                    }
                    break;
                default:
                    // Do noting
            }// Of switch
        }// Of for
        // Of if
        return tempStack.depth == 0;
    }// Of bracketMatching
	
	/**
     * main,test
     * 
     * @param args
     */
    public static void main(String[] args) {
        String s1 = "( )  )";
        String s2 = "[2 + (1 - 3)] * 4";
        String s3 = "()()(())";
        String s4 = "({}[])";

        System.out.println(bracketMatching(s1));
        System.out.println(bracketMatching(s2));
        System.out.println(bracketMatching(s3));
        System.out.println(bracketMatching(s4));
    }// Of main
}// Of class StackTest

为了简洁,新建了类导入了前一天的代码。
由于只有括号进栈,所以用最后栈是否为空表示返回结果。

[一开始漏掉了选择语句里遇到不匹配的情况后的break,以为既然已经return了那么break是多余的,忽略了正确匹配的情况。。]

运行结果:
(尴尬的地方:这里用pop方法遇到空栈时会打印一个Empty)
运行结果-day15

16.递归

package day20;

/**
 * Day16: Recursion
 *
 * @author pzf
 */
public class Recursion {

    /**
     * Sum to N
     *
     * @param paraN The given value.
     * @return The sum.
     */
    public static int sum(int paraN) {
        if (paraN <= 0) {
            return 0;
        }// Of if
        return sum(paraN - 1) + paraN;
    }// Of sum

    /**
     * Fibonacci sequence.
     *
     * @param paraN The given value.
     * @return The paraNth number in fibonacci sequence.
     */
    public static int fib(int paraN){
        if(paraN <= 0){
            return 0;
        }// Of if
        if(paraN == 1 || paraN == 2){
            return 1;
        }// Of if
        return fib(paraN-1) + fib(paraN - 2);
    }// Of fib

    /**
     * main
     *
     * @param args
     */
    public static void main(String[] args) {
        System.out.println(sum(10));
        System.out.println(fib(10));
    }// Of main
}// Of class Recursion

17.链队列

package day20;

/**
 * Day17: LinkedQueue
 *
 * @author pzf
 */
public class LinkedQueue {
    /**
     * Inner class:Node
     */
    private class Node {
        // attributes
        public int data;
        public Node next;

        /**
         * contractor
         * @param paraValue
         */
        public Node(int paraValue) {
            data = paraValue;
            next = null;
        }// Of contractor
    }// Of class Node

    //attributes
    Node headNode;
    Node tailNode;

    /**
     * contractor
     */
    public LinkedQueue() {
        headNode = new Node(-1);
        tailNode = headNode;
    }// Of contractor

    /**
     * Enqueue
     *
     * @param paraValue The given value.
     */
    public void enqueue(int paraValue) {
        Node tempNode = new Node(paraValue);
        tailNode.next = tempNode;
        tailNode = tempNode;
    }// Of enqueue

    /**
     * Dequeue
     *
     * @return The number at the headNode
     */
    public int dequeue() {
        // empty?
        if (headNode == tailNode) {
            System.out.println("Empty queue");
            return -1;
        }// Of if

        int res = headNode.next.data;
        headNode.next = headNode.next.next;

        // if empty
        if(headNode.next==null){
            tailNode = headNode;
        }// Of if

        return res;
    }// Of dequeue

    /**
     * Overrides toString
     *
     * @return format string
     */
    public String toString() {
        String res = "";
        if (headNode.next == null) {
            return "empty";
        }// Of if

        Node tempNode = headNode.next;
        while(tempNode.next !=null ){
            res += tempNode.data + " -> ";
            tempNode = tempNode.next;
        }// Of while
        res += tempNode.data;

        return res;
    }// Of toString

    /**
     * main,test
     *
     * @param args
     */
    public static void main(String[] args) {
        LinkedQueue queue = new LinkedQueue();
        for (int i = 0; i < 5; i++) {
            queue.enqueue(i);
        }// Of for

        System.out.println(queue);

        for (int i = 0; i < 6; i++) {
            System.out.println(queue.dequeue());
        }// Of for
    }// Of main
}// Of class LinkedQueue

运行截图:
运行结果-17

18.循环队列

package day20;

/**
 * Day 18: CircleQueue
 *
 * @author pzf
 */
public class CircleQueue {
    //attributes
    final static int MAX_SPACE = 10;
    int[] data;
    int head, tail;

    /**
     * contractor
     */
    public CircleQueue() {
        data = new int[MAX_SPACE];
        head = 0;
        tail = 0;
    }// Of contractor

    /**
     * enqueue
     *
     * @param paraValue The given value.
     * @return true of false
     */
       public boolean enqueue(int paraValue) {
        // 1. full?
        if ((tail + 1) % MAX_SPACE == head) {
            System.out.println("Full");
            return false;
        }// Of if

        // 2.enqueue
        data[tail % MAX_SPACE] = paraValue;
        tail = ++tail % MAX_SPACE;
        return true;
    }// Of enqueue

    /**
     * dequeue
     *
     * @return The value of head
     */
    public int dequeue() {
        // 1. empty?
        if (head == tail) {
            System.out.println("Empty");
            return -1;
        }// Of if

        // 2. dequeue
        int res = data[head % MAX_SPACE];
        head = (head + 1) % MAX_SPACE;
        return res;
    }// Of dequeue

    /**
     * Overrides toString
     *
     * @return String
     */
    public String toString() {
        String res = "";
        /*for (int i = head; ; i++) {
            if (i % MAX_SPACE == tail) {
                break;
            }
            res += data[i % MAX_SPACE] + ", ";
        }*/
        int count = head;
        while (count % MAX_SPACE != tail) {
            res += data[count % MAX_SPACE] + ", ";
            count++;
        }// Of while

        // remove the extra ", "
        if(res.length()>0){
            res = res.substring(0,res.length()-2);
        }// Of if

        return res;
    }// Of toString

    /**
     * main,test
     *
     * @param args
     */
    public static void main(String[] args) {
        CircleQueue cq = new CircleQueue();
        for (int i = 0; i < 10; i++) {
            cq.enqueue(i);
        }
        System.out.println(cq);
        for (int i = 0; i < 10; i++) {
            cq.dequeue();
        }
        System.out.println(cq);
        for (int i = 0; i < 4; i++) {
            cq.enqueue(i + 5);
            System.out.println(cq);
        }

    }// Of main
}// Of class CircleQueue


运行结果:运行结果

强迫症,偏要去掉最后的逗号,之前少循环一次然后最后拼接最后一个值的方法在循环队列里有BUG,干脆换个写法。

19.字符串匹配

package day20;

/**
 * Day19: MyString
 *
 * @author pzf
 */
public class MyString {
    // attributes
    final static int MAX_LENGTH = 10;
    int length;
    char[] data;

    /**
     *  contractor
     */
    public MyString() {
        length = 0;
        data = new char[MAX_LENGTH];
    }// Of contractor

    /**
     *  Contractor with parameter
     *
     * @param paraString String
     */
    public MyString(String paraString) {
        data = new char[MAX_LENGTH];

        for (int i = 0; i < paraString.length() && i < MAX_LENGTH; i++) {
            data[i] = paraString.charAt(i);
            length = i + 1;
        }// Of for
    }// Of contractor with parameter

    /**
     * Overrides toString
     *
     * @return String
     */
    public String toString() {
        String res = "";
        for (int i = 0; i < length; i++) {
            res += data[i];
        }// Of for
        return res;
    }// Of toString

    /**
     * Locate the position of a substring.
     *
     * @param paraString The given substring.
     * @return position. -1 for invalid input
     */
    public int locate(MyString paraString) {
        int paraLength = paraString.length;
        if (paraLength == 0 || paraLength > MAX_LENGTH) {
            System.out.println("Invalid input");
            return -1;
        }// Of if

        boolean flag;

        for (int i = 0; i < length - paraLength; i++) {
            flag = true;
            for (int j = 0; j < paraLength; j++) {
                if (data[i + j] != paraString.data[j]) {
                    flag = false;
                    break;
                }// Of if
            }// Of for
            if (flag) {
                return i;
            }// Of if
        }// Of for
        return -1;
    }// Of locate

    /**
     * Get a substring
     *
     * @param paraStartPosition The start position.
     * @param paraLength The length of the new substring
     * @return The new MyString object.
     */
    public MyString subString(int paraStartPosition, int paraLength) {
        MyString resString = new MyString();

        if (paraLength > length || paraLength <= 0 || paraStartPosition < 0 || paraStartPosition > this.length) {
            System.out.println("Invalid input");
        } else {
            int count = 0;
            for (int i = paraStartPosition; count < paraLength; i++) {
                resString.data[count++] = this.data[i];
            }// Of for

            //resString.length = paraLength;
        }// Of if

        return resString;
    }// Of subString

    /**
     * main, test
     *
     * @param args
     */
    public static void main(String[] args) {
        MyString a = new MyString("Good morning");
        System.out.println(a);
        MyString mor = new MyString("mor");
        MyString my = new MyString("my");
        MyString empty = new MyString("");
        System.out.println(a.locate(mor));
        System.out.println(a.locate(my));
        System.out.println(a.locate(empty));
        System.out.println(a.subString(0, 3));
        System.out.println(a.subString(2, 4));
        System.out.println(a.subString(20, 4));
    }// main
}// Of class MyString


在这里插入图片描述
有参构造函数加了对参数字符串长度的判断,subString和locate方法也加上了对无效输入的判断,以免越界,增加一点健壮性。

20.小结

  1. 面向对象与面向过程相比, 有哪些优势? 注: 第 1 - 10 天的程序, 就是面向过程的.

复用性高,低耦合

  1. 比较线性表和链接的异同.

同:
1.都储存同一数据类型
2.线性结构
3.都可以顺序存取
异:
1.链接不用事先规定最大容量
2.链接增删元素时不用移动其他元素,线性表需要成块移动
3.链接不占用连续内存空间,线性表占用连续内存空间
4.链接增删效率高,线性表查找效率高,侧重不同

  1. 分析线性表和链接的优缺点.

线性表:
优点:支持随机存取,查找方便,O(1)
缺点:占用大量连续内存空间,增删元素时有大量移动O(n)

链表:
优点:增删元素效率高,O(1),不需要移动,占用的内存空间不一定相邻
缺点:查找效率慢,O(n)

  1. 分析调拭程序常见的问题及解决方案.

常见问题:极端情况的报错,如数组越界、空指针
解决:打断点debug、用打印语句判断是否运行了这一步等找出现错误的原因;分析处理边界极端情况的方法

  1. 分析链队列与循环队列的优缺点.

循环队列对空间的利用率高,节约空间,但是会出现满队列的情况,适用于已知数据规模的情况

链队列用分散的内存空间储存,不会有溢出的情况,占用空间更多

  1. 第 18 天建立的两个队列, 其区别仅在于基础数据不同, 一个是 int, 一个是 char. 按这种思路, 对于不同的基础数据类型, 都需要重写一个类, 这样合理吗? 你想怎么样?

不合理
可以用通配符,代码如下

通配符

package day20;

import java.util.ArrayList;

/**
 * 解决换数据类型就重写类的方法
 * 
 * @param <T> 数据类型
 * @author pzf
 */
public class CircleAnyQueue<T> {
    // attributes
    final static int MAX_SPACE = 10;
    int head, tail;
    ArrayList<T> data;

    /**
     * contractor
     */
    public CircleAnyQueue() {
        data = new ArrayList<T>(MAX_SPACE);
        head = 0;
        tail = 0;
    }// Of contractor

    /**
     * 进队
     * 
     * @param value
     * @return
     */
    public boolean enqueue(T value) {
        if ((tail + 1) % MAX_SPACE == head) {
            System.out.println("Full");
            return false;
        }// Of if
        data.add(tail % MAX_SPACE, value);
        tail = (tail+1) % MAX_SPACE;

        return true;
    }// Of enqueue

	/**
     * 出队
     *
     * @return T 队头元素
     */
    public T dequeue(){
        if( tail == head ){
            System.out.println("Empty");
            return null;
        }// Of if
        T res = this.data.get(head % MAX_SPACE);
        head = (head + 1) % MAX_SPACE;
        return res;
    }// Of dequeue

    /**
     * 重写toString
     * 
     * @return 字符串
     */
    public String toString(){
        String res = "";
        int count = head;
        while (count % MAX_SPACE != tail) {
            //res += data[count % MAX_SPACE] + ", ";
            res += (T)data.get(count % MAX_SPACE) + ", ";
            count++;
        }// Of while

        if(res.length()>0){
            res = res.substring(0,res.length()-2);
        }// Of if

        return res;
    }// Of toString

    /**
     * Test,main
     * 
     * @param args
     */
    public static void main(String[] args) {
        CircleAnyQueue<Integer> a = new CircleAnyQueue<>();
        CircleAnyQueue<String> b = new CircleAnyQueue<>();
        for (int i = 0; i < 10; i++) {
            a.enqueue(i);
            b.enqueue("abc"+i);
        }// Of for
        System.out.println(a);
        System.out.println(b);
    }// Of main
}// Of class CircleAnyQueue

在这里插入图片描述
data如果用数组,似乎new的时候不支持通配符,会报错,没研究出来怎么解决,就换了ArrayList


总结:
用了3天完成1-20天的内容,一年没碰过Java,复健复健,后面的内容算是比较陌生,慢慢学习。
代码规范继续完善,不看闵老师的注释真写不出那种简洁的注释,或许写出来也只有我自己看得懂。

原文:日撸代码300行(11-20天,线性数据结构)_minfanphd的博客-CSDN博客

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值