数据结构与算法分析 使用C语言实现的读取教材目录文件并生成树和二叉树结构,保存为新的文本文件并输出

将教材目录生成为普通树结构的代码:

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <direct.h>

#define MAX_CHILDREN 12  // 每个节点最多11个子节点

// 树节点结构体

typedef struct TreeNode {

    int id;

char longid[50];  //作为主码

    char name[100];

    int pageStart;

    int pageEnd;

    int level;

    struct TreeNode* parent;

    struct TreeNode* children[MAX_CHILDREN]; // 子节点数组

} TreeNode;

// 树结构

typedef struct {

    TreeNode* root;

} ChapterTree;

void PrintTreeStructure(ChapterTree* tree) {

    // 如果树的根节点为空,直接返回

    if (!tree->root) return;

    // 定义一个队列,用于层次遍历树结构,最多存储2000个节点

    TreeNode* queue[2000];

    // 初始化

    int front = 0, rear = 0;

    // 将根节点入队

    queue[rear++] = tree->root;

    // 当队列不为空时,循环遍历

    while (front < rear) {

        // 取队列头节点

        TreeNode* current = queue[front++];

        // 如果当前节点有子节点,则打印当前节点的信息

        if (current->children[0] != NULL) {

            printf("节点%d [%s] 的子节点: ", current->id, current->longid);

            // 如果使用name会输出乱码,因为无法识别中文字体,所以使用longid(主码)作为输出对象

        }

        // 遍历所有子节点位置(包括NULL)

        for (int i = 0; i < MAX_CHILDREN; i++) {

            // 如果子节点为空,跳出循环

            if (current->children[i] == NULL) {

                break;

            } else {

                printf("[%d]%d ", i, current->children[i]->id);        // 打印子节点的索引和id

                queue[rear++] = current->children[i];                  // 将子节点入队

            }

        }

        // 如果当前节点有子节点,则换行

        if (current->children[0] != NULL) {

            printf("\n");

        }

    }

}

// 查找指定ID的节点

TreeNode* FindNodeById(ChapterTree* tree, int targetId) {

    // 如果树为空,直接返回NULL

    if (!tree->root) return NULL;

    // 创建一个队列用于广度优先搜索,最大容量为2000

    TreeNode* queue[2000];

    int front = 0, rear = 0;

    // 将根节点入队

    queue[rear++] = tree->root;

    // 当队列不为空时继续搜索

    while (front < rear) {

        // 取出队列头部的节点

        TreeNode* current = queue[front++];

        // 如果当前节点的ID等于目标ID,返回该节点

        if (current->id == targetId) return current;

        

        // 遍历当前节点的所有子节点

        for (int i = 0; i < MAX_CHILDREN; i++) {

            // 如果子节点存在,将其入队

            if (current->children[i]) {

                queue[rear++] = current->children[i];

            }

        }

    }

    // 如果遍历完整棵树仍未找到,返回NULL

    return NULL;

}

// 从文件加载章节树

void LoadFile(const char* filename, ChapterTree* tree) {

    // 创建虚拟根节点

    tree->root = (TreeNode*)calloc(1, sizeof(TreeNode));

    strcpy(tree->root->longid, "0");

    strcpy(tree->root->name, "Root");

    tree->root->id = 0;

    tree->root->parent = NULL;

    tree->root->level = 0;

    // 打开文件

    FILE* file = fopen(filename, "r");

    if (!file) {

        // 如果文件打开失败,释放根节点并返回

        perror("无法打开文件");

        free(tree->root);

        tree->root = NULL;

        return;

    }

    char line[256];

    // 逐行读取文件内容

    while (fgets(line, sizeof(line), file)) {

        // 去掉行尾的换行符

        line[strcspn(line, "\n")] = 0;

        // 解析字段,以制表符为分隔符(我的理解是类似于python的解包,将元组中的的值进行写入)

        char* token = strtok(line, "\t");

        char longid[50] = "";

        strncpy(longid, token, 49);

        token = strtok(NULL, "\t");

        char name[100] = "";

        strncpy(name, token, 99);

        token = strtok(NULL, "\t");

        int pageStart = token ? atoi(token) : 0;

        token = strtok(NULL, "\t");

        int pageEnd = token ? atoi(token) : 0;

        token = strtok(NULL, "\t");

        int id = token ? atoi(token) : 0;

        token = strtok(NULL, "\t");

        int parentId = token ? atoi(token) : 0;

        // 创建新节点,并赋值

        TreeNode* newNode = (TreeNode*)calloc(1, sizeof(TreeNode));

        strncpy(newNode->name, name, 99);

        newNode->pageStart = pageStart;

        newNode->pageEnd = pageEnd;

        newNode->id = id;

        strncpy(newNode->longid, longid, 49);

        newNode->level = 0;

        // 查找父节点,如果parentId为0,则父节点为根节点

        TreeNode* parent = (parentId == 0) ? tree->root : FindNodeById(tree, parentId);

        if (parent) {

            // 寻找父节点的第一个空子节点位置

            int insertPos = -1;

            for (int i = 0; i < MAX_CHILDREN; i++) {

                if (!parent->children[i]) {

                    insertPos = i;

                    break;

                }

            }

            

            // 如果找到空位置,将新节点插入

            if (insertPos != -1) {

                parent->children[insertPos] = newNode;

                newNode->parent = parent;

                newNode->level = parent->level + 1;

            } else {

                // 如果父节点已满,打印错误信息并释放新节点

                printf("错误:父节点%d已达最大子节点数,无法插入%d\n", parentId, id);

                free(newNode);

            }

        } else {

            // 如果未找到父节点,打印错误信息并释放新节点

            printf("未找到父节点%d,节点%d未被插入\n", parentId, id);

            free(newNode);

        }

    }

    // 关闭文件

    fclose(file);

}

// 写入txt文件函数

void WriteToFile(const char* filename, ChapterTree* tree) {

    if (!tree->root) return;

    FILE* file = fopen(filename, "w");

    if (!file) {

        perror("无法打开文件");

        return;

    }

    TreeNode* queue[2000];

    int front = 0, rear = 0;

    queue[rear++] = tree->root;

    while (front < rear) {

        TreeNode* current = queue[front++];

        // 写入当前节点信息

        fprintf(file, "节点%d [%s] 的子节点: ", current->id, current->longid);

        // 遍历所有子节点位置(包括NULL)

        for (int i = 0; i < MAX_CHILDREN; i++) {

            if (current->children[i]==NULL) {

                break;

            } else {

                fprintf(file, "[%d]%d ", i, current->children[i]->id);

                queue[rear++] = current->children[i];

            }

        }

        fprintf(file, "\n");

    }

    fclose(file);

}

