数据结构(C语言实现)

本文主要介绍了用C语言实现链表和栈两种数据结构。链表部分涵盖创建、头部插入、任意位置插入和删除结点,以及循环迭代和递归方式反转链表,还提及双向链表;栈部分介绍了用数组和链表实现栈,包括进栈、出栈和打印栈的功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、链表

1.链表实现以及在头部插入结点

先来一段代码....

该代码包含创建链表并在头部插入结点,遍历链表并打印结点数据,接下来逐步分析,简单的基础语法不过多记录....

#include<stdio.h>
#include<stdlib.h>
struct Node {
    int data;
    struct Node* next;
};
struct Node* head;
void Insert(int x) {
    Node* temp = (Node*)malloc(sizeof(struct Node));
    temp->data = x;
    temp->next = NULL;
    head = temp;
}
void Print() {
    struct Node* temp = head;
    printf("List is:");
    while (temp != NULL) {
        printf("%d", temp->data);
        temp = temp->next;
    }
    printf("\n");
}
int main(void)
{
    head = NULL;
    int n;
    printf("How many numbers?\n");
    scanf("%d", &n);//链表的数量
    int x;//用户插入的数据
    for (int i = 0; i < n; i++) {
        printf("Enter the number\n");
        scanf("%d", &x);
        Insert(x);
        Print();
    }
    return 0;
}
a.创建链表

创建一个链表需要创建结点类型(一个结构体类型,包含值域和指针域),一个头节点,用头结点地址来找到整个链表,头结点指向空地址

struct Node {
    int data;
    struct Node* next;//指向Node结构体类的指针(指向下一个结点)
};
struct Node* head;//全局变量,便于函数直接引用
​
int main(void){
    head = NULL;//还没有结点,头结点先指向空地址
}
b.链表结点插入函数

依据思路,链表为空时我们可以想到这样的代码

void Insert(int x) {
    Node* temp = (Node*)malloc(sizeof(struct Node));
    temp->data = x;
    temp->next = NULL;
    head = temp;
}

但这只能满足链表为空的情况,因此加入if判断一下情况

void Insert(int x) {
	Node* temp = (Node*)malloc(sizeof(struct Node));
	temp->data = x;
	temp->next = NULL;
    if(head != NULL) temp->next = head;
	head = temp;
}

最终代码可以简化为这样,因为包含了链表为空的情况

void Insert(int x) {
    Node* temp = (Node*)malloc(sizeof(struct Node));
    temp->data = x;
    temp->next = NULL;
    head = temp;
}

如果改变一下指针指向的顺序,先让头结点指向新结点的地址,这样就会失去原来头结点指向的地址,导致整个链表断开。

c.链表遍历打印数值的函数
void Insert(int x) {
    Node* temp = (Node*)malloc(sizeof(struct Node));
    temp->data = x;
    temp->next = NULL;
    head = temp;
}
d.拓展思考

如果head不是全局变量

#include<stdio.h>
#include<stdlib.h>
struct Node {
	int data;
	struct Node* next;
};
//struct Node* head;  注释掉了
Node* Insert(Node* head ,int x) {  //注意多传了一个参,并且返回类型是指向Node类型的指针
	struct Node* temp = (Node*)malloc(sizeof(struct Node));
	temp->data = x;
	temp->next = head;
	head = temp;
    return head;
}
void Print(Node* head) {      //需要传参
	//struct Node* temp = head;  注释掉,有head形参不用temp,因为不会让main函数中head指向的地址丢失
	printf("List is:");
	while (head != NULL) {
		printf("%d", head->data);
		head = head->next;
	}
	printf("\n");
}//注意temp全换成了head
int main(void)
{
	Node* head = NULL;//在main函数里创建头结点
	int n;
	printf("How many numbers?\n");
	scanf("%d", &n);
	int x;
	for (int i = 0; i < n; i++) {
		printf("Enter the number\n");
		scanf("%d", &x);
		head = Insert(head,x);
		Print(head);//传参
	}
	return 0;
}

续上,关于Insert函数还有一种写法

void Insert(Node** head ,int x) {  //返回类型为void,传指针的指针
    struct Node* temp = (Node*)malloc(sizeof(struct Node));
    temp->data = x;
    temp->next = *head;
    *head = temp;
}
​
int main(void){
    Insert(&head,x);
}
2.任意位置插入结点

