c语言树中的父结构重构的编码,数据结构的实践心得(基于典型树结构的C语言XML操作封装,以及相应的树型结构重构:myxml、tre...

数据结构的实践心得(基于典型树结构的C语言XML操作封装,以及相应的树型结构重构:myxml、treeList)

COMZHJ 咕咚的小宇宙

42c98c4c688f5b2c5170aa4b3cb953fc.png

XML操作封装头文件(myxml.h):

#pragma once

#include "treeList.h"

#define XMLNodeAttributeBLOCK 10

#define XMLNumberSIZE 20

#define XMLValueERROR -99999999

#define XMLFileBufferBLOCK 4096

typedef struct

{

double version;

char *encoding;

}XMLDocument;

// 初始化XML根节点

treeNode* initXMLRoot(char *rootName);

// 取得匹配xmlPath路径的第一个节点

treeNode* selectSingleXMLNode(treeNode *xmlNode, char *xmlPath);

// 取得节点名称

char* getXMLNodeName(treeNode *xmlNode);

// 取得节点文本

char* getXMLNodeText(treeNode *xmlNode);

// 设置节点文本

int setXMLNodeText(treeNode *xmlNode, char *nodeText);

// 取得子节点

treeNode* getXMLChildNode(treeNode *xmlNode, char *childName);

// 取得节点属性值(字符串)

char* getXMLAttValue(treeNode *xmlNode, char *attName);

// 取得节点属性值(整型)

int getXMLAttValueInt(treeNode *xmlNode, char *attName);

// 取得节点属性值(浮点型)

double getXMLAttValueDouble(treeNode *xmlNode, char *attName);

// 设置节点属性值(字符串)

int setXMLAttValue(treeNode *xmlNode, char *attName, char *attValue);

// 设置节点属性值(整型)

int setXMLAttValueInt(treeNode *xmlNode, char *attName, int attValue);

// 设置节点属性值(浮点型)

int setXMLAttValueDouble(treeNode *xmlNode, char *attName, double attValue);

// 插入XML子节点

treeNode* insertXMLChildNode(treeNode *xmlNode, char *childName, char *childText);

// 移动XML子节点

treeNode* moveXMLChildNode(treeNode *xmlNode, treeNode *childNode);

// 设置节点属性数量

int setXMLNodeAttCount(treeNode *xmlNode, int attCount);

// 删除XML节点(递归)

int deleteXMLNode(treeNode *xmlNode);

// 保存XML文件

void saveXMLFile(char *filePath, treeNode *tnIn, char *encoding);

// 加载XML文件

treeNode* loadXMLFile(char *filePath);

XML操作封装程序文件(myxml.c):

#include

#include

#include "mystring.h"

#include "myxml.h"

// 初始化XML根节点

treeNode* initXMLRoot(char *rootName)

{

// 取得根节点名称长度

int len = mystrlen(rootName);

if (len <= 0) return NULL;

// 准备复制名称的内存空间

char *name = (char *)malloc(sizeof(char) * (len + 1));

if (!name) return NULL;

// 创建根节点

treeNode *tn = createTreeNode();

if (tn)

{

// 复制根节点名称

mystrcpy(rootName, name);

// 设置树节点的值

setTreeNodeValue(tn, name, 0);

}

else

{

// 如果创建树节点失败,则释放名称的内存空间

free(name);

}

return tn;

}

// 取得匹配xmlPath路径的第一个节点

treeNode* selectSingleXMLNode(treeNode *xmlNode, char *xmlPath)

{

if (!xmlNode) return NULL;

// 取得文本长度

int len = mystrlen(xmlPath);

if (len <= 0) return NULL;

char *splitList = (char *)malloc(sizeof(char) * (len + 1));

if (!splitList) return NULL;

// 分割xmlPath路径

seqList split = mySplit(xmlPath, '/', splitList);

char *name = split.elem[0];

// 逐个比较xmlPath路径

if (!myEqual(xmlNode->key, name)) return NULL;

treeNode *tn = xmlNode;

int i;

// 循环解析内容

for (i = 1; i < split.len; i++)

{

// 取得每个解析内容

name = split.elem[i];

// 逐个比较xmlPath路径

tn = getXMLChildNode(tn, name);

if (!tn) break;

}

// 释放分割字符串列表

clearSeqList(&split);

return tn;

}

// 取得节点名称

char* getXMLNodeName(treeNode *xmlNode)

{

if (!xmlNode) return NULL;

return (char *)xmlNode->key;

}

// 取得节点文本

char* getXMLNodeText(treeNode *xmlNode)

{

if (!xmlNode) return NULL;

return (char *)(int)xmlNode->value;

}

// 设置节点文本

int setXMLNodeText(treeNode *xmlNode, char *nodeText)

{

if (!xmlNode) return -1;

// 取得文本长度

int len = mystrlen(nodeText);

if (len <= 0) return -1;

// 准备复制文本的内存空间

char *text = (char *)malloc(sizeof(char) * (len + 1));

if (!text) return -1;

// 复制文本

mystrcpy(nodeText, text);

// 设置树节点的值

setTreeNodeValue(xmlNode, xmlNode->key, (int)text);

return 1;

}

// 取得子节点

treeNode* getXMLChildNode(treeNode *xmlNode, char *childName)

{

if ((!xmlNode) || (!childName)) return NULL;

treeNode *tn;

int i;

for (i = 0; i < xmlNode->childCount; i++)

{

tn = xmlNode->childList[i];

// 进行名称(key)的深度比较

if (myEqual(tn->key, childName)) return tn;

}

return NULL;

}

// 取得节点属性值(字符串)

char* getXMLAttValue(treeNode *xmlNode, char *attName)

{

if ((!xmlNode) || (!attName)) return NULL;

int i;

for (i = 0; i < xmlNode->dataSize; i++)

{

// 进行属性名称(dataKey)的深度比较

if (myEqual(xmlNode->dataKey[i], attName)) return (char *)(int)xmlNode->data[i];

}

return NULL;

}

// 取得节点属性值(整型)

int getXMLAttValueInt(treeNode *xmlNode, char *attName)

{

char *value = getXMLAttValue(xmlNode, attName);

if (!value) return XMLValueERROR;

return myatoi(value);

}

// 取得节点属性值(浮点型)

double getXMLAttValueDouble(treeNode *xmlNode, char *attName)

{

char *value = getXMLAttValue(xmlNode, attName);

if (!value) return XMLValueERROR;

return myatof(value);

}

// 设置节点属性值(字符串)

int setXMLAttValue(treeNode *xmlNode, char *attName, char *attValue)

{

if ((!xmlNode) || (!attName)) return -1;

// 初始化空字符串

if (!attValue) attValue = "";

// 取得属性值长度(允许为空字符串)

int len = mystrlen(attValue);

if (len < 0) return -1;

// 准备复制属性值的内存空间

char *value = (char *)malloc(sizeof(char) * (len + 1));

if (!value) return -1;

int i;

for (i = 0; i < xmlNode->dataLen; i++)

{

// 进行属性名称(dataKey)的深度比较

if (myEqual(xmlNode->dataKey[i], attName))

{

char *tmp = (int)xmlNode->data[i];

// 释放原有的属性值空间

if (tmp) free(tmp);

// 复制属性值

mystrcpy(attValue, value);

// 设置树节点的属性值

xmlNode->data[i] = (int)value;

return 1;

}

}

// 节点属性的数量,是否小于允许存储的空间

if (xmlNode->dataLen < xmlNode->dataSize)

{

// 取得属性名称长度

len = mystrlen(attName);

if (len > 0)

{

// 准备复制属性名称的内存空间

char *name = (char *)malloc(sizeof(char) * (len + 1));

if (name)

{

// 复制属性名称

mystrcpy(attName, name);

// 设置树节点的属性名称

xmlNode->dataKey[xmlNode->dataLen] = name;

// 复制属性值

mystrcpy(attValue, value);

// 设置树节点的属性值

xmlNode->data[xmlNode->dataLen] = (int)value;

// 数据内容的长度自增

xmlNode->dataLen++;

return 1;

}

}

}

// 如果上述操作失败,则释放属性值的内存空间

free(value);

return -1;

}

// 设置节点属性值(整型)

int setXMLAttValueInt(treeNode *xmlNode, char *attName, int attValue)

{

if ((!xmlNode) || (!attName)) return -1;

// 缓存属性值的内存空间

char *tmp = (char *)malloc(sizeof(char) * XMLNumberSIZE);

if (!tmp) return -1;

// 整型转换为字符串

myitoa(attValue, tmp);

// 设置节点属性值(字符串)

int result = setXMLAttValue(xmlNode, attName, tmp);

// 释放缓存空间

free(tmp);

return result;

}

// 设置节点属性值(浮点型)

int setXMLAttValueDouble(treeNode *xmlNode, char *attName, double attValue)

{

if ((!xmlNode) || (!attName)) return -1;

// 缓存属性值的内存空间

char *tmp = (char *)malloc(sizeof(char) * XMLNumberSIZE);

if (!tmp) return -1;

// 浮点型转换为字符串

myftoa(attValue, tmp);

// 设置节点属性值(字符串)

int result = setXMLAttValue(xmlNode, attName, tmp);

// 释放缓存空间

free(tmp);

return result;

}

// 插入XML子节点

treeNode* insertXMLChildNode(treeNode *xmlNode, char *childName, char *childText)

{

if ((!xmlNode) || (!childName)) return NULL;

// 初始化空字符串

if (!childText) childText = "";

// 取得子节点文本长度(允许为空字符串)

int len = mystrlen(childText);

if (len < 0) return NULL;

// 准备复制子节点文本的内存空间

char *text = (char *)malloc(sizeof(char) * (len + 1));

if (!text) return NULL;

// 取得子节点名称长度

len = mystrlen(childName);

if (len > 0)

{

// 准备复制子节点名称的内存空间

char *name = (char *)malloc(sizeof(char) * (len + 1));

if (name)

{

// 复制子节点名称

mystrcpy(childName, name);

// 复制子节点文本

mystrcpy(childText, text);

// 插入子节点

treeNode* child = insertChildNode(xmlNode, name, (int)text);

if (child)

{

// 设置树节点的数据内容空间大小(属性值数量)

setTreeNodeDataSize(child, XMLNodeAttributeBLOCK);

return child;

}

}

}

// 如果上述操作失败,则释放子节点文本的内存空间

free(text);

return NULL;

}

// 移动XML子节点

treeNode* moveXMLChildNode(treeNode *xmlNode, treeNode *childNode)

{

if ((!xmlNode) || (!childNode)) return NULL;

// 添加子节点

return addChildNode(xmlNode, childNode);

}

// 设置节点属性数量

int setXMLNodeAttCount(treeNode *xmlNode, int attCount)

{

if (!xmlNode) return -1;

// 判断传入的节点属性数量是否符合要求

if (attCount < XMLNodeAttributeBLOCK) return -1;

// 设置树节点的数据内容空间大小

return setTreeNodeDataSize(xmlNode, attCount);

}

// 删除XML节点(递归)

int deleteXMLNode(treeNode *xmlNode)

{

if (!xmlNode) return -1;

// 移除原有的父级关系

removeChildNode(xmlNode->parent, xmlNode);

// 清空子节点

clearTreeList(xmlNode);

return 1;

}

// 节点的属性信息

char* writeXMLNodeAttInfo(char *buffer, treeNode *tnIn)

{

if ((!buffer) || (!tnIn)) return buffer;

int i;

// 遍历属性信息

for (i = 0; i < tnIn->dataLen; i++)

{

// 拼接属性名称和属性值

mystrcat(buffer, " ");

mystrcat(buffer, tnIn->dataKey[i]);

mystrcat(buffer, "=\"");

mystrcat(buffer, (int)tnIn->data[i]);

mystrcat(buffer, "\"");

}

return buffer;

}

// 写入节点信息

void writeXMLNodeInfo(char *buffer, treeNode *tnIn, FILE *fpIn, treeNode *root)

{

if ((!buffer) || (!tnIn) || (!fpIn)) return;

// 初始化缓存内容

mymemset(buffer, 0, XMLFileBufferBLOCK);

// 取得子节点的相对层级

int i, level = levelChildNode(root, tnIn);

// 补充制表缩进符号

for (i = 0; i < level; i++)

{

buffer[i] = '\t';

}

buffer[i] = '

// 节点名称

mystrcat(buffer, tnIn->key);

// 节点的属性信息

writeXMLNodeAttInfo(buffer, tnIn);

mystrcat(buffer, ">\r\n");

// 取得待写入的缓存长度

int len = mystrlen(buffer);

// 写入XML文件

fwrite(buffer, 1, len, fpIn);

// 是否包含节点值

len = mystrlen((int)tnIn->value);

if (len > 0)

{

// 初始化缓存内容

mymemset(buffer, 0, XMLFileBufferBLOCK);

int valueLevel = level + 1;

// 补充制表缩进符号

for (i = 0; i < valueLevel; i++)

{

buffer[i] = '\t';

}

// 节点值

mystrcat(buffer, (int)tnIn->value);

mystrcat(buffer, "\r\n");

// 写入XML文件

fwrite(buffer, 1, (i + len + 2), fpIn);

}

// 遍历子节点

for (i = 0; i < tnIn->childCount; i++)

{

// 递归写入子节点信息

writeXMLNodeInfo(buffer, tnIn->childList[i], fpIn, root);

}

// 初始化缓存内容

mymemset(buffer, 0, XMLFileBufferBLOCK);

// 补充制表缩进符号

for (i = 0; i < level; i++)

{

buffer[i] = '\t';

}

// 拼接节点的结束信息

buffer[i] = '

// 节点名称

mystrcat(buffer, tnIn->key);

mystrcat(buffer, ">\r\n");

// 取得待写入的缓存长度

len = mystrlen(buffer);

// 写入XML文件

fwrite(buffer, 1, len, fpIn);

}

// 保存XML文件

void saveXMLFile(char *filePath, treeNode *tnIn, char *encoding)

{

if (!tnIn) return;

// 打开待保存的文件(r是只读,w是写入,b打开二进制文件)

FILE *fp = fopen(filePath, "wb");

if (!fp) return;

// 定义一个写入缓存

char buffer[XMLFileBufferBLOCK] = "<?xml version=\"1.0\" encoding=\"";

// 连接字符编码设置(如果使用“UTF-8”,则必须保证XML文件内的中文符合“UTF-8”编码要求)

int len = mystrlen(encoding);

if (len <= 0) encoding = "GB2312";

mystrcat(buffer, encoding);

// 补充文件标识的后续字符

mystrcat(buffer, "\"?>\r\n");

// 取得待写入的缓存长度

len = mystrlen(buffer);

// 写入XML文件的头部标识

fwrite(buffer, 1, len, fp);

// 写入节点信息

writeXMLNodeInfo(buffer, tnIn, fp, tnIn);

// 关闭文件

fclose(fp);

}

// 读取节点信息

treeNode* readXMLNodeInfo(treeNode *parent, char *read, FILE *fpIn, char *splitStr)

{

if ((!read) || (!fpIn)) return NULL;

// 读取节点的结束信息

if (indexOfStr(read, "") >= 0)

{

if (!parent) return NULL;

// 返回当前节点的父级,表示当前节点完成读取

return parent->parent;

}

treeNode *tn = NULL;

// 使用空格分割解析内容

seqList split = mySplit(read, ' ', splitStr);

char *tmp, *name, *value;

int i, tmpIndex, len;

// 循环解析内容

for (i = 0; i < split.len; i++)

{

// 取得每个解析内容

tmp = split.elem[i];

// 是否已解析节点

if (tn)

{

tmpIndex = indexOfStr(tmp, "=\"");

// 解析属性

if (tmpIndex > 0)

{

tmp[tmpIndex] = 0;

// 属性名称

name = tmp;

// 属性值

value = tmp + tmpIndex + 2;

myReplaceLast(value, '"', 0);

// 设置节点属性值(字符串)

setXMLAttValue(tn, name, value);

}

}

else

{

tmpIndex = indexOf(tmp, '

// 解析节点文本

if (tmpIndex < 0)

{

// 设置当前节点文本

if (parent)

{

len = mystrlen(tmp);

// 文本长度是否有效

if (len > 0)

{

// 解析制表符

tmpIndex = indexOfLast(tmp, '\t');

// 节点文本

value = tmp + tmpIndex + 1;

myReplaceLast(value, '\n', 0);

myReplaceLast(value, '\r', 0);

// 设置节点文本

setXMLNodeText(parent, value);

}

}

}

else

{

// 节点名称

name = tmp + tmpIndex + 1;

myReplaceLast(name, '>', 0);

if (parent)

{

// 插入XML子节点

tn = insertXMLChildNode(parent, name, "");

}

else

{

// 初始化XML根节点

tn = initXMLRoot(name);

}

}

}

}

// 释放分割字符串列表

clearSeqList(&split);

// 如果无法解析有效内容,则继续返回父级节点

if (!tn) return parent;

return tn;

}

// 加载XML文件

treeNode* loadXMLFile(char *filePath)

{

// 打开待保存的文件(r是只读,w是写入,b打开二进制文件)

FILE *fp = fopen(filePath, "rb");

if (!fp) return NULL;

// 定义一个读取缓存

char buffer[XMLFileBufferBLOCK] = { 0 };

// 定义一个分割缓存

char splitStr[XMLFileBufferBLOCK] = { 0 };

// 读取文件第一行内容

char *read = fgets(buffer, XMLFileBufferBLOCK, fp);

// 是否包含文件标识

if (indexOfStr(read, "?xml") > 0)

{

// 继续读取文件第二行内容

read = fgets(buffer, XMLFileBufferBLOCK, fp);

}

// 根节点

treeNode *root = NULL, *parent;

// 继续读取文件每一行内容

while (read)

{

if (root)

{

// 读取节点信息

parent = readXMLNodeInfo(parent, read, fp, splitStr);

// 已读取根节点的结束信息,完成解析

if (!parent) break;

}

else

{

// 读取根节点

root = readXMLNodeInfo(NULL, read, fp, splitStr);

// 初始化父级节点

if (root) parent = root;

}

// 继续读取

read = fgets(buffer, XMLFileBufferBLOCK, fp);

}

// 关闭文件

fclose(fp);

return root;

}

典型树型重构头文件(treeList.h):

#pragma once

#define ChildListMemoryBLOCK 10

typedef double treeElemType;

typedef struct

{

int key; // 树节点关键字

treeElemType value; // 树节点值

int *dataKey; // 数据关键字

treeElemType *data; // 数据内容

int dataLen; // 数据内容的数量

int dataSize; // 数据内容的空间大小

struct treeNode *parent; // 父节点

struct treeNode **childList; // 子节点列表

int childCount; // 子节点数量

}treeNode;

// 创建树节点

treeNode* createTreeNode();

// 设置树节点的数据内容空间大小

int setTreeNodeDataSize(treeNode *T, int dataSize);

// 设置树节点的值

void setTreeNodeValue(treeNode *T, int key, treeElemType value);

// 设置树节点的数据内容

void setTreeNodeData(treeNode *T, int *dataKey, treeElemType *data, int dataLen);

// 是否为叶子节点返回1,否则返回0

int isLeafTreeNode(treeNode *T);

// 树节点的长度(递归)

int lengthTreeList(treeNode *T);

// 取得树节点的层级

int levelTreeNode(treeNode *T);

// 取得子节点的相对层级

int levelChildNode(treeNode *T, treeNode *child);

// 是否为子节点返回1,否则返回0(递归)

int isChildNode(treeNode *T, treeNode *child);

// 取得树节点的根节点

treeNode* getRoot(treeNode *T);

// 通过关键字,取得树节点(递归)

treeNode* getNodeByKey(treeNode *T, int key);

// 通过索引,取得子节点

treeNode* getChildNode(treeNode *T, int index);

// 插入子节点

treeNode* insertChildNode(treeNode *T, int key, treeElemType value);

// 添加子节点

treeNode* addChildNode(treeNode *T, treeNode *child);

// 移除子节点

int removeChildNode(treeNode *T, treeNode *child);

// 删除子节点

int deleteChildNode(treeNode *T, int index);

// 通过关键字,删除子节点(递归)

int deleteNodeByKey(treeNode *T, int key);

// 清空树列表(递归)

void clearTreeList(treeNode *T);

典型树型重构程序文件(treeList.c):

#include

#include "mystring.h"

#include "treeList.h"

// 创建树节点

treeNode* createTreeNode()

{

treeNode *tn = (treeNode *)malloc(sizeof(treeNode));

if (!tn) return NULL;

tn->key = 0;

tn->value = 0;

tn->parent = NULL;

tn->childList = NULL;

tn->childCount = 0;

tn->dataKey = NULL;

tn->data = NULL;

tn->dataLen = 0;

tn->dataSize = 0;

return tn;

}

// 设置树节点的数据内容空间大小

int setTreeNodeDataSize(treeNode *T, int dataSize)

{

// 判断树节点是否有效

if (!T) return -1;

// 判断传入的数据内容空间大小是否有效

if (dataSize < 1) return -1;

// 是否需要补充内存空间

if (T->dataSize < dataSize)

{

if (T->dataSize > 0)

{

// 补充申请树节点的数据内存空间

T->dataKey = (int *)realloc(T->dataKey, sizeof(int) * dataSize);

T->data = (treeElemType *)realloc(T->data, sizeof(treeElemType) * dataSize);

}

else

{

// 初始化树节点的数据内存空间

T->dataKey = (int *)malloc(sizeof(int) * dataSize);

T->data = (treeElemType *)malloc(sizeof(treeElemType) * dataSize);

}

// 内存空间申请失败,则退出

if ((!T->dataKey) || (!T->data)) return -1;

// 更新数据内容空间大小

T->dataSize = dataSize;

}

return 1;

}

// 设置树节点的值

void setTreeNodeValue(treeNode *T, int key, treeElemType value)

{

// 判断树节点是否有效

if (!T) return;

T->key = key;

T->value = value;

}

// 设置树节点的数据内容

void setTreeNodeData(treeNode *T, int *dataKey, treeElemType *data, int dataLen)

{

// 判断树节点是否有效

if (!T) return;

int len = T->dataSize;

// 可设置的数据内容长度,以dataSize和dataLen相对较小的数量为准

if (dataLen < T->dataSize) len = dataLen;

if (len <= 0) return;

// 是否包含数据内容

int i;

// 数据关键字

if ((T->dataKey) && (dataKey))

{

// 设置数据关键字

for (i = 0; i < len; i++)

{

T->dataKey[i] = dataKey[i];

}

}

// 数据内容

if ((T->data) && (data))

{

// 设置数据内容

for (i = 0; i < len; i++)

{

T->data[i] = data[i];

}

}

// 数据内容长度

T->dataLen = len;

}

// 是否为叶子节点返回1,否则返回0

int isLeafTreeNode(treeNode *T)

{

if (!T) return -1;

return (T->childCount <= 0);

}

// 树节点的长度(递归)

int lengthTreeList(treeNode *T)

{

if (!T) return 0;

// 记录树节点自己的数量

int count = 1;

int i;

// 递归循环子节点

for (i = 0; i < T->childCount; i++)

{

// 递归调用

count += lengthTreeList(T->childList[i]);

}

return count;

}

// 取得树节点的层级

int levelTreeNode(treeNode *T)

{

if (!T) return -1;

// 从 0 开始

int level = 0;

treeNode *tn = T;

// 递归父节点

while (tn->parent)

{

tn = tn->parent;

level++;

}

return level;

}

// 取得子节点的相对层级

int levelChildNode(treeNode *T, treeNode *child)

{

if ((!T) || (!child)) return -1;

// 判断T是否就是child

if (T == child) return 0;

treeNode *tn = child->parent;

// 从 1 继续

int level = 1;

// 递归父节点

while (tn)

{

if (T == tn) return level;

tn = tn->parent;

level++;

}

return -1;

}

// 是否为子节点返回1,否则返回0(递归)

int isChildNode(treeNode *T, treeNode *child)

{

if ((!T) || (!child)) return -1;

// 判断T是否就是child

if (T == child) return 1;

int i, result;

// 递归循环子节点

for (i = 0; i < T->childCount; i++)

{

// 递归调用

result = isChildNode(T->childList[i], child);

if (result) return result;

}

return 0;

}

// 取得树节点的根节点

treeNode* getRoot(treeNode *T)

{

if (!T) return NULL;

treeNode *tn = T;

// 递归父节点

while (tn->parent)

{

tn = tn->parent;

}

return tn;

}

// 通过关键字,取得树节点(递归)

treeNode* getNodeByKey(treeNode *T, int key)

{

if (!T) return NULL;

// 判断Key值是否匹配

if (T->key == key) return T;

treeNode *tn;

int i;

// 递归循环子节点

for (i = 0; i < T->childCount; i++)

{

// 递归调用

tn = getNodeByKey(T->childList[i], key);

if (tn) return tn;

}

return NULL;

}

// 通过索引,取得子节点

treeNode* getChildNode(treeNode *T, int index)

{

if (!T) return NULL;

// 判断索引是否有效

if ((index < 0) || (index >= T->childCount)) return NULL;

return T->childList[index];

}

// 插入子节点

treeNode* insertChildNode(treeNode *T, int key, treeElemType value)

{

if (!T) return NULL;

if (T->childCount > 0)

{

// 计算内存块是否需要增加

int blockCount = T->childCount % ChildListMemoryBLOCK;

// 如果余数为零,则需要补充内存空间

if (!blockCount)

{

blockCount = (T->childCount / ChildListMemoryBLOCK);

// 补充申请子节点列表的内存空间

T->childList = (treeNode **)realloc(T->childList,

sizeof(treeNode *) * ChildListMemoryBLOCK * (blockCount + 1));

}

}

else

{

// 申请子节点列表的内存空间

T->childList = (treeNode **)malloc(sizeof(treeNode *) * ChildListMemoryBLOCK);

}

// 创建树节点

treeNode *child = createTreeNode();

// 设置子节点的数据值

setTreeNodeValue(child, key, value);

child->parent = T;

// 在子节点列表中添加新增的子节点

T->childList[T->childCount] = child;

// 子节点数量自增

T->childCount++;

return child;

}

// 添加子节点

treeNode* addChildNode(treeNode *T, treeNode *child)

{

if ((!T) || (!child)) return NULL;

// 避免嵌套死循环

if (isChildNode(child, T) > 0) return NULL;

if (T->childCount > 0)

{

// 计算内存块是否需要增加

int blockCount = T->childCount % ChildListMemoryBLOCK;

// 如果余数为零,则需要补充内存空间

if (!blockCount)

{

blockCount = (T->childCount / ChildListMemoryBLOCK);

// 补充申请子节点列表的内存空间

T->childList = (treeNode **)realloc(T->childList,

sizeof(treeNode *) * ChildListMemoryBLOCK * (blockCount + 1));

}

}

else

{

// 申请子节点列表的内存空间

T->childList = (treeNode **)malloc(sizeof(treeNode *) * ChildListMemoryBLOCK);

}

// 移除原有的子节点

removeChildNode(child->parent, child);

child->parent = T;

// 在子节点列表中添加新增的子节点

T->childList[T->childCount] = child;

// 子节点数量自增

T->childCount++;

return child;

}

// 移除子节点

int removeChildNode(treeNode *T, treeNode *child)

{

if ((!T) || (!child)) return -1;

// 判断父级关系是否匹配

if (T != child->parent) return -1;

int i, count;

// 判断原有的父级关系是否已经维护

for (i = 0; i < T->childCount; i++)

{

if (T->childList[i] == child)

{

count = T->childCount - 1;

// 维护子级列表关系,之后的子级指针需要前移

for (; i < count; i++)

{

T->childList[i] = T->childList[i + 1];

}

T->childCount--;

return 1;

}

}

return -1;

}

// 删除子节点

int deleteChildNode(treeNode *T, int index)

{

if (!T) return -1;

// 判断索引是否有效

if ((index < 0) || (index >= T->childCount)) return -1;

// 清空子节点

clearTreeList(T->childList[index]);

int i, count = T->childCount - 1;

// 维护子级列表关系,之后的子级指针需要前移

for (i = index; i < count; i++)

{

T->childList[i] = T->childList[i + 1];

}

T->childCount--;

return 1;

}

// 通过关键字,删除子节点(递归)

int deleteNodeByKey(treeNode *T, int key)

{

// 通过关键字,取得树节点(递归)

treeNode *tn = getNodeByKey(T, key);

if (!tn) return -1;

// 移除原有的父级关系

removeChildNode(tn->parent, tn);

// 清空子节点

clearTreeList(tn);

return 1;

}

// 清空树列表(递归)

void clearTreeList(treeNode *T)

{

if (!T) return;

int i;

// 递归循环子节点

for (i = 0; i < T->childCount; i++)

{

// 递归调用

clearTreeList(T->childList[i]);

}

// 释放数据关键字

if (T->dataKey) free(T->dataKey);

// 释放数据空间

if (T->data) free(T->data);

// 释放子节点空间

if (T->childList) free(T->childList);

// 释放自己

free(T);

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值