int main() {

    ChapterTree tree = {NULL};

    // 加载文件

    //LoadFile("目录1.txt", &tree);

LoadFile("目录(优化).txt", &tree);  //将在章节名按*+章节号命名,不会有汉字错误

    

    // 输出树结构

    printf("树结构(节点ID [子节点位置]子节点ID):\n");

    PrintTreeStructure(&tree);

 // 写入文件

WriteToFile("树结构.txt", &tree);

    getchar();

    return 0;

}

结果:

同时生成了新文件,成功!

输出的优化后目录的结果为:

节点0 [0] 的子节点: [0]1 [1]16 [2]37 [3]57 [4]69 [5]82 [6]92 [7]105 [8]136 [9]159 [10]174 [11]189

节点1 [*1] 的子节点: [0]2 [1]8 [2]9

节点16 [*2] 的子节点: [0]17 [1]18 [2]19 [3]20 [4]25 [5]32 [6]33

节点37 [*3] 的子节点: [0]38 [1]43 [2]46 [3]53

节点57 [*4] 的子节点: [0]58 [1]62 [2]63 [3]64

节点69 [*5] 的子节点: [0]70 [1]74 [2]77 [3]78

节点82 [*6] 的子节点: [0]83 [1]84 [2]85 [3]86 [4]87 [5]88

节点92 [*7] 的子节点: [0]93 [1]96 [2]99

节点105 [*8] 的子节点: [0]106 [1]111 [2]115 [3]118 [4]123 [5]128 [6]132 [7]133 [8]134

节点136 [*9] 的子节点: [0]137 [1]140 [2]143 [3]146 [4]149 [5]153 [6]156 [7]157

节点159 [*10] 的子节点: [0]160 [1]161 [2]164 [3]167 [4]170 [5]171 [6]172

节点174 [*11] 的子节点: [0]175 [1]176 [2]180 [3]183

节点189 [bibiliography] 的子节点:

节点2 [1.1] 的子节点: [0]3 [1]4 [2]5 [3]6 [4]7

节点8 [1.2] 的子节点:

节点9 [1.3] 的子节点: [0]10 [1]11 [2]12 [3]13 [4]14

节点17 [2.1] 的子节点:

节点18 [2.1.1] 的子节点:

节点19 [2.1.2] 的子节点:

节点20 [2.2] 的子节点: [0]21 [1]22 [2]23 [3]24

节点25 [2.3] 的子节点: [0]26 [1]27 [2]28 [3]29 [4]30 [5]31

节点32 [2.4] 的子节点:

节点33 [2.5] 的子节点: [0]34 [1]35

节点38 [3.1] 的子节点: [0]39 [1]40 [2]41 [3]42

节点43 [3.2] 的子节点: [0]44 [1]45

节点46 [3.3] 的子节点: [0]47 [1]48 [2]49 [3]50 [4]51 [5]52

节点53 [3.4] 的子节点: [0]54 [1]55

节点58 [4.1] 的子节点: [0]59 [1]60 [2]61

节点62 [4.2] 的子节点:

节点63 [4.3] 的子节点:

节点64 [4.4] 的子节点: [0]65 [1]66 [2]67

节点70 [5.1] 的子节点: [0]71 [1]72 [2]73

节点74 [5.2] 的子节点: [0]75 [1]76

节点77 [5.3] 的子节点: [0]79 [1]80

节点78 [5.4] 的子节点:

节点83 [6.1] 的子节点:

节点84 [6.2] 的子节点:

节点85 [6.3] 的子节点:

节点86 [6.4] 的子节点:

节点87 [6.5] 的子节点:

节点88 [6.6] 的子节点: [0]89 [1]90

节点93 [7.1] 的子节点: [0]94 [1]95

节点96 [7.2] 的子节点: [0]97 [1]98

节点99 [7.3] 的子节点: [0]100 [1]101 [2]102 [3]103

节点106 [8.1] 的子节点: [0]107 [1]108 [2]109 [3]110

节点111 [8.2] 的子节点: [0]112 [1]113 [2]114

节点115 [8.3] 的子节点: [0]116 [1]117

节点118 [8.4] 的子节点: [0]119 [1]120 [2]121 [3]122

节点123 [8.5] 的子节点: [0]124 [1]125 [2]126 [3]127

节点128 [8.6] 的子节点: [0]129 [1]130 [2]131

节点132 [8.7] 的子节点:

节点133 [8.8] 的子节点:

节点134 [8.9] 的子节点:

节点137 [9.1] 的子节点: [0]138 [1]139

节点140 [9.2] 的子节点: [0]141 [1]142

节点143 [9.3] 的子节点: [0]144 [1]145

节点146 [9.4] 的子节点: [0]147 [1]148

节点149 [9.5] 的子节点: [0]150 [1]151 [2]152

节点153 [9.6] 的子节点: [0]154 [1]155

节点156 [9.7] 的子节点:

节点157 [9.8] 的子节点:

节点160 [10.1] 的子节点:

节点161 [10.2] 的子节点: [0]162 [1]163

节点164 [10.3] 的子节点: [0]165 [1]166

节点167 [10.4] 的子节点: [0]168 [1]169

节点170 [10.5] 的子节点:

节点171 [10.6] 的子节点:

节点172 [10.7] 的子节点:

节点175 [11.1] 的子节点:

节点176 [11.2] 的子节点: [0]177 [1]178 [2]179

节点180 [11.3] 的子节点: [0]181 [1]182

节点183 [11.4] 的子节点: [0]184 [1]185 [2]186 [3]187

节点3 [1.1.1] 的子节点:

节点4 [1.1.2] 的子节点:

节点5 [1.1.3] 的子节点:

节点6 [1.1.4] 的子节点:

节点7 [1.1.5] 的子节点:

节点10 [1.3.1] 的子节点:

节点11 [1.3.2] 的子节点:

节点12 [1.3.3] 的子节点:

节点13 [1.3.4] 的子节点:

节点14 [1.3.5] 的子节点:

节点21 [2.2.1] 的子节点:

节点22 [2.2.2] 的子节点:

节点23 [2.2.3] 的子节点:

节点24 [2.2.4] 的子节点:

节点26 [2.3.1] 的子节点:

节点27 [2.3.2] 的子节点:

节点28 [2.3.3] 的子节点:

节点29 [2.3.4] 的子节点:

节点30 [2.3.5] 的子节点:

节点31 [2.3.6] 的子节点:

节点34 [2.5.1] 的子节点:

节点35 [2.5.2] 的子节点:

节点39 [3.1.1] 的子节点:

节点40 [3.1.2] 的子节点:

节点41 [3.1.3] 的子节点:

节点42 [3.1.4] 的子节点:

节点44 [3.2.1] 的子节点:

节点45 [3.2.2] 的子节点:

节点47 [3.3.1] 的子节点:

节点48 [3.3.2] 的子节点:

节点49 [3.3.3] 的子节点:

节点50 [3.3.4] 的子节点:

节点51 [3.3.5] 的子节点:

节点52 [3.3.6] 的子节点:

节点54 [3.4.1] 的子节点:

节点55 [3.4.2] 的子节点:

节点59 [4.1.1] 的子节点:

节点60 [4.1.2] 的子节点:

节点61 [4.1.3] 的子节点:

节点65 [4.4.1] 的子节点:

节点66 [4.4.2] 的子节点:

节点67 [4.4.3] 的子节点:

节点71 [5.1.1] 的子节点:

节点72 [5.1.2] 的子节点:

节点73 [5.1.3] 的子节点:

节点75 [5.2.1] 的子节点:

节点76 [5.2.2] 的子节点:

节点79 [5.4.1] 的子节点:

节点80 [5.4.2] 的子节点:

节点89 [6.6.1] 的子节点:

节点90 [6.6.2] 的子节点:

节点94 [7.1.1] 的子节点:

节点95 [7.1.2] 的子节点:

节点97 [7.2.1] 的子节点:

节点98 [7.2.2] 的子节点:

节点100 [7.3.1] 的子节点:

节点101 [7.3.2] 的子节点:

节点102 [7.3.3] 的子节点:

节点103 [7.3.4] 的子节点:

节点107 [8.1.1] 的子节点:

节点108 [8.1.2] 的子节点:

节点109 [8.1.3] 的子节点:

节点110 [8.1.4] 的子节点:

节点112 [8.2.1] 的子节点:

节点113 [8.2.2] 的子节点:

节点114 [8.2.3] 的子节点:

节点116 [8.3.1] 的子节点:

节点117 [8.3.2] 的子节点:

节点119 [8.4.1] 的子节点:

节点120 [8.4.2] 的子节点:

节点121 [8.4.3] 的子节点:

节点122 [8.4.4] 的子节点:

节点124 [8.5.1] 的子节点:

节点125 [8.5.2] 的子节点:

节点126 [8.5.3] 的子节点:

节点127 [8.5.4] 的子节点:

节点129 [8.6.1] 的子节点:

节点130 [8.6.2] 的子节点:

节点131 [8.6.3] 的子节点:

节点138 [9.1.1] 的子节点:

节点139 [9.1.2] 的子节点:

节点141 [9.2.1] 的子节点:

节点142 [9.2.2] 的子节点:

节点144 [9.3.1] 的子节点:

节点145 [9.3.2] 的子节点:

节点147 [9.4.1] 的子节点:

节点148 [9.4.2] 的子节点:

节点150 [9.5.1] 的子节点:

节点151 [9.5.2] 的子节点:

节点152 [9.5.3] 的子节点:

节点154 [9.6.1] 的子节点:

节点155 [9.6.2] 的子节点:

节点162 [10.2.1] 的子节点:

节点163 [10.2.2] 的子节点:

节点165 [10.3.1] 的子节点:

节点166 [10.3.2] 的子节点:

节点168 [10.4.1] 的子节点:

节点169 [10.4.2] 的子节点:

节点177 [11.2.1] 的子节点:

节点178 [11.2.2] 的子节点:

节点179 [11.2.3] 的子节点:

节点181 [11.3.1] 的子节点:

节点182 [11.3.2] 的子节点:

节点184 [11.4.1] 的子节点:

节点185 [11.4.2] 的子节点:

节点186 [11.4.3] 的子节点:

节点187 [11.4.4] 的子节点:

希望去除其没有子节点的输出:

// 写入txt文件函数

void WriteToFile(const char* filename, ChapterTree* tree) {

    if (!tree->root) return;

    FILE* file = fopen(filename, "w");

    if (!file) {

        perror("无法打开文件");

        return;

    }

    TreeNode* queue[2000];

    int front = 0, rear = 0;

    queue[rear++] = tree->root;

    while (front < rear) {

        TreeNode* current = queue[front++];

        

// 如果当前节点有子节点, 写入当前节点信息。

        if (current->children[0] != NULL) {

            fprintf(file, "节点%d [%s] 的子节点: ", current->id, current->longid);

            // 如果使用name会输出乱码,因为无法识别中文字体,所以使用longid(主码)作为输出对象

        }

        fprintf(file, "节点%d [%s] 的子节点: ", current->id, current->longid);

        // 遍历所有子节点位置(包括NULL)

        for (int i = 0; i < MAX_CHILDREN; i++) {

            if (current->children[i]==NULL) {

                break;

            } else {

                fprintf(file, "[%d]%d ", i, current->children[i]->id);

                queue[rear++] = current->children[i];

            }

        }

        fprintf(file, "\n");

    }

    fclose(file);

}

使用二叉树仿真指针实现的二叉树结构的代码:

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

typedef char DataType1;

#include"标头.h" 

#include <direct.h>

// 层次遍历输出树的结构,按照孩子兄弟表示法打印每个节点的自身编码、左孩子编码和右兄弟编码