先来看一段代码,这段代码实现了在所给定位置插入结点,重点来看Insert函数

#include<stdio.h>
#include<stdlib.h>
struct Node {
    int data;
    struct Node* next;
};
struct Node* head;
void Print() {
    struct Node* temp = head;
    printf("List is:");
    while (temp != NULL) {
        printf("%d", temp->data);
        temp = temp->next;
    }
    printf("\n");
}
//n是插入位置,data是插入数据
void Insert(int data, int n) {
    Node* temp1 = new Node();//这里采用new在堆上开辟内存
    temp1->data = data;
    temp1->next = NULL;
    if (n == 1) {
        temp1->next = head;
        head = temp1;
        return;
    }
    Node* temp2 = head;
    for (int i = 0; i < n - 2; i++) {
        temp2 = temp2->next;
    }
    temp1->next = temp2->next;
    temp2->next = temp1;
}
int main(void)
{
    head = NULL;
    Insert(2, 1);
    Insert(3, 2);
    Insert(4, 1);
    Insert(5, 2);
    Print();
​
    return 0;
}

这段代码实现的重点是Insert函数

void Insert(int data, int n) {
    Node* temp1 = new Node();//这里采用new在堆上开辟内存
    temp1->data = data;
    temp1->next = NULL;
    if (n == 1) {
        temp1->next = head;
        head = temp1;
        return;//跳出函数
    }
    Node* temp2 = head;
    for (int i = 0; i < n - 2; i++) {//可以思考一下为什么是n-2
        temp2 = temp2->next;
    }
    temp1->next = temp2->next;
    temp2->next = temp1;//很多人这块理解不了,实际上temp1、temp2都是指针,对其解引用修改的都是堆上的结点
}
3.任意位置删除一个结点

先来看一段代码,该代码尝试在链表末尾插入,并且可以指定位置删除结点。

#include<stdio.h>
#include<stdlib.h>
struct Node {
    int data;
    struct Node* next;
};
struct Node* head;
void Insert(int data) {
    Node* temp1 = (Node*)malloc(sizeof(struct Node));
    temp1->data = data;
    Node* temp2 = head;
    if (head == NULL) {
        head = temp1;
        temp1->next = NULL;
        return;
    }
    while (temp2->next != NULL) {
        temp2 = temp2->next;
    }
    temp2->next = temp1;
    temp1->next = NULL;
}
void Print() {
    struct Node* temp = head;
    printf("List is:");
    while (temp != NULL) {
        printf("%d", temp->data);
        temp = temp->next;
    }
    printf("\n");
}
void Delete(int n) {
    Node* temp1 = head;
    if (n == 1) {
        head = temp1->next;
        free(temp1);
        return;
    }
    for (int i = 0; i < n - 2; i++) {
        temp1 = temp1->next;
    }
    Node* temp2 = temp1->next;
    temp1->next = temp2->next;
    free(temp2);//释放malloc开辟出的无用数据内存,如果是c++用  delete temp2
}
int main(void)
{
    head = NULL;
    Insert(1);
    Insert(2);
    Insert(3);
    Insert(4);
    int n;
    scanf("%d", &n);
    Delete(n);
    Print();
​
    return 0;
}
a.在链表末尾插入结点
void Insert(int data) {
    Node* temp1 = (Node*)malloc(sizeof(struct Node));
    temp1->data = data;
    Node* temp2 = head;
    if (head == NULL) {    //特判一下链表为空
        head = temp1;
        temp1->next = NULL;
        return;
    }
    while (temp2->next != NULL) {
        temp2 = temp2->next;
    }
    temp2->next = temp1;
    temp1->next = NULL;
}

总感觉这次写复杂了一点,太晚了,想起来再改进吧...

还有这里体现了链表相比于数组的一个缺点,比如这里在末尾插入结点时需要遍历到链表末尾,而数组则直接使用下标(指针)就可以了

,毕竟数组是一段连续的内存块,任意位置插入也是如此,总感觉讲错了,水平有限,这里就不展开了...

