diff --git a/APP_Framework/Applications/app_test/Kconfig b/APP_Framework/Applications/app_test/Kconfig index 45df5f5d5..ffadf9c6b 100644 --- a/APP_Framework/Applications/app_test/Kconfig +++ b/APP_Framework/Applications/app_test/Kconfig @@ -240,5 +240,9 @@ menu "test app" bool "Config test soft timer" default n + + menuconfig USER_TEST_RADIX + bool "Config test radix" + default n endif endmenu diff --git a/APP_Framework/Applications/app_test/Makefile b/APP_Framework/Applications/app_test/Makefile index 1cf919846..7625e7111 100644 --- a/APP_Framework/Applications/app_test/Makefile +++ b/APP_Framework/Applications/app_test/Makefile @@ -101,5 +101,9 @@ ifeq ($(CONFIG_ADD_XIZI_FETURES),y) SRC_FILES += test_timer.c endif + ifeq ($(CONFIG_USER_TEST_RADIX),y) + SRC_FILES += test_radix_tree/test_radix_tree.c + endif + include $(KERNEL_ROOT)/compiler.mk endif diff --git a/APP_Framework/Applications/app_test/test_radix_tree/README.MD b/APP_Framework/Applications/app_test/test_radix_tree/README.MD new file mode 100644 index 000000000..9f11d83ab --- /dev/null +++ b/APP_Framework/Applications/app_test/test_radix_tree/README.MD @@ -0,0 +1,34 @@ +# ##请填写赛题题目## +一级赛题3 基于k210-emulator实现基数树并测试验证 +## 1. 简介 +基于矽璓模拟器k210-emulator,实现基数树,并编写测试程序在shell终端打印结果, + +## 2. 数据结构设计说明 +radix_tree.h头文件定义了radixNode作为树节点,MAXSIZE为一个节点的孩子节点的数量. +radixTree中定义根节点 +typedef struct rdNode +{ + char* str;//存储的字符串 + bool exist;//当前节点是否是存储的字符串的最终的节点 + struct rdNode *child[MAXSIZE];//孩子节点 +}radixNode; + +函数: +insert(char* s):向树中存储一个字符串 +delete(char* s):删除树中的一个字符串 +search(char* s):查询树中是否存在字符串 +height():查看树的高度 +size():查看树存储的字符串个数 + +其余函数都是辅助函数。 + +## 3. 测试程序说明 +测试函数为insert,search,delete,height以及size。首先创建基数树并插入字符串,随后查找,在删除字符串继续查找。并且比较删除前后的树高和size. + +## 4. 运行结果(##需结合运行测试截图按步骤说明##) +打开menuconfig进行裁剪 +![Alt text](Snipaste_2023-06-25_11-12-56.png) +编译项目 +![Alt text](Snipaste_2023-06-25_11-14-42.png) +启动qemu并且运行Shell命令 +![Alt text](Snipaste_2023-06-25_11-15-10.png) diff --git a/APP_Framework/Applications/app_test/test_radix_tree/Snipaste_2023-06-25_11-12-56.png b/APP_Framework/Applications/app_test/test_radix_tree/Snipaste_2023-06-25_11-12-56.png new file mode 100644 index 000000000..0aa12ed92 Binary files /dev/null and b/APP_Framework/Applications/app_test/test_radix_tree/Snipaste_2023-06-25_11-12-56.png differ diff --git a/APP_Framework/Applications/app_test/test_radix_tree/Snipaste_2023-06-25_11-14-42.png b/APP_Framework/Applications/app_test/test_radix_tree/Snipaste_2023-06-25_11-14-42.png new file mode 100644 index 000000000..86aa12f17 Binary files /dev/null and b/APP_Framework/Applications/app_test/test_radix_tree/Snipaste_2023-06-25_11-14-42.png differ diff --git a/APP_Framework/Applications/app_test/test_radix_tree/Snipaste_2023-06-25_11-15-10.png b/APP_Framework/Applications/app_test/test_radix_tree/Snipaste_2023-06-25_11-15-10.png new file mode 100644 index 000000000..0f38583b7 Binary files /dev/null and b/APP_Framework/Applications/app_test/test_radix_tree/Snipaste_2023-06-25_11-15-10.png differ diff --git a/APP_Framework/Applications/app_test/test_radix_tree/test_radix_tree.c b/APP_Framework/Applications/app_test/test_radix_tree/test_radix_tree.c new file mode 100644 index 000000000..78524fc2f --- /dev/null +++ b/APP_Framework/Applications/app_test/test_radix_tree/test_radix_tree.c @@ -0,0 +1,457 @@ +/* +* Copyright (c) 2020 AIIT XUOS Lab +* XiUOS is licensed under Mulan PSL v2. +* You can use this software according to the terms and conditions of the Mulan PSL v2. +* You may obtain a copy of Mulan PSL v2 at: +* http://license.coscl.org.cn/MulanPSL2 +* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, +* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, +* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +* See the Mulan PSL v2 for more details. +*/ + +/** +* @file: test_radix_tree.cc +* @brief: a application of radixTree +* @version: 1.0 +* @author: huzhongwen +* @date: 2023/6/22 +*/ + +#include +#include +#include +#include +#include + +#include"test_radix_tree.h" +#define MAXSIZE (10) +#define ROOTVAL "####\0" +#define END -1 +#define BEGIN -1 + + +//创建根节点 +radixTree* createRadixTree(){ + radixNode* root=(radixNode*)malloc(sizeof(radixNode)); + root->str=ROOTVAL; + root->exist=false; + radixTree *tree=(radixTree*)malloc(sizeof(radixTree)); + tree->root=root; + for(int i=0;ichild[i]=NULL; + } + return tree; +} + +//从树节点创建子树节点 +void createRadixNode(char* str,int index,radixNode* node){ + if(index<0||index>MAXSIZE){ + return; + } + node->child[index]=(radixNode*)malloc(sizeof(radixNode)); + node->child[index]->str=str; + node->child[index]->exist=true; + for(int i=0;ichild[index]->child[i]=NULL; + } +} + +//创建节点并初始化 +radixNode* createNode(){ + radixNode* node=(radixNode*)malloc(sizeof(radixNode)); + node->str='\0'; + for(int i=0;ichild[i]=NULL; + } + return node; +} + +//判断树节点是否是根节点 +bool isRoot(radixNode* node){ + if(node!=NULL&&node->str==ROOTVAL){ + return true; + } + return false; +} +/* +//判断两颗子树是否是相同的 +bool isSame(radixNode *node1,radixNode *node2){ + if(node1==NULL)return node2==NULL; + if(node1->str!=node2->str)return false; + //uncompleted + if(node1->len!=node2->len)return false; + + // + return true; +} +*/ + +void insert(radixTree* tree,char* str){ + insertChild(tree,tree->root,str); +} + + +// +//在包含公共前缀时,插入节点 +void insertNode(radixTree *tree,radixNode* node,char *str){ + if(str=="")return; + if(isRoot(node)){ + return insertChild(tree,node,str); + } + //计算公共前缀的索引 + int preIndex=calPreFix(str,node->str); + //节点字符串包含插入字符串,当前节点的剩余字符串,需要作为当前节点的孩子系节点 + if(preIndexstr)-1){ + char* oldStr=node->str; + if(getSize(node)==0){ + insertChild(tree,node,substring(oldStr,preIndex+1,strlen(oldStr)-preIndex-1)); + }else{ + //存在孩子节点的情况下,创建新节点 + radixNode* newNode=(radixNode*)malloc(sizeof(radixNode)); + //复制孩子指针 + for(int i=0;ichild[i]=node->child[i]; + node->child[i]=NULL; + } + node->child[0]=newNode; + newNode->exist=true; + //划分字符串 + node->str=substring(oldStr,0,preIndex); + newNode->str=substring(oldStr,preIndex+1,strlen(oldStr)-preIndex-1); + } + } + + //此时插入字符串的剩余字符串需要继续插入到孩子节点当中 + if(preIndexchild[i])){ + insertNode(tree,node->child[i],str); + return; + } + } + //如果当前节点的孩子节点没有找到前缀,则新初始化一个孩子节点并保存str + radixNode* newNode=createNode(); + //strCopy(newNode->str,str); + newNode->str=str; + newNode->exist=true; + for(int i=0;ichild[i]==NULL){ + node->child[i]=newNode; + break; + } + } +} + + +//uncompleted +//找到一个字符串是否包含前缀 +bool isPartPreFix(char* str,radixNode*node){ + if(node==NULL)return false; + if(strlen(str)==0)return false; + + if(str[0]==node->str[0])return true; + return false; +} + + +//计算插入的str和节点的str的公共部分的索引 +int calPreFix(char* str,char* node_str){ + if(node_str==NULL)return -1; + int preIndex=0; + while (str[preIndex]!='\0'&&node_str[preIndex]!='\0') + { + if(str[preIndex]==node_str[preIndex]){ + preIndex++; + }else{ + return preIndex-1; + } + } + return preIndex-1; +} + +//计算char长度 +int getLength(char* str){ + int count=0; + while (str[count]!='\0') + { + count++; + } + return count; +} + +//复制chars数组 +int copyChar(char* str1,char* str2){ + if(str1==NULL||str2==NULL){ + printf("copyChar get a Null"); + return -1; + } + +} + +//截取字符串,从从start到最后的位置 +char* substring(char* str,int start,int len){ + char *res=(char*)malloc(sizeof(char)*(len+1)); + char* temp=res; + int count=0; + for(int i=start;iroot,str); +} + +//删除部分的代码 +bool deleteFromNode(radixNode* parentNode,radixNode* node,char* str){ + if(node==NULL)return false; + if(parentNode==NULL){ + return deleteFromChild(str,node); + } + //找出str和当前节点的公共前缀 + int preIndex=calPreFix(str,node->str); + //当前节点没有公共前缀 + if(preIndex<0){ + return false; + } + //完全匹配 + if(preIndex==strlen(str)-1){ + //当前节点没有孩子,则直接删除 + if(getSize(node)==0){ + for(int i=iter(parentNode,BEGIN);i!=END;i=iter(parentNode,i)){ + if(parentNode!=NULL&&node!=NULL&&parentNode->child[i]!=NULL){ + if(parentNode->child[i]->str==node->str){ + parentNode->child[i]=NULL; + free(node); + } + } + } + return true; + }else{ + //当前节点存在孩子时 + if(includedWord(node)){ + node->exist=false; + }else{ + deleteAllNode(node); + } + return true; + } + }else if(strlen(node->str)child[i])){ + return true; + } + } + if(node->exist){ + return true; + } + return false; +} + +//删除以node为根的树 +void deleteAllNode(radixNode* node){ + if(node==NULL)return; + radixNode* temp; + for(int i=iter(node,BEGIN);i!=END;i=iter(node,i)){ + deleteAllNode(node->child[i]); + } + free(node); +} + + +//删除节点的辅助函数 +bool deleteFromChild(char* str,radixNode* node){ + if(node==NULL)return false; + for(int i=iter(node,BEGIN);i!=END;i=iter(node,i)){ + if(deleteFromNode(node,node->child[i],str)){ + return true; + } + } +} + + +//获得节点的子树节点的数量 +int getSize(radixNode* node){ + if(node==NULL)return -1; + int size=0; + for(int i=0;ichild[i]!=NULL){ + size++; + } + } + return size; +} + + + + +//搜索字符串 +bool search(char* word,radixTree* tree){ + if(word=="")return false; + return searchFromNode(word,tree->root); +} + +//辅助函数 +bool searchFromNode(char* word,radixNode* node){ + if(node==NULL)return false; + if(isRoot(node)){ + return searchFromChild(word,node); + } + //找出word与当前节点的公共前缀 + int Index=calPreFix(word,node->str); + if(Index<0){ + return false; + } + //完全匹配 + if((Index==strlen(word)-1)&&node->exist){ + return true; + }else{ + //部分匹配 + return searchFromChild(substring(word,Index+1,strlen(word)-Index-1),node); + } +} + +//辅助函数 +bool searchFromChild(char* word,radixNode* node){ + for(int i=0;ichild[i])){ + return true; + } + } + return false; +} + +//计算树高 +int height(radixTree* tree){ + return heightOfNode(tree->root); +} + +//树高辅助函数 +int heightOfNode(radixNode* node){ + if(node==NULL)return 0; + int height_tree=0; + for(int i=iter(node,BEGIN);i!=END;i=iter(node,i)){ + int temp=heightOfNode(node->child[i]); + if(height_treeroot,&num); + return num; +} + +void sizeOfNode(radixNode* node,int *num){ + if(node==NULL)return; + for(int i=iter(node,BEGIN);i!=END;i=iter(node,i)){ + sizeOfNode(node->child[i],num); + } + if(node->exist){ + (*num)++; + } +} + +void strCopy(char* str1,char* str2){ + int len=strlen(str2); + if(len==0)return; + str1=(char*)malloc(sizeof(char)*(len+1)); + for(int i=0;i=MAXSIZE){ + return -1; + } + for(;itchild[it]==NULL){ + continue; + } + return it; + } + return -1; +} + + +void TestRadix(){ + printf("test radix tree\n"); + radixTree* tree=createRadixTree(); + char* s=(char*)malloc(sizeof(char)*10); + s="ab\0"; + insert(tree,s); + s="abc\0"; + insert(tree,s); + s="abdg\0"; + insert(tree,s); + s="cd\0"; + insert(tree,s); + s="abdgo\0"; + insert(tree,s); + + if(search(s,tree)){ + printf("search 'abdg' successfully\n"); + } + if(search(s,tree)){ + printf("search 'abdgo' successfully\n"); + } + + printf("size is :%d\n",size(tree)); + printf("height is:%d\n",height(tree)); + + if(deleteNode(s,tree)){ + printf("delete word of '%s' successfully\n",s); + } + if(!search(s,tree)){ + printf("search %s failure\n",s); + } + s="abc\0"; + if(deleteNode(s,tree)){ + printf("delete '%s'successfully\n",s); + } + if(!search(s,tree)){ + printf("search %s failure\n",s); + } + printf("size is :%d\n",size(tree)); + printf("height is:%d\n",height(tree)); +} + +PRIV_SHELL_CMD_FUNCTION(TestRadix, a radix_tree test sample, PRIV_SHELL_CMD_MAIN_ATTR); diff --git a/APP_Framework/Applications/app_test/test_radix_tree/test_radix_tree.h b/APP_Framework/Applications/app_test/test_radix_tree/test_radix_tree.h new file mode 100644 index 000000000..773da4cf6 --- /dev/null +++ b/APP_Framework/Applications/app_test/test_radix_tree/test_radix_tree.h @@ -0,0 +1,131 @@ +/* +* Copyright (c) 2020 AIIT XUOS Lab +* XiUOS is licensed under Mulan PSL v2. +* You can use this software according to the terms and conditions of the Mulan PSL v2. +* You may obtain a copy of Mulan PSL v2 at: +* http://license.coscl.org.cn/MulanPSL2 +* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, +* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, +* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +* See the Mulan PSL v2 for more details. +*/ + +/** +* @file: test_radix_tree.cc +* @brief: a application of radixTree +* @version: 1.0 +* @author: huzhongwen +* @date: 2023/6/22 +*/ + + +#ifndef RADIX_TREE +#define RADIX_TREE + +#include +#include +#include + + +#define MAXSIZE (10) +#define ROOTVAL "####\0" + + +typedef struct rdNode +{ + char* str; + bool exist; + struct rdNode *child[MAXSIZE]; +}radixNode; + +typedef struct rdTree +{ + struct rdNode* root; +}radixTree; + +//创建根节点 +radixTree* createRadixTree(); + +//从树节点创建子树节点 +void createRadixNode(char* str,int index,radixNode* node); + +//创建节点并初始化 +radixNode* createNode(); + +//判断树节点是否是根节点 +bool isRoot(radixNode* node); + +void insert(radixTree* tree,char* str); + +//在包含公共前缀时,插入节点 +void insertNode(radixTree *tree,radixNode* node,char* str); + +void insertChild(radixTree* tree,radixNode* node,char* str); + +//找到一个字符串是否包含前缀 +bool isPartPreFix(char* str,radixNode*node); + + +//计算插入的str和节点的str的公共部分的索引 +int calPreFix(char* str,char* node_str); + +//计算char长度 +int getLength(char* str); + +//复制chars数组 +int copyChar(char* str1,char* str2); + +//检查子树中是否包含节点 +bool includedWord(radixNode* node); + +//删除以node为根的树 +void deleteAllNode(radixNode* node); + +//删除节点 +bool deleteNode(char* str,radixTree* tree); + +//删除节点辅助函数 +bool deleteFromNode(radixNode* parentNode,radixNode* node,char* str); + +//删除节点的辅助函数 +bool deleteFromChild(char* str,radixNode* node); + +//获得节点的子树节点的数量 +int getSize(radixNode* node); + +//打印树的每层的节点数 +void printTree(radixNode* node); + +//截取字符串 +char* substring(char* str,int start,int len); + +//搜索字符串 +bool search(char* word,radixTree* tree); + +//辅助函数 +bool searchFromNode(char* word,radixNode* node); + +//辅助函数 +bool searchFromChild(char* word,radixNode* node); + +//计算树高 +int height(radixTree* tree); + +//树高辅助函数 +int heightOfNode(radixNode* node); + +//树存储的字符串的个数 +int size(radixTree* tree); + +void sizeOfNode(radixNode* node,int *num); + +//复制字符串 +void strCopy(char* str1,char* str2); + +//孩子节点的迭代器 +int iter(radixNode* node,int it); + + +//void TestRadix(); + +#endif \ No newline at end of file diff --git a/Ubiquitous/XiZi_IIoT/board/k210-emulator/config.mk b/Ubiquitous/XiZi_IIoT/board/k210-emulator/config.mk index d33cf2db8..159f99fd3 100644 --- a/Ubiquitous/XiZi_IIoT/board/k210-emulator/config.mk +++ b/Ubiquitous/XiZi_IIoT/board/k210-emulator/config.mk @@ -14,4 +14,3 @@ export DEFINES := -DHAVE_CCONFIG_H -DHAVE_SIGINFO export ARCH = risc-v export MCU = k210 -