void PrintAsChildSibling(ChapterTree* tree) {

    if (!tree->root) return; // 如果树为空,直接返回

    int max_nodes = 2000; // 队列的最大容量

    BiTreeNode** queue = (BiTreeNode**)malloc(sizeof(BiTreeNode*) * max_nodes); // 创建队列,用于层次遍历

    int front = 0, rear = 0; // 队列的头尾指针

    

    queue[rear++] = tree->root; // 将根节点入队

    

    while (front < rear) { // 队列不为空时循环

        BiTreeNode* current = queue[front++]; // 出队一个节点

        // 获取当前节点的左孩子和右兄弟的编码,若不存在则为0

        int leftId = current->leftChild ? current->leftChild->id : 0;

        int rightId = current->rightChild ? current->rightChild->id : 0;

        // 打印当前节点的自身编码、左孩子编码和右兄弟编码

        printf("%d %d %d\n", current->id, leftId, rightId);

        

        // 遍历当前节点的所有孩子节点(通过左孩子和右兄弟链表)

        BiTreeNode* child = current->leftChild;

        while (child) {

            if (rear >= max_nodes) { // 如果队列满,提示并退出

                printf("队列溢出! 最大容量:%d\n", max_nodes);

                free(queue);

                return;

            }

            queue[rear++] = child; // 将孩子节点入队

            child = child->rightChild; // 移动到下一个兄弟节点

        }

    }

    free(queue); // 释放队列内存

}

// 辅助函数:通过节点编码查找对应的节点

BiTreeNode* FindNodeById(ChapterTree* tree, int id) {

    if (!tree->root) return NULL; // 如果树为空,返回空

    BiTreeNode** queue = (BiTreeNode**)malloc(sizeof(BiTreeNode*) * 2000); // 创建队列

    int front = 0, rear = 0;

    queue[rear++] = tree->root; // 根节点入队

    while (front < rear) { // 队列不为空时循环

        BiTreeNode* current = queue[front++]; // 出队一个节点

        if (current->id == id) { // 如果找到目标节点

            free(queue); // 释放队列内存

            return current; // 返回该节点

        }

        // 遍历当前节点的所有孩子节点并入队

        BiTreeNode* child = current->leftChild;

        while (child) {

            if (rear < 2000) { // 队列未满时

                queue[rear++] = child; // 孩子节点入队

            }

            child = child->rightChild; // 移动到下一个兄弟节点

        }

    }

    free(queue); // 释放队列内存

    return NULL; // 未找到,返回空

}

// 读取文件并构建树(修正版)

void LoadFile(const char* filename, ChapterTree* tree) {

    // 创建虚拟根节点,作为整棵树的根

    tree->root = (BiTreeNode*)malloc(sizeof(BiTreeNode));

    strcpy(tree->root->longid, "0"); // 设置虚拟根节点的longid

    strcpy(tree->root->name, "Root"); // 设置虚拟根节点的名称

    tree->root->pageStart = 0; // 设置虚拟根节点的起始页码

    tree->root->pageEnd = 0; // 设置虚拟根节点的结束页码

    tree->root->id = 0; // 设置虚拟根节点的编码

    tree->root->parentId = -1; // 标记为虚拟根节点,父节点编码为-1

    tree->root->parent = NULL; // 父节点指针为空

    tree->root->leftChild = NULL; // 左孩子指针为空

    tree->root->rightChild = NULL; // 右兄弟指针为空

    tree->root->level = 0; // 层级为0

    FILE* file = fopen(filename, "r"); // 打开文件

    if (!file) { // 如果文件打开失败

        perror("无法打开文件"); // 打印错误信息

        free(tree->root); // 释放虚拟根节点内存

        tree->root = NULL; // 树根置空

        return; // 返回

    }

    char line[256]; // 用于存储每一行数据

    // 按行读取文件内容

    while (fgets(line, sizeof(line), file)) {

        line[strcspn(line, "\n")] = 0; // 去掉换行符

        char* token = strtok(line, "\t"); // 以制表符分割字符串

        if (!token) continue; // 如果分割失败,跳过

        char longid[50]; // 存储longid

        strcpy(longid, token); // 获取longid

        token = strtok(NULL, "\t"); // 获取下一个字段

        if (!token) continue; // 如果分割失败,跳过

        char name[256]; // 存储名称

        strcpy(name, token); // 获取名称

        token = strtok(NULL, "\t"); // 获取下一个字段

        int pageStart = token ? atoi(token) : 0; // 获取起始页码

        token = strtok(NULL, "\t"); // 获取下一个字段

        int pageEnd = token ? atoi(token) : 0; // 获取结束页码

        token = strtok(NULL, "\t"); // 获取下一个字段

        int id = token ? atoi(token) : 0; // 获取节点编码

        token = strtok(NULL, "\t"); // 获取下一个字段

        int parentId = token ? atoi(token) : 0; // 获取父节点编码

        // 创建新节点

        BiTreeNode* newNode = (BiTreeNode*)malloc(sizeof(BiTreeNode));

        strncpy(newNode->name, name, 99); // 设置名称

        newNode->name[99] = '\0'; // 确保字符串以null结尾

        newNode->pageStart = pageStart; // 设置起始页码

        newNode->pageEnd = pageEnd; // 设置结束页码

        newNode->id = id; // 设置节点编码

        newNode->parentId = parentId; // 设置父节点编码

        strncpy(newNode->longid, longid, 49); // 设置longid

        newNode->longid[49] = '\0'; // 确保字符串以null结尾

        newNode->level = 0; // 层级将在插入时更新

        newNode->parent = NULL; // 父节点指针初始化为空

        newNode->leftChild = NULL; // 左孩子指针初始化为空

        newNode->rightChild = NULL; // 右兄弟指针初始化为空

        // 查找父节点(parentId=0时查找虚拟根节点)

        BiTreeNode* parent = (parentId == 0) ? tree->root : FindNodeById(tree, parentId);

        if (parent) { // 如果找到父节点

            if (!parent->leftChild) { // 如果父节点没有左孩子

                parent->leftChild = newNode; // 设置为左孩子

                newNode->parent = parent; // 设置父节点指针

                newNode->level = parent->level + 1; // 更新层级

            } else { // 如果父节点已有左孩子

                // 找到父节点的最右边的兄弟节点

                BiTreeNode* sibling = parent->leftChild;

                while (sibling->rightChild) {

                    sibling = sibling->rightChild;

                }

                sibling->rightChild = newNode; // 设置为最右边兄弟的右兄弟

                newNode->parent = parent; // 设置父节点指针

                newNode->level = parent->level + 1; // 更新层级

            }

        } else { // 如果未找到父节点

            printf("未找到父节点 %d,节点 %d 未被插入\n", parentId, id); // 提示信息

            free(newNode); // 释放新节点内存,避免内存泄漏

        }

    }

    fclose(file); // 关闭文件

}