b.任意位置删除结点
void Delete(int n) {
	Node* temp1 = head;
	if (n == 1) {
		head = temp1->next;
		free(temp1);
		return;
	}
	for (int i = 0; i < n - 2; i++) {
		temp1 = temp1->next;
	}
	Node* temp2 = temp1->next;
	temp1->next = temp2->next;
	free(temp2);//释放malloc开辟出的无用数据内存,如果是c++用  delete temp2
}

解释一下for循环吧,初始化i=0时只要n>=2,temp1就可以指向第n-1个结点,这时只需要特判一下n=1的情况,第一个结点没有前一项,应此特判一下,觉得难理解可以自己画一下图,或者等作者补图^_^

4.循环迭代反转链表(只是改变连接)

使用以前的代码,加入了Reverse函数来反转链表,以前提过的就不重复了,直接看Reverse函数的实现

#include<stdio.h>
#include<stdlib.h>
struct Node {
    int data;
    struct Node* next;
};
struct Node* head;
void Print() {
    struct Node* temp = head;
    printf("List is:");
    while (temp != NULL) {
        printf("%d", temp->data);
        temp = temp->next;
    }
    printf("\n");
}
//n是插入位置,data是插入数据
void Insert(int data, int n) {
    Node* temp1 = new Node();//这里采用new在堆上开辟内存
    temp1->data = data;
    temp1->next = NULL;
    if (n == 1) {
        temp1->next = head;
        head = temp1;
        return;
    }
    Node* temp2 = head;
    for (int i = 0; i < n - 2; i++) {
        temp2 = temp2->next;
    }
    temp1->next = temp2->next;
    temp2->next = temp1;
}
void Reverse() {
    struct Node* current, * prev, * next;
    current = head;
    prev = NULL;
    while (current != NULL) {
        next = current->next;
        current -> next = prev;
        prev = current;
        current = next;
    }
    head = prev;
}
int main(void)
{
    head = NULL;
    Insert(2, 1);
    Insert(3, 2);
    Insert(4, 1);
    Insert(5, 2);
    Print();
    Reverse();
    Print();
    return 0;
}
a.反转链表
void Reverse() {
    struct Node* current, * prev, * next;
    current = head;
    prev = NULL;
    while (current != NULL) {
        next = current->next;
        current = prev->next;
        prev = current;
        current = next;
    }
    head = prev;
}

定义了三个指针变量current,prev,next

正如其名,current用于存储当前结点地址,prev用于存储上个结点位置的地址,next用于存储下一个结点位置的地址

之所以建立这三个变量是为了防止链表断裂导致找不到上个位置或下个位置的地址

这个函数也包含了特殊情况,可以自行多尝试几个案例

5.递归方式实现链表反转(打印数值反转)

注意这次只是打印数值时反着打,实际并没有改变链表的结构

#include<stdio.h>
#include<stdlib.h>
struct Node {
    int data;
    struct Node* next;
};
struct Node* head = NULL;
void Insert(int data, int n) {
    Node* temp1 = new Node();
    temp1->data = data;
    temp1->next = NULL;
    if (n == 1) {
        temp1->next = head;
        head = temp1;
        return;
    }
    Node* temp2 = head;
    for (int i = 0; i < n - 2; i++) {
        temp2 = temp2->next;
    }
    temp1->next = temp2->next;
    temp2->next = temp1;
}
void ReversePrint(Node* temp) {
    if (temp == NULL) {
        printf("\n");
        return;
    }
    ReversePrint(temp->next);
    printf("%d", temp->data);
}
void Print() {
    struct Node* temp = head;
    printf("List is:");
    while (temp != NULL) {
        printf("%d", temp->data);
        temp = temp->next;
    }
    printf("\n");
}
int main(void) {
    
    Insert(1, 1);
    Insert(2, 2);
    Insert(3, 3);
    Insert(4, 4);
    Print();
    ReversePrint(head);
​
    return 0;
}
a.递归反向打印
void ReversePrint(Node* temp) {
    if (temp == NULL) {
        printf("\n");
        return;
    }
    ReversePrint(temp->next);//注意先后位置
    printf("%d", temp->data);
}
b.递归正向打印
void ReversePrint(Node* temp) {
    if (temp == NULL) {
        printf("\n");
        return;
    }
    printf("%d", temp->data);
    ReversePrint(temp->next);
}

在递归中位置不同会影响打印的先后顺序,注意递归结束条件的书写

7.关于双向链表

双向链表无需反转,但占用内存更多

