6-2 顺序表操作集(20 point(s))

本文介绍了一个简单的顺序表操作集的实现方法,包括创建空表、查找元素位置、插入元素和删除元素等基本操作,并提供了完整的C语言代码示例。
6-2 顺序表操作集(20 point(s))

本题要求实现顺序表的操作集。

函数接口定义:

List MakeEmpty(); 
Position Find( List L, ElementType X );
bool Insert( List L, ElementType X, Position P );
bool Delete( List L, Position P );

其中List结构定义如下:

typedef int Position;
typedef struct LNode *List;
struct LNode {
    ElementType Data[MAXSIZE];
    Position Last; /* 保存线性表中最后一个元素的位置 */
};

各个操作函数的定义为:

List MakeEmpty():创建并返回一个空的线性表;

Position Find( List L, ElementType X ):返回线性表中X的位置。若找不到则返回ERROR;

bool Insert( List L, ElementType X, Position P ):将X插入在位置P并返回true。若空间已满,则打印“FULL”并返回false;如果参数P指向非法位置,则打印“ILLEGAL POSITION”并返回false;

bool Delete( List L, Position P ):将位置P的元素删除并返回true。若参数P指向非法位置,则打印“POSITION P EMPTY”(其中P是参数值)并返回false。

裁判测试程序样例:

#include <stdio.h>
#include <stdlib.h>

#define MAXSIZE 5
#define ERROR -1
typedef enum {false, true} bool;
typedef int ElementType;
typedef int Position;
typedef struct LNode *List;
struct LNode {
    ElementType Data[MAXSIZE];
    Position Last; /* 保存线性表中最后一个元素的位置 */
};

List MakeEmpty(); 
Position Find( List L, ElementType X );
bool Insert( List L, ElementType X, Position P );
bool Delete( List L, Position P );

int main()
{
    List L;
    ElementType X;
    Position P;
    int N;

    L = MakeEmpty();
    scanf("%d", &N);
    while ( N-- ) {
        scanf("%d", &X);
        if ( Insert(L, X, 0)==false )
            printf(" Insertion Error: %d is not in.\n", X);
    }
    scanf("%d", &N);
    while ( N-- ) {
        scanf("%d", &X);
        P = Find(L, X);
        if ( P == ERROR )
            printf("Finding Error: %d is not in.\n", X);
        else
            printf("%d is at position %d.\n", X, P);
    }
    scanf("%d", &N);
    while ( N-- ) {
        scanf("%d", &P);
        if ( Delete(L, P)==false )
            printf(" Deletion Error.\n");
        if ( Insert(L, 0, P)==false )
            printf(" Insertion Error: 0 is not in.\n");
    }
    return 0;
}

/* 你的代码将被嵌在这里 */

输入样例:

6
1 2 3 4 5 6
3
6 5 1
2
-1 6

输出样例:

FULL Insertion Error: 6 is not in.
Finding Error: 6 is not in.
5 is at position 0.
1 is at position 4.
POSITION -1 EMPTY Deletion Error.
FULL Insertion Error: 0 is not in.
POSITION 6 EMPTY Deletion Error.
FULL Insertion Error: 0 is not in.