// 将树的结构保存到文件中

void SaveToFile(ChapterTree* tree, const char* filename) {

    if (!tree->root) return; // 如果树为空,直接返回

    FILE* file = fopen(filename, "w"); // 打开文件,准备写入

    if (!file) { // 如果文件打开失败

        perror("无法创建文件");

        return;

    }

    int max_nodes = 2000; // 队列的最大容量

    BiTreeNode** queue = (BiTreeNode**)malloc(sizeof(BiTreeNode*) * max_nodes); // 创建队列,用于层次遍历

    int front = 0, rear = 0; // 队列的头尾指针

    

    queue[rear++] = tree->root; // 将根节点入队

    

    while (front < rear) { // 队列不为空时循环

        BiTreeNode* current = queue[front++]; // 出队一个节点

        // 获取当前节点的左孩子和右兄弟的编码,若不存在则为0

        int leftId = current->leftChild ? current->leftChild->id : 0;

        int rightId = current->rightChild ? current->rightChild->id : 0;

        // 将当前节点的自身编码、左孩子编码和右兄弟编码写入文件

        fprintf(file, "%d %d %d\n", current->id, leftId, rightId);

        

        // 遍历当前节点的所有孩子节点(通过左孩子和右兄弟链表)

        BiTreeNode* child = current->leftChild;

        while (child) {

            if (rear >= max_nodes) { // 如果队列满,提示并退出

                printf("队列溢出! 最大容量:%d\n", max_nodes);

                free(queue);

                fclose(file);

                return;

            }

            queue[rear++] = child; // 将孩子节点入队

            child = child->rightChild; // 移动到下一个兄弟节点

        }

    }

    free(queue); // 释放队列内存

    fclose(file); // 关闭文件

}

int main() {

    ChapterTree tree;

    tree.root = NULL; // 初始化树,根为空

    // 加载文件,构建树

    LoadFile("目录.txt", &tree);

    // 按孩子兄弟表示法输出树的结构

    printf("节点信息(自身编码 左孩子 右兄弟):\n");

    PrintAsChildSibling(&tree);

 // 将树的结构保存到文件中

    SaveToFile(&tree, "二叉树树结构.txt");

    getchar();

    return 0;

}

结果:

同时生成了新文件,成功!

输出结果为:0 1 0

1 2 1

1 0 16

16 17 16

16 0 37

37 38 37

37 0 57

57 58 57

57 0 69

69 70 77

77 0 82

82 83 82

82 0 92

92 93 92

92 0 105

105 106 105

105 0 136

136 137 136

136 0 159

159 160 159

159 0 174

174 175 174

174 0 0

0 0 0

2 3 8

8 0 9

9 10 0

17 0 18

18 0 19

19 0 20

20 21 25

25 26 32

32 0 33

33 34 0

38 39 43

43 44 46

46 47 53

53 54 0

58 59 62

62 0 63

63 0 64

64 65 0

70 71 74

74 75 77

77 79 78

78 0 0

83 0 84

84 0 85

85 0 86

86 0 87

87 0 88

88 89 0

93 94 96

96 97 99

99 100 0

106 107 111

111 112 115

115 116 118

118 119 123

123 124 128

128 129 132

132 0 133

133 0 134

134 0 0

137 138 140

140 141 143

143 144 146

146 147 149

149 150 153

153 154 156

156 0 157

157 0 0

160 0 161

161 162 164

164 165 167

167 168 170

170 0 171

171 0 172

172 0 0

175 0 176

176 177 180

180 181 183

183 184 0

3 0 4

4 0 5

5 0 6

6 0 7

7 0 0

10 0 11

11 0 12

12 0 13

13 0 14

14 0 0

21 0 22

22 0 23

23 0 24

24 0 0

26 0 27

27 0 28

28 0 29

29 0 30

30 0 31

31 0 0

34 0 35

35 0 0

39 0 40

40 0 41

41 0 42

42 0 0

44 0 45

45 0 0

47 0 48

48 0 49

49 0 50

50 0 51

51 0 52

52 0 0

54 0 55

55 0 0

59 0 60

60 0 61

61 0 0

65 0 66

66 0 67

67 0 0

71 0 72

72 0 73

73 0 0

75 0 76

76 0 0

79 0 80

80 0 0

89 0 90

90 0 0

94 0 95

95 0 0

97 0 98

98 0 0

100 0 101

101 0 102

102 0 103

103 0 0

107 0 108

108 0 109

109 0 110

110 0 0

112 0 113

113 0 114

114 0 0

116 0 117

117 0 0

119 0 120

120 0 121

121 0 122

122 0 0

124 0 125

125 0 126

126 0 127

127 0 0

129 0 130

130 0 131

131 0 0

138 0 139

139 0 0

141 0 142

142 0 0

144 0 145

145 0 0

147 0 148

148 0 0

150 0 151

151 0 152

152 0 0

154 0 155

155 0 0

162 0 163

163 0 0

165 0 166

166 0 0

168 0 169

169 0 0

177 0 178

178 0 179

179 0 0

181 0 182

182 0 0

184 0 185

185 0 186

186 0 187

187 0 0

此处为普通目录格式(复制到txt文件即可):

第1章 绪论 1 1 1 0

1.1 数据结构的基本概念 1 1 2 1

1.1.1 数据、数据元素、数据元素的数据类型 1 2 3 2

1.1.2 数据的逻辑结构 2 3 4 2

1.1.3 数据的存储结构 3 3 5 2

1.1.4 数据的操作 3 4 6 2

1.1.5 本书的结构和主要内容 4 4 7 2

1.2 抽象数据类型 4 5 8 1

1.3 算法和算法的时间复杂度 5 5 9 1

1.3.1 算法 5 6 10 9

1.3.2 算法的性质和设计目标 6 7 11 9

1.3.3 算法的时间效率分析 7 10 12 9

1.3.4 算法耗时的实际测试 10 12 13 9

1.3.5 数据元素个数和时间复杂度 12 13 14 9

习题1 13 15 15 1

第2章 线性表 15 15 16 0

2.1 线性表概述 15 15 17 16

2.1.1 线性表的定义 15 15 18 16

2.1.2 线性表的抽象数据类型 15 16 19 16

2.2 线性表的顺序表示和实现 16 16 20 16

2.2.1 顺序表的存储结构 16 17 21 20