#include<stdio.h>
#include<stdlib.h>
struct Node {
    int data;
    Node* prev;
    Node* next;
};
struct Node* head;
struct Node* CreatNode() {
    Node* newNode = (Node*)malloc(sizeof(Node));
    newNode->next = NULL;
    newNode->prev = NULL;
    return newNode;
}
void InsertAtHead(int x) {
    Node* temp = CreatNode();
    temp->data = x;
    if (head == NULL) {
        head = temp;
        return;
    }
    head->prev = temp;//极容易漏
    temp->next = head;
    head = temp;
}
void Print() {
    Node* temp = head;
    printf("List is:");
    while (temp != NULL) {
        printf("%d", temp->data);
        temp = temp->next;
    }
    printf("\n");
}
void ReversePrint() {
    Node* temp = head;
    if (head == NULL) return;
    printf("List is:");
    while (temp->next != NULL) {
        temp = temp->next;
    }
    while (temp != NULL) {
        printf("%d", temp->data);
        temp = temp->prev;
    }
    printf("\n");
}
int main(void)
{
    head = NULL;
    InsertAtHead(1);
    InsertAtHead(2);
    InsertAtHead(3);
    Print();
    ReversePrint();
    return 0;
}
a.创建双向链表

创建双向链表与单向链表不同在于定义结构体时多了一个指针域用于存储上一个结点的地址

struct Node {
    int data;
    Node* prev;
    Node* next;
};
struct Node* head;
struct Node* CreatNode() {
    Node* newNode = (Node*)malloc(sizeof(Node));
    newNode->next = NULL;
    newNode->prev = NULL;
    return newNode;
}

为图方便这块头结点使用全局变量,定义CreatNode函数可以在接下来减少重复代码

b.在头部插入结点
void InsertAtHead(int x) {
    Node* temp = CreatNode();
    temp->data = x;
    if (head == NULL) {
        head = temp;
        return;
    }
    head->prev = temp;//极容易漏
    temp->next = head;
    head = temp;
}

感觉相比单向链表就多注意prev指向前一个结点,其他插入也类似,插入部分不过多赘述了

c.打印链表

正向打印

void Print() {
    Node* temp = head;
    printf("List is:");
    while (temp != NULL) {
        printf("%d", temp->data);
        temp = temp->next;
    }
    printf("\n");
}

反向打印

void Print() {
    Node* temp = head;
    printf("List is:");
    while (temp != NULL) {
        printf("%d", temp->data);
        temp = temp->next;
    }
    printf("\n");
}
二、栈

栈简而言之就是先进后出,后进先出,相比于链表要简单不少

1.用数组实现一个栈

下面的代码用数组实现一个栈,包括进栈以及出栈和打印栈的功能,较为简单,不过多赘述

#include<stdio.h>
#define Maxsize 101
int stack[Maxsize];
int top = -1;//使用全局变量避免传参
void Push(int x) {
    if (top == Maxsize - 1) {
        printf("stack overflow\n");
        return;
    }
    stack[++top] = x;
}
void Pop() {
    if (top == -1) {
        printf("stack is empty\n");
        return;
    }
    top--;
}
int Top() {
    return stack[top];
}
void Print() {
    for (int i = 0; i <= top; i++) {
        printf("%d", stack[i]);
    }
    printf("\n");
}
int main(void)
{
    Push(1);
    Push(2);
    Push(3);
    Push(4);
    Print();
    Pop();
    Pop();
    Print();
​
    return 0;
}
a.进栈代码
void Push(int x) {
    if (top == Maxsize - 1) {
        printf("stack overflow\n");
        return;
    }//这里可以改成创建一个更大的数组并把值拷贝进去,我记得是用memset实现
    stack[++top] = x;
}
b.出栈代码
void Pop() {
    if (top == -1) {
        printf("stack is empty\n");
        return;
    }
    top--;
}
c.打印栈
void Print() {
    for (int i = 0; i <= top; i++) {
        printf("%d", stack[i]);
    }
    printf("\n");
}
2.用链表实现一个栈

只对单向链表进行头结点插入基本就可以实现一个栈