code:
List MakeEmpty(){
    List p;
    p = (List)malloc(sizeof(struct LNode));
    p->Last = -1;//这里令last为-1,这样可以last每次指的就是最后一个数据,而不是下一个数据的下一个
    return p;
}
Position Find( List L, ElementType X ){
    int i;
    for(i = 0; i <= L->Last; i++){
        if(X==L->Data[i]){//遍历搜索查找
            return i;
        }
    }
    return ERROR;
}
bool Insert( List L, ElementType X, Position P ){
    if(L->Last==MAXSIZE-1){//容量慢
        printf("FULL");
        return false;
    }
    if(P<0||P>L->Last+1){//只能查到已有数字的位置或最后一个的下一个
        printf("ILLEGAL POSITION");
        return false;
    }
    int i;
    for(i = L->Last+1; i > P; i--){
        L->Data[i] = L->Data[i-1];//向右平移
    }
    L->Data[i] = X;//插入
    L->Last++;//个数增加
    return true;
}
bool Delete( List L, Position P ){
    int i;
    //if(L->Last==-1)return false;//为空!!!因为这一句多此一举的判断导致为空时应输出empty没输出
    if(P<0||P>L->Last){//删除的位置不在已有位置内
        printf("POSITION %d EMPTY",P);
        return false;
    }
    for(i = P; i < L->Last; i++){//删除后向左平移
        L->Data[i] = L->Data[i+1];
    }
    L->Last--;//减少一个
    return true;
}

 
<think>我们有一个需求:将字母按分数分组的一对多映射转换为一对一的小写字母分数映射。 原映射可能是这样的:每个分数对应一个字符串,字符串中包含多个字母(大小写可能都有)。例如: 5: "AEIOU" 1: "aeiou" 2: "BCDF" 等等。 我们需要将其转换为:每个字母(转换为小写)对应一个分数。例如,上面的映射应该变成: 'a':5, 'e':5, 'i':5, 'o':5, 'u':5, // 注意:原大写字母转换成了小写,并且原小写字母的分数1被覆盖了?这里需要明确规则 但是注意,原映射中可能有同一个字母的大小写形式出现在不同的分数组中,例如上面的例子中,大写字母'A'在5分,小写字母'a'在1分。 根据需求,我们需要将字母转换为小写,那么转换后,同一个字母(小写)只能有一个分数。因此我们需要决定如何处理冲突。 问题中并没有明确冲突处理规则,但根据需求描述“每个字母单独存储的一对一映射”,且要求转换为小写,我们可以这样理解: - 最终映射中,每个小写字母作为键,其分数值应该是原映射中该字母(不论大小写)出现的分数值?但是原映射中同一个字母的大小写可能出现在不同组,那么就会产生冲突。 因此,我们需要明确:在转换过程中,如果同一个字母的大小写形式出现在不同的分数组中,那么以哪个为准? 由于问题没有明确,我们可以假设: - 方案1:按照原映射的顺序,后出现的覆盖先出现的? - 方案2:按照某种优先级(比如大写的优先级高于小写?或者相反?) - 方案3:或者原映射中同一个字母的大小写应该属于同一个分数?但原映射中出现了不同分数,说明数据可能有误? 但是,观察问题描述:“将字母按分数分组的一对多映射转换为一对一的小写字母分数映射”。这里强调的是“转换为一对一”,所以每个小写字母只能出现一次。 我们可以这样设计: - 遍历原映射的每一个分数组。 - 对于每个分数组中的字符串,遍历每个字符,将其转换为小写字母,然后建立这个字母到当前分数的映射。 - 如果同一个字母(小写)在之前已经出现过,那么后面的分数会覆盖前面的分数。 也就是说,如果原映射中,先出现小写字母'a'在1分组,后出现大写字母'A'在5分组,那么当我们遍历到5分组时,会将'a'(小写)的分数更新为5。 因此,最终每个小写字母的分数是它在原映射中最后一次出现的分数。 另一种可能:如果原映射中同时存在大小写字母,但要求我们忽略大小写,并将所有字母视为小写字母,那么我们就需要将每个字母都转成小写,然后建立映射,后出现的覆盖先出现的。 步骤: 1. 定义一个结构来表示原映射:可能是一个数组,每个元素是一个结构,包含分数和字符串(字符串包含字母)。 2. 创建一个新的映射(比如用数组或哈希表),用于存储每个小写字母对应的分数。 3. 遍历原映射的每个分组: for 每个分组(分数score,字符串str): for 字符串中的每个字符c: 将c转换为小写:char lower_c = tolower(c); 将映射中lower_c对应的分数设置为当前分组的score(覆盖之前的值) 4. 这样我们就得到了一个一对一的小写字母到分数的映射。 注意:原映射中可能包含非字母字符?根据需求,我们只处理字母,所以如果遇到非字母,我们可以跳过,或者报错?根据需求,我们只处理字母。 实现示例: 假设原映射用数组表示: struct ScoreGroup { int score; char *letters; } groups[] = { {5, "AEIOU"}, {1, "aeiou"}, {2, "BCDF"} }; 我们想要得到一个映射:一个数组(或哈希表)`mapping`,下标为字母(小写)的ASCII值,值为分数。例如,对于字母'a'(ASCII为97),我们设置mapping[97]=1,但随后在遍历第一组时,由于'A'被转换为'a',所以会设置mapping[97]=5。然后遍历第二组时,又设置一次为1。然后第三组没有a,所以最终是1?但是注意,我们的遍历顺序是先第一组(5分),然后第二组(1分),然后第三组(2分)。所以最后设置的是1分。但是实际上,我们希望的是最后出现的分数?还是先出现的? 根据我们的遍历顺序,后遍历的分组会覆盖先遍历的分组。但是原映射中,第一组是5分,第二组是1分,第三组是2分。在第二组中,我们遍历到小写字母'a',将其分数设置为1,覆盖了第一组设置的5分。 然而,如果我们希望保留的是第一次出现的分数,那么就需要在设置之前检查该字母是否已经设置过?如果已经设置过,则跳过。但问题没有明确,我们按照后覆盖前的方式(即最后出现的分数为准)来实现。 但是,问题描述中并没有说明优先级,所以我们可以按照两种方式提供,或者让用户选择。不过,根据问题描述,我们只要求转换为一对一映射,且字母为小写。所以覆盖策略是合理的,因为原映射中同一个字母出现多次,最后出现的分数就是最终分数。 另一种思路:原映射中,同一个字母的大小写形式可能分别出现在不同分组,但我们需要将它们视为同一个字母(小写),所以只能有一个分数。如果我们希望保留最高分,那么就需要在遍历时比较分数大小?但是问题没有要求,所以我们按照顺序覆盖。 因此,我们按照遍历顺序,后遍历的分组会覆盖先遍历的分组。 实现步骤: 1. 创建一个数组`score_map`,大小足够覆盖所有小写字母(比如256,按字符的ASCII值索引),初始化为-1(表示未设置)或0,或者根据需求。 2. 遍历原映射的每个分组: for (int i=0; i<group_count; i++) { int score = groups[i].score; char *s = groups[i].letters; while (*s) { char c = *s; // 转换为小写 char lower_c = tolower(c); // 将lower_c对应的分数设置为当前score score_map[(unsigned char)lower_c] = score; // 注意:使用unsigned char避免符号问题 s++; } } 3. 这样,score_map数组的下标就是小写字母的ASCII值,对应的值就是分数。 注意:我们只处理字母,但原映射中可能包含非字母?如果包含非字母,我们也可以处理,但问题要求是字母,所以我们可以跳过非字母?或者原映射保证只有字母?这里我们假设原映射只有字母。 如果原映射包含非字母,我们可以这样处理: if (!isalpha(c)) { // 跳过 continue; } 但是问题没有提到非字母,所以我们暂时不处理非字母,直接转换。 但是注意:原映射中的字符串可能包含大小写字母,我们全部转换为小写。 另外,原映射中可能包含重复的字母(比如同一个组内出现两次同一个字母,或者不同组出现同一个字母),我们按照上述方法处理(重复出现则覆盖)。 这样,我们就建立了一个从字母(小写)到分数的一对一映射。 但是,我们如何存储这个一对一映射?我们可以用一个结构体数组,每个结构体包含字母和分数,但这样查找效率低。或者用哈希表,但C语言没有内置哈希表。我们可以用一个数组,以字符的ASCII值作为索引,这样直接访问。 所以,我们用一个大小为256的整数数组,下标对应字符的ASCII码,值就是分数。对于非字母字符,我们也可以设置,但之后我们可以忽略。 示例代码: 假设原映射已经定义好,我们创建一个分数映射数组,然后遍历原映射填充。 注意:原映射中,同一个分组内的字母字符串可能包含重复字母?比如{5, "AEA"},那么字母'a'会被设置两次,但分数相同,所以没关系。 代码实现: 首先,包含头文件: #include <stdio.h> #include <ctype.h> // for tolower 然后,定义原映射结构: #define MAX_GROUPS 10 // 假设最多10个分组 struct ScoreGroup { int score; char *letters; // 字符串,以空字符结尾 }; 然后,我们有一个函数来建立映射: void build_mapping(struct ScoreGroup groups[], int group_count, int score_map[]) { // 初始化score_map,将所有字符的分数初始化为-1(表示未定义) for (int i=0; i<256; i++) { score_map[i] = -1; // 用-1表示未设置 } // 遍历每个分组 for (int i=0; i<group_count; i++) { char *s = groups[i].letters; while (*s) { char c = *s; // 转换为小写 char lower_c = tolower((unsigned char)c); // 注意:tolower函数参数是int,且需转换为unsigned char避免符号扩展 // 更新映射 score_map[(unsigned char)lower_c] = groups[i].score; s++; } } } 注意:tolower函数需要包含ctype.h,并且它接受一个int参数,返回int。我们传入的是char,需要转换为unsigned char再转换为int,以避免负的char值导致未定义行为。 使用示例: int main() { struct ScoreGroup groups[] = { {5, "AEIOU"}, {1, "aeiou"}, {2, "BCDF"} }; int group_count = sizeof(groups)/sizeof(groups[0]); int score_map[256]; // 索引为字符的ASCII值 build_mapping(groups, group_count, score_map); // 打印小写字母的分数 for (char c = 'a'; c <= 'z'; c++) { int score = score_map[(unsigned char)c]; if (score != -1) { printf("字母 %c 的分数是 %d\n", c, score); } } return 0; } 运行结果: 字母 a 的分数是 1 (因为第二组覆盖了第一组) 字母 e 的分数是 1 字母 i 的分数是 1 字母 o 的分数是 1 字母 u 的分数是 1 字母 b 的分数是 2 字母 c 的分数是 2 字母 d 的分数是 2 字母 f 的分数是 2 但是,我们可能希望保留第一组的大写字母的分数(即5分),那么我们可以调整遍历顺序:先遍历后面的分组,再遍历前面的分组?不行,因为覆盖是后遍历的覆盖先遍历的。 如果我们希望保留第一次出现的分数(即先遍历到的分组),那么可以在设置映射时,如果该字母已经设置过分数,则跳过。 修改build_mapping函数: void build_mapping(struct ScoreGroup groups[], int group_count, int score_map[]) { for (int i=0; i<256; i++) { score_map[i] = -1; } // 注意:这里我们按顺序遍历分组,但只设置尚未设置过的字母 for (int i=0; i<group_count; i++) { char *s = groups[i].letters; while (*s) { char c = *s; char lower_c = tolower((unsigned char)c); unsigned char idx = (unsigned char)lower_c; // 如果这个字母还没有设置过分数,则设置 if (score_map[idx] == -1) { score_map[idx] = groups[i].score; } s++; } } } 这样,先遍历的分组先设置,后遍历的分组如果遇到同一个字母已经设置过,就不会覆盖。 那么,使用这个版本,上面的示例输出: 字母 a 的分数是 5 (因为第一组设置了5,第二组再设置a时,发现已经设置过,就跳过了) 字母 e 的分数是 5 等等。 所以,我们需要根据需求选择覆盖策略。问题没有明确,我们可以提供两种方式,并让用户选择。 因此,我们可以增加一个参数来控制覆盖策略: enum { COVER_LAST, COVER_FIRST }; void build_mapping(struct ScoreGroup groups[], int group_count, int score_map[], int cover_policy) { if (cover_policy == COVER_FIRST) { // 先设置的有效,后设置的不覆盖 for (int i=0; i<256; i++) { score_map[i] = -1; } for (int i=0; i<group_count; i++) { char *s = groups[i].letters; while (*s) { char c = *s; char lower_c = tolower((unsigned char)c); unsigned char idx = (unsigned char)lower_c; if (score_map[idx] == -1) { score_map[idx] = groups[i].score; } s++; } } } else { // COVER_LAST: 后设置的有效,覆盖前面的 // 先全部初始化为-1 for (int i=0; i<256; i++) { score_map[i] = -1; } // 但这里我们按顺序遍历,后面的分组会覆盖前面的 for (int i=0; i<group_count; i++) { char *s = groups[i].letters; while (*s) { char c = *s; char lower_c = tolower((unsigned char)c); unsigned char idx = (unsigned char)lower_c; // 不管之前有没有设置,都覆盖 score_map[idx] = groups[i].score; s++; } } } } 这样,用户可以根据需要选择策略。 但是,问题要求是“将字母按分数分组的一对多映射转换为一对一的小写字母分数映射”,没有明确冲突处理,所以我们可以默认使用后覆盖前的策略(即后面的分组覆盖前面的),因为这样更符合遍历顺序。 总结:我们实现了两种策略,用户可以根据需要选择。 另外,我们还可以考虑只处理字母字符,对于非字母字符,我们可以跳过,避免设置到score_map中。在build_mapping函数中,我们可以检查字符是否为字母: if (!isalpha(c)) { s++; continue; } 修改后: void build_mapping(struct ScoreGroup groups[], int group_count, int score_map[], int cover_policy) { // 初始化 for (int i=0; i<256; i++) { score_map[i] = -1; } for (int i=0; i<group_count; i++) { char *s = groups[i].letters; while (*s) { char c = *s; // 检查是否为字母 if (!isalpha((unsigned char)c)) { s++; continue; } char lower_c = tolower((unsigned char)c); unsigned char idx = (unsigned char)lower_c; if (cover_policy == COVER_FIRST) { if (score_map[idx] == -1) { score_map[idx] = groups[i].score; } } else { score_map[idx] = groups[i].score; } s++; } } } 这样,非字母字符会被跳过,不会设置。 最后,我们根据用户的需求,可以选择覆盖策略。 注意:原映射中,同一个分组内出现非字母字符,我们跳过,这样就不会设置该字符。 因此,完整的程序示例: #include <stdio.h> #include <ctype.h> #define COVER_FIRST 0 #define COVER_LAST 1 struct ScoreGroup { int score; char *letters; }; void build_mapping(struct ScoreGroup groups[], int group_count, int score_map[], int cover_policy) { // 初始化score_map为-1 for (int i=0; i<256; i++) { score_map[i] = -1; } for (int i=0; i<group_count; i++) { char *s = groups[i].letters; while (*s) { unsigned char c = *s; // 用unsigned char避免符号问题 // 检查是否为字母 if (!isalpha(c)) { s++; continue; } char lower_c = tolower(c); if (cover_policy == COVER_FIRST) { if (score_map[lower_c] == -1) { score_map[lower_c] = groups[i].score; } } else { score_map[lower_c] = groups[i].score; } s++; } } } int main() { // 示例分组 struct ScoreGroup groups[] = { {5, "AEIOU"}, {1, "aeiou"}, {2, "BCDF"} }; int group_count = sizeof(groups)/sizeof(groups[0]); int score_map[256]; // 使用后覆盖前的策略(COVER_LAST) build_mapping(groups, group_count, score_map, COVER_LAST); // 打印所有小写字母的分数(如果设置了的话) for (char c = 'a'; c <= 'z'; c++) { if (score_map[(unsigned char)c] != -1) { printf("%c: %d\n", c, score_map[(unsigned char)c]); } } return 0; } 运行结果(COVER_LAST): a:1, e:1, i:1, o:1, u:1, b:2, c:2, d:2, f:2 如果使用COVER_FIRST策略: build_mapping(groups, group_count, score_map, COVER_FIRST); 结果: a:5, e:5, i:5, o:5, u:5, b:2, c:2, d:2, f:2 用户可以根据需要选择策略。 注意:原映射中,小写字母在第二组,所以使用COVER_FIRST时,第二组的小写字母不会覆盖第一组设置的大写字母(因为第一组已经将小写字母设置成5分,所以第二组设置时发现已经设置过,就不再设置)。 但是,原映射中第一组是大写字母,第二组是小写字母,它们转换成小写字母后是一样的。所以,在COVER_FIRST策略下,第一组设置的小写字母分数5,第二组就不会再设置(因为已经设置过)。而在COVER_LAST策略下,第二组会覆盖第一组的设置。 因此,我们实现了需求。 相关问题: 1. 如果原映射中同一个分组内出现了同一个字母多次(比如"AA"),会有影响吗? 答:不会,因为第一次设置后,如果是COVER_FIRST策略,第二次设置同一个字母时已经设置过,所以跳过;如果是COVER_LAST策略,第二次设置会覆盖第一次,但分数相同,所以结果一样。 2. 原映射中的非字母字符如何处理? 答:在循环中,我们使用isalpha检查,跳过非字母字符。 3. 是否区分大小写? 答:在转换时,我们将所有字母转换为小写,所以不区分大小写,最终映射的键都是小写字母。 最后,我们输出代码,并注意注释。</think>### 实现字母分数映射转换 在C语言中,将按分数分组的一对多映射(如 `{5: "AEIOU", 1: "aeiou", 2: "BCDF"}`)转换为一对一的小写字母分数映射,需遵循以下步骤: 1. **初始化映射表** 创建一个长度为 256 的整数数组(覆盖 ASCII 表),初始值设为 -1(表示未定义)。 2. **遍历分组并填充映射** - 对每个分数分组中的字符串逐字符处理 - 将字符转换为小写(`tolower()`) - 直接覆盖写入映射表(后出现的分组优先级更高) 3. **冲突处理** 同一字母出现在不同分组时,**后遍历的分组会覆盖先前的值**(可通过调整分组遍历顺序控制优先级)。 #### 示例代码 ```c #include <stdio.h> #include <ctype.h> // 包含 tolower() #define COVER_LAST 1 // 后覆盖先策略 int main() { // 1. 定义原始分组映射(分数 -> 字母串) struct ScoreGroup { int score; char *letters; } groups[] = { {5, "AEIOU"}, // 分组1 {1, "aeiou"}, // 分组2(小写组) {2, "BCDF"} // 分组3 }; int group_count = sizeof(groups) / sizeof(groups[0]); // 2. 初始化映射表(ASCII范围) int score_map[256]; for (int i = 0; i < 256; i++) { score_map[i] = -1; // -1表示未定义 } // 3. 构建一对一映射(转换为小写) for (int i = 0; i < group_count; i++) { char *s = groups[i].letters; while (*s) { unsigned char c = *s; if (isalpha(c)) { // 确保是字母 char lower_c = tolower(c); // 转为小写 score_map[lower_c] = groups[i].score; // 直接覆盖写入 } s++; } } // 4. 打印转换结果(仅显示小写字母映射) printf("小写字母分数映射:\n"); for (char c = 'a'; c <= 'z'; c++) { if (score_map[c] != -1) { printf(" %c -> %d\n", c, score_map[c]); } } return 0; } ``` #### 输出示例 ``` 小写字母分数映射: a -> 1 // 分组2覆盖了分组1的5分 b -> 2 c -> 2 d -> 2 e -> 1 f -> 2 i -> 1 o -> 1 u -> 1 ``` #### 关键说明 1. **大小写处理** `tolower()` 函数确保所有字母统一为小写,例如 `'A'` 和 `'a'` 均映射为 `'a'`。 2. **覆盖策略** 默认**后遍历的分组优先**(如分组2的 `aeiou=1` 覆盖分组1的 `AEIOU=5`)。若需优先保留先出现的值: ```c // 在遍历循环内添加检查 if (score_map[lower_c] == -1) { // 仅当未设置时写入 score_map[lower_c] = groups[i].score; } ``` 3. **非字母过滤** `isalpha()` 确保跳过数字、符号等非字母字符。 #### 应用场景 - 游戏中的字母分数系统 - 文本分析中的字符权重计算 - 密码学中的字符映射表 --- ### 相关问题 1. **如何实现大小写无关的字母分数查询?** 查询时统一将输入字符转换为小写,再查表即可: ```c int get_score(char c) { return score_map[(unsigned char)tolower(c)]; } ``` 2. **若需保留原始大小写信息,数据结构应如何设计?** 可改用结构体数组存储每个字母的原始形式和分数: ```c struct CharScore { char original_char; int score; }; // 遍历时同时记录原始字符和转换后的小写形式 ``` 3. **如何处理分组间的分数冲突(如字母 'a' 在两组中分数不同)?** 提供两种策略函数: ```c void build_mapping(ScoreGroup* groups, int count, int policy) { // policy=0: 先出现的分组优先 // policy=1: 后出现的分组优先(默认) } ``` 4. **如何扩展支持Unicode字符?** 需改用宽字符(`wchar_t`)和哈希表存储映射,例如: ```c #include <wchar.h> #include <locale.h> setlocale(LC_ALL, ""); // 启用本地化 wchar_t wide_str[] = L"中文字符"; // 使用第三方库(如uthash)实现宽字符哈希表 ``` 5. **如何优化大映射表的查询效率?** - 字母类映射:直接索引(O(1)) - 扩展字符集:哈希表(O(1) 平均) - 范围查询:前缀树(Trie) [^1]: 关于字符大小写转换的位操作技巧 [^2]: C语言终端输出模式配置细节
评论 10
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值