2.2.2 顺序表操作的实现 17 19 22 20

2.2.3 顺序表操作的效率分析 19 20 23 20

2.2.4 顺序表应用举例 20 22 24 20

2.3 线性表的链式表示和实现 22 22 25 16

2.3.1 单链表的存储结构 22 25 26 25

2.3.2 单链表的操作实现 25 29 27 25

2.3.3 单链表操作的效率分析 29 30 28 25

2.3.4 单链表应用举例 30 31 29 25

2.3.5 循环单链表 31 31 30 25

2.3.6 双向循环链表 31 34 31 25

2.4 静态链表 34 35 32 16

2.5 算法设计举例 35 35 33 16

2.5.1 顺序表算法设计举例 35 36 34 33

2.5.2 单链表算法设计举例 36 37 35 33

习题2 37 41 36 16

第3章 堆栈和队列 41 41 37 0

3.1 堆栈 41 41 38 37

3.1.1 堆栈的基本概念 41 42 39 38

3.1.2 堆栈的抽象数据类型 42 42 40 38

3.1.3 堆栈的顺序表示和实现 42 44 41 38

3.1.4 堆栈的链式表示和实现 44 47 42 38

3.2 堆栈应用 47 47 43 37

3.2.1 括号匹配问题 47 49 44 43

3.2.2 算术表达式计算问题 49 53 45 43

3.3 队列 53 53 46 37

3.3.1 队列的基本概念 53 54 47 46

3.3.2 队列的抽象数据类型 54 54 48 46

3.3.3 顺序队列及其存在的问题 54 55 49 46

3.3.4 顺序循环队列的表示和实现 55 58 50 46

3.3.5 链式队列 58 60 51 46

3.3.6 队列应用举例 60 64 52 46

3.4 优先级队列 64 64 53 37

3.4.1 顺序优先级队列的设计和实现 64 66 54 53

3.4.2 优先级队列应用举例 66 67 55 53

习题3 67 71 56 37

第4章 71 71 57 0

4.1 串概述 71 71 58 57

4.1.1 串及其基本概念 71 72 59 58

4.1.2 串的抽象数据类型 72 72 60 58

4.1.3 C语言的串函数 72 74 61 58

4.2 串的存储结构 74 76 62 57

4.3 串基本操作的实现算法 76 80 63 57

4.4 串的模式匹配算法 80 81 64 57

4.4.1 Brute-Force算法 81 83 65 64

4.4.2 KMP算法 83 88 66 64

4.4.3 Brute-Force算法和KMP算法的比较 88 90 67 64

习题4 90 92 68 57

第5章 数组 92 92 69 0

5.1 数组概述 92 92 70 69

5.1.1 数组的定义 92 92 71 70

5.1.2 数组的实现机制 92 93 72 70

5.1.3 数组的抽象数据类型 93 93 73 70

5.2 动态数组 93 93 74 69

5.2.1 动态数组的设计方法 93 96 75 74

5.2.2 动态数组和静态数组对比 96 97 76 74

5.3 特殊矩阵的压缩存储 97 99 77 69

5.4 稀疏矩阵的压缩存储 99 99 78 69

5.4.1 稀疏矩阵的三元组顺序表 99 100 79 77

5.4.2 稀疏矩阵的三元组链表 100 101 80 77

习题5 101 104 81 77

第6章 递归算法 104 104 82 0

6.1 递归的概念 104 105 83 82

6.2 递归算法的执行过程 105 107 84 82

6.3 递归算法的设计方法 107 109 85 82

6.4 递归过程和运行时栈 109 110 86 82

6.5 递归算法的时间效率分析 110 113 87 82

6.6 算法设计举例 113 113 88 82

6.6.1 一般递归算法设计举例 113 115 89 88

6.6.2 回溯算法及设计举例 115 118 90 88

习题6 118 120 91 82

第7章 广义表 120 120 92 0

7.1 广义表概述 120 120 93 92

7.1.1 广义表的概念 120 121 94 93

7.1.2 广义表的抽象数据类型 121 121 95 93

7.2 广义表的存储结构 121 122 96 92

7.2.1 头链和尾链存储结构 122 122 97 96

7.2.2 原子和子表存储结构 122 123 98 96

7.3 广义表操作的实现 123 123 99 92

7.3.1 头链和尾链存储结构下操作的实现 123 126 100 99

7.3.2 头链和尾链存储结构应用举例 126 128 101 99

7.3.3 原子和子表存储结构下操作的实现 128 130 102 99

7.3.4 原子和子表存储结构应用举例 130 130 103 99

习题7 130 132 104 92

第8章 树和二叉树 132 132 105 0

8.1 132 132 106 105

8.1.1 树的定义 132 133 107 106

8.1.2 树的表示方法 133 134 108 106

8.1.3 树的抽象数据类型 134 134 109 106

8.1.4 树的存储结构 134 137 110 106

8.2 二叉树 137 137 111 105

8.2.1 二叉树的定义 137 138 112 111

8.2.2 二叉树的抽象数据类型 138 138 113 111

8.2.3 二叉树的性质 138 140 114 111

8.3 二叉树的设计和实现 140 140 115 105

8.3.1 二叉树的存储结构 140 142 116 115

8.3.2 二叉树的操作实现 142 144 117 115

8.4 二叉树遍历 144 144 118 105

8.4.1 二叉树遍历的方法和结构 144 145 119 118

8.4.2 二叉链存储结构下二叉树遍历的实现 145 146 120 118

8.4.3 二叉树遍历应用举例 146 148 121 118

8.4.4 非递归的二叉树遍历算法 148 150 122 118

8.5 线索二叉树 150 150 123 105

8.5.1 线索二叉树及其用途 150 152 124 123

8.5.2 中序线索二叉树的设计 152 153 125 123

8.5.3 中序线索二叉树循环操作的设计 153 154 126 123

8.5.4 中序线索二叉树应用举例 154 155 127 123

8.6 哈夫曼树 155 155 128 105

8.6.1 哈夫曼树的基本概念 155 156 129 128

8.6.2 哈夫曼编码问题 156 157 130 128

8.6.3 哈夫曼编码问题设计和实现 157 161 131 128

8.7 等价问题 161 164 132 105

8.8 树与二叉树的转换 164 166 133 105

8.9 树的遍历 166 166 134 105

习题8 166 170 135 105