#include<stdio.h>
#include<stdlib.h>
struct Node {
    int data;
    struct Node* link;
};
struct Node* top = NULL;
void Push(int x) {
    Node* temp = (Node*)malloc(sizeof(Node));
    temp->data = x;
    temp->link = top;
    top = temp;
}
void Pop() {
    Node* temp;
    if (top == NULL) return;
    temp = top;
    top = top->link;
    free(temp);
}
void Print(){
    if (top == NULL) {
        printf("stack is empty");
        return;
    }
    Node* temp = top;
    while (temp != NULL) {
        printf("%d", temp->data);
        temp = temp->link;
    }
    printf("\n");
}
int main() {
    Push(1);
    Push(2);
    Push(3);
    Print();
    Pop();
    Print();
​
    return 0;
}
a.栈的实现
struct Node {
    int data;
    struct Node* link;
};
struct Node* top = NULL;
b.入栈
void Push(int x) {
    Node* temp = (Node*)malloc(sizeof(Node));
    temp->data = x;
    temp->link = top;
    top = temp;
}
c.出栈
void Pop() {
    Node* temp;
    if (top == NULL) return;
    temp = top;
    top = top->link;
    free(temp);//别忘了释放无用数据的内存
}

16进制10进制.txt 32.txt asm.txt Crctable.txt C标志符命名源程序.txt erre.txt erre2.txt ff.txt for循环的.txt list.log N皇后问题回溯算法.txt ping.txt re.txt source.txt winsock2.txt ww.txt 万年历.txt 万年历的算法 .txt 乘方函数桃子猴.txt 乘法矩阵.txt 二分查找1.txt 二分查找2.txt 二叉排序树.txt 二叉树.txt 二叉树实例.txt 二进制数.txt 二进制数2.txt 余弦曲线.txt 余弦直线.txt 傻瓜递归.txt 冒泡排序.txt 冒泡法改进.txt 动态计算网络最长最短路线.txt 十五人排序.txt 单循环链表.txt 单词倒转.txt 单链表.txt 单链表1.txt 单链表2.txt 单链表倒序.txt 单链表的处理全集.txt 双链表正排序.txt 反出字符.txt 叠代整除.txt 各种排序法.txt 哈夫曼算法.txt 哈慢树.txt 四分砝码.txt 四塔1.txt 四塔2.txt 回文.txt 图.txt 圆周率.txt 多位阶乘.txt 多位阶乘2.txt 大加数.txt 大小倍约.txt 大整数.txt 字符串查找.txt 字符编辑.txt 字符编辑技术(插入和删除) .txt 完数.txt 定长串.txt 实例1.txt 实例2.txt 实例3.txt 小写数字转换成大写数字1.txt 小写数字转换成大写数字2.txt 小写数字转换成大写数字3.txt 小字库DIY-.txt 小字库DIY.txt 小孩分糖果.txt 小明买书.txt 小白鼠钻迷宫.txt 带头结点双链循环线性表.txt 平方根.txt 建树和遍历.txt 建立链表1.txt 扫描码.txt 挽救软盘.txt 换位递归.txt 排序法.txt 推箱子.txt 数字移动.txt 数据结构.txt 数据结构2.txt 数据结构3.txt 数组完全单元.txt 数组操作.txt 数组递归退出.txt 数组递归退出2.txt 文件加密.txt 文件复制.txt 文件连接.txt 无向图.txt 时间陷阱.txt 杨辉三角形.txt 栈单元加.txt 栈操作.txt 桃子猴.txt 桶排序.txt 检出错误.txt 检测鼠标.txt 汉字字模.txt 汉诺塔.txt 汉诺塔2.txt 灯塔问题.txt 猴子和桃.txt 百鸡百钱.txt 矩阵乘法动态规划.txt 矩阵转换.txt 硬币分法.txt 神经元模型.txt 穷举搜索法.txt 符号图形.txt 简单数据库.txt 简单计算器.txt 简单逆阵.txt 线性顺序存储结构.txt 线索化二叉树.txt 绘制圆.txt 编随机数.txt 网络最短路径Dijkstra算法.txt 自我复制.txt 节点.txt 苹果分法.txt 螺旋数组1.txt 螺旋数组2.txt 试题.txt 诺汉塔画图版.txt 读写文本文件.txt 货郎担分枝限界图形演示.txt 货郎担限界算法.txt 质因子.txt 输出自已.txt 迷宫.txt 迷宫问题.txt 逆波兰计算器.txt 逆矩阵.txt 逆阵.txt 递堆法.txt 递归桃猴.txt 递归车厢.txt 递推.txt 逻辑移动.txt 链串.txt 链栈.txt 链表十五人排序.txt 链表(递归).txt 链队列.txt 队列.txt 阶乘递归.txt 阿姆斯特朗数.txt 非递归.txt 顺序栈.txt 顺序表.txt 顺序队列.txt 骑士遍历1.txt 骑士遍历2.txt 骑士遍历回逆.txt 黑白.txt
16进制10进制.txt 32.txt asm.txt Crctable.txt C标志符命名源程序.txt erre.txt erre2.txt ff.txt for循环的.txt list.log N皇后问题回溯算法.txt ping.txt re.txt source.txt winsock2.txt ww.txt 万年历.txt 万年历的算法 .txt 乘方函数桃子猴.txt 乘法矩阵.txt 二分查找1.txt 二分查找2.txt 二叉排序树.txt 二叉树.txt 二叉树实例.txt 二进制数.txt 二进制数2.txt 余弦曲线.txt 余弦直线.txt 傻瓜递归.txt 冒泡排序.txt 冒泡法改进.txt 动态计算网络最长最短路线.txt 十五人排序.txt 单循环链表.txt 单词倒转.txt 单链表.txt 单链表1.txt 单链表2.txt 单链表倒序.txt 单链表的处理全集.txt 双链表正排序.txt 反出字符.txt 叠代整除.txt 各种排序法.txt 哈夫曼算法.txt 哈慢树.txt 四分砝码.txt 四塔1.txt 四塔2.txt 回文.txt 图.txt 圆周率.txt 多位阶乘.txt 多位阶乘2.txt 大加数.txt 大小倍约.txt 大整数.txt 字符串查找.txt 字符编辑.txt 字符编辑技术(插入和删除) .txt 完数.txt 定长串.txt 实例1.txt 实例2.txt 实例3.txt 小写数字转换成大写数字1.txt 小写数字转换成大写数字2.txt 小写数字转换成大写数字3.txt 小字库DIY-.txt 小字库DIY.txt 小孩分糖果.txt 小明买书.txt 小白鼠钻迷宫.txt 带头结点双链循环线性表.txt 平方根.txt 建树和遍历.txt 建立链表1.txt 扫描码.txt 挽救软盘.txt 换位递归.txt 排序法.txt 推箱子.txt 数字移动.txt 数据结构.txt 数据结构2.txt 数据结构3.txt 数组完全单元.txt 数组操作.txt 数组递归退出.txt 数组递归退出2.txt 文件加密.txt 文件复制.txt 文件连接.txt 无向图.txt 时间陷阱.txt 杨辉三角形.txt 栈单元加.txt 栈操作.txt 桃子猴.txt 桶排序.txt 检出错误.txt 检测鼠标.txt 汉字字模.txt 汉诺塔.txt 汉诺塔2.txt 灯塔问题.txt 猴子和桃.txt 百鸡百钱.txt 矩阵乘法动态规划.txt 矩阵转换.txt 硬币分法.txt 神经元模型.txt 穷举搜索法.txt 符号图形.txt 简单数据库.txt 简单计算器.txt 简单逆阵.txt 线性顺序存储结构.txt 线索化二叉树.txt 绘制圆.txt 编随机数.txt 网络最短路径Dijkstra算法.txt 自我复制.txt 节点.txt 苹果分法.txt 螺旋数组1.txt 螺旋数组2.txt 试题.txt 诺汉塔画图版.txt 读写文本文件.txt 货郎担分枝限界图形演示.txt 货郎担限界算法.txt 质因子.txt 输出自已.txt 迷宫.txt 迷宫问题.txt 逆波兰计算器.txt 逆矩阵.txt 逆阵.txt 递堆法.txt 递归桃猴.txt 递归车厢.txt 递推.txt 逻辑移动.txt 链串.txt 链栈.txt 链表十五人排序.txt 链表(递归).txt 链队列.txt 队列.txt 阶乘递归.txt 阿姆斯特朗数.txt 非递归.txt 顺序栈.txt 顺序表.txt 顺序队列.txt 骑士遍历1.txt 骑士遍历2.txt 骑士遍历回逆.txt 黑白.txt
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值