第9章 170 170 136 0

9.1 图概述 170 170 137 136

9.1.1 图的基本概念 170 172 138 137

9.1.2 图的抽象数据类型 172 173 139 137

9.2 图的存储结构 173 173 140 136

9.2.1 图的邻接矩阵存储结构 173 174 141 140

9.2.2 图的邻接表存储结构 174 175 142 140

9.3 图的实现 175 175 143 136

9.3.1 邻接矩阵存储结构下图操作的实现 175 178 144 143

9.3.2 邻接表存储结构下图操作的实现 178 181 145 143

9.4 图的遍历 181 181 146 136

9.4.1 图的深度和广度优先遍历算法 181 183 147 146

9.4.2 图的深度和广度优先遍历算法实现 183 185 148 146

9.5 最小生成树 185 185 149 136

9.5.1 最小生成树的基本概念 185 186 150 149

9.5.2 普里姆算法 186 190 151 149

9.5.3 克鲁斯卡尔算法 190 191 152 149

9.6 最短路径 191 191 153 136

9.6.1 最短路径的基本概念 191 195 154 153

9.6.2 每对顶点之间的最短路径 195 197 155 153

9.7 拓扑排序 197 200 156 136

9.8 关键路径 200 203 157 136

习题9 203 206 158 136

第10章 排序 206 206 159 0

10.1 排序的基本概念 206 207 160 159

10.2 插入排序 207 208 161 159

10.2.1 直接插入排序 208 209 162 161

10.2.2 希尔排序 209 211 163 161

10.3 选择排序 211 211 164 159

10.3.1 直接选择排序 211 212 165 164

10.3.2 堆排序 212 216 166 164

10.4 交换排序 216 216 167 159

10.4.1 冒泡排序 216 217 168 167

10.4.2 快速排序 217 220 169 167

10.5 归并排序 220 222 170 159

10.6 基数排序 222 225 171 159

10.7 排序算法性能比较 225 225 172 159

习题10 225 229 173 159

第11章 查找 229 229 174 0

11.1 查找的基本概念 229 230 175 174

11.2 静态查找 230 230 176 174

11.2.1 顺序表 230 231 177 176

11.2.2 有序顺序表 231 232 178 176

11.2.3 索引顺序表 232 235 179 176

11.3 动态查找 235 235 180 174

11.3.1 二叉排序树和平衡二叉树 235 241 181 180

11.3.2 B-树和B+树 241 246 182 180

11.4 哈希查找 246 246 183 174

11.4.1 哈希表的基本概念 246 248 184 183

11.4.2 哈希函数构造方法 248 249 185 183

11.4.3 哈希冲突解决方法 249 251 186 183

11.4.4 哈希表设计 251 254 187 183

习题11 254 258 188 174

参考文献 258 258 189 NULL

优化目录:*1 绪论 1 1 1 0

1.1 数据结构的基本概念 1 1 2 1

1.1.1 数据、数据元素、数据元素的数据类型 1 2 3 2

1.1.2 数据的逻辑结构 2 3 4 2

1.1.3 数据的存储结构 3 3 5 2

1.1.4 数据的操作 3 4 6 2

1.1.5 本书的结构和主要内容 4 4 7 2

1.2 抽象数据类型 4 5 8 1

1.3 算法和算法的时间复杂度 5 5 9 1

1.3.1 算法 5 6 10 9

1.3.2 算法的性质和设计目标 6 7 11 9

1.3.3 算法的时间效率分析 7 10 12 9

1.3.4 算法耗时的实际测试 10 12 13 9

1.3.5 数据元素个数和时间复杂度 12 13 14 9

*2 线性表 15 15 16 0

2.1 线性表概述 15 15 17 16

2.1.1 线性表的定义 15 15 18 16

2.1.2 线性表的抽象数据类型 15 16 19 16

2.2 线性表的顺序表示和实现 16 16 20 16

2.2.1 顺序表的存储结构 16 17 21 20

2.2.2 顺序表操作的实现 17 19 22 20

2.2.3 顺序表操作的效率分析 19 20 23 20

2.2.4 顺序表应用举例 20 22 24 20

2.3 线性表的链式表示和实现 22 22 25 16

2.3.1 单链表的存储结构 22 25 26 25

2.3.2 单链表的操作实现 25 29 27 25

2.3.3 单链表操作的效率分析 29 30 28 25

2.3.4 单链表应用举例 30 31 29 25

2.3.5 循环单链表 31 31 30 25

2.3.6 双向循环链表 31 34 31 25

2.4 静态链表 34 35 32 16

2.5 算法设计举例 35 35 33 16

2.5.1 顺序表算法设计举例 35 36 34 33

2.5.2 单链表算法设计举例 36 37 35 33

*3 堆栈和队列 41 41 37 0

3.1 堆栈 41 41 38 37

3.1.1 堆栈的基本概念 41 42 39 38

3.1.2 堆栈的抽象数据类型 42 42 40 38

3.1.3 堆栈的顺序表示和实现 42 44 41 38

3.1.4 堆栈的链式表示和实现 44 47 42 38

3.2 堆栈应用 47 47 43 37

3.2.1 括号匹配问题 47 49 44 43

3.2.2 算术表达式计算问题 49 53 45 43

3.3 队列 53 53 46 37

3.3.1 队列的基本概念 53 54 47 46

3.3.2 队列的抽象数据类型 54 54 48 46

3.3.3 顺序队列及其存在的问题 54 55 49 46

3.3.4 顺序循环队列的表示和实现 55 58 50 46

3.3.5 链式队列 58 60 51 46

3.3.6 队列应用举例 60 64 52 46

3.4 优先级队列 64 64 53 37

3.4.1 顺序优先级队列的设计和实现 64 66 54 53

3.4.2 优先级队列应用举例 66 67 55 53

*4 71 71 57 0

4.1 串概述 71 71 58 57

4.1.1 串及其基本概念 71 72 59 58

4.1.2 串的抽象数据类型 72 72 60 58

4.1.3 C语言的串函数 72 74 61 58

4.2 串的存储结构 74 76 62 57

4.3 串基本操作的实现算法 76 80 63 57

4.4 串的模式匹配算法 80 81 64 57

4.4.1 Brute-Force算法 81 83 65 64

4.4.2 KMP算法 83 88 66 64

4.4.3 Brute-Force算法和KMP算法的比较 88 90 67 64

*5 数组 92 92 69 0

5.1 数组概述 92 92 70 69

5.1.1 数组的定义 92 92 71 70

5.1.2 数组的实现机制 92 93 72 70

5.1.3 数组的抽象数据类型 93 93 73 70

5.2 动态数组 93 93 74 69

5.2.1 动态数组的设计方法 93 96 75 74

5.2.2 动态数组和静态数组对比 96 97 76 74

5.3 特殊矩阵的压缩存储 97 99 77 69

5.4 稀疏矩阵的压缩存储 99 99 78 69

5.4.1 稀疏矩阵的三元组顺序表 99 100 79 77

5.4.2 稀疏矩阵的三元组链表 100 101 80 77

*6 递归算法 104 104 82 0

6.1 递归的概念 104 105 83 82

6.2 递归算法的执行过程 105 107 84 82

6.3 递归算法的设计方法 107 109 85 82

6.4 递归过程和运行时栈 109 110 86 82

6.5 递归算法的时间效率分析 110 113 87 82

6.6 算法设计举例 113 113 88 82

6.6.1 一般递归算法设计举例 113 115 89 88

6.6.2 回溯算法及设计举例 115 118 90 88

*7 广义表 120 120 92 0

7.1 广义表概述 120 120 93 92

7.1.1 广义表的概念 120 121 94 93

7.1.2 广义表的抽象数据类型 121 121 95 93

7.2 广义表的存储结构 121 122 96 92

7.2.1 头链和尾链存储结构 122 122 97 96

7.2.2 原子和子表存储结构 122 123 98 96

7.3 广义表操作的实现 123 123 99 92

7.3.1 头链和尾链存储结构下操作的实现 123 126 100 99

7.3.2 头链和尾链存储结构应用举例 126 128 101 99

7.3.3 原子和子表存储结构下操作的实现 128 130 102 99

7.3.4 原子和子表存储结构应用举例 130 130 103 99

*8 树和二叉树 132 132 105 0

8.1 132 132 106 105

8.1.1 树的定义 132 133 107 106

8.1.2 树的表示方法 133 134 108 106

8.1.3 树的抽象数据类型 134 134 109 106

8.1.4 树的存储结构 134 137 110 106

8.2 二叉树 137 137 111 105

8.2.1 二叉树的定义 137 138 112 111

8.2.2 二叉树的抽象数据类型 138 138 113 111

8.2.3 二叉树的性质 138 140 114 111

8.3 二叉树的设计和实现 140 140 115 105

8.3.1 二叉树的存储结构 140 142 116 115

8.3.2 二叉树的操作实现 142 144 117 115

8.4 二叉树遍历 144 144 118 105

8.4.1 二叉树遍历的方法和结构 144 145 119 118

8.4.2 二叉链存储结构下二叉树遍历的实现 145 146 120 118

8.4.3 二叉树遍历应用举例 146 148 121 118

8.4.4 非递归的二叉树遍历算法 148 150 122 118

8.5 线索二叉树 150 150 123 105

8.5.1 线索二叉树及其用途 150 152 124 123

8.5.2 中序线索二叉树的设计 152 153 125 123

8.5.3 中序线索二叉树循环操作的设计 153 154 126 123

8.5.4 中序线索二叉树应用举例 154 155 127 123

8.6 哈夫曼树 155 155 128 105

8.6.1 哈夫曼树的基本概念 155 156 129 128

8.6.2 哈夫曼编码问题 156 157 130 128

8.6.3 哈夫曼编码问题设计和实现 157 161 131 128

8.7 等价问题 161 164 132 105

8.8 树与二叉树的转换 164 166 133 105

8.9 树的遍历 166 166 134 105

*9 170 170 136 0

9.1 图概述 170 170 137 136

9.1.1 图的基本概念 170 172 138 137

9.1.2 图的抽象数据类型 172 173 139 137

9.2 图的存储结构 173 173 140 136

9.2.1 图的邻接矩阵存储结构 173 174 141 140

9.2.2 图的邻接表存储结构 174 175 142 140

9.3 图的实现 175 175 143 136

9.3.1 邻接矩阵存储结构下图操作的实现 175 178 144 143

9.3.2 邻接表存储结构下图操作的实现 178 181 145 143

9.4 图的遍历 181 181 146 136

9.4.1 图的深度和广度优先遍历算法 181 183 147 146

9.4.2 图的深度和广度优先遍历算法实现 183 185 148 146

9.5 最小生成树 185 185 149 136

9.5.1 最小生成树的基本概念 185 186 150 149

9.5.2 普里姆算法 186 190 151 149

9.5.3 克鲁斯卡尔算法 190 191 152 149

9.6 最短路径 191 191 153 136

9.6.1 最短路径的基本概念 191 195 154 153

9.6.2 每对顶点之间的最短路径 195 197 155 153

9.7 拓扑排序 197 200 156 136

9.8 关键路径 200 203 157 136

*10 排序 206 206 159 0

10.1 排序的基本概念 206 207 160 159

10.2 插入排序 207 208 161 159

10.2.1 直接插入排序 208 209 162 161

10.2.2 希尔排序 209 211 163 161

10.3 选择排序 211 211 164 159

10.3.1 直接选择排序 211 212 165 164

10.3.2 堆排序 212 216 166 164

10.4 交换排序 216 216 167 159

10.4.1 冒泡排序 216 217 168 167

10.4.2 快速排序 217 220 169 167

10.5 归并排序 220 222 170 159

10.6 基数排序 222 225 171 159

10.7 排序算法性能比较 225 225 172 159

*11 查找 229 229 174 0

11.1 查找的基本概念 229 230 175 174

11.2 静态查找 230 230 176 174

11.2.1 顺序表 230 231 177 176

11.2.2 有序顺序表 231 232 178 176

11.2.3 索引顺序表 232 235 179 176

11.3 动态查找 235 235 180 174

11.3.1 二叉排序树和平衡二叉树 235 241 181 180

11.3.2 B-树和B+树 241 246 182 180

11.4 哈希查找 246 246 183 174

11.4.1 哈希表的基本概念 246 248 184 183

11.4.2 哈希函数构造方法 248 249 185 183

11.4.3 哈希冲突解决方法 249 251 186 183

11.4.4 哈希表设计 251 254 187 183

bibiliography 参考文献 258 258 189 0

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值