first commit of radix_tree

This commit is contained in:
HuZW 2023-06-25 19:21:37 +08:00
parent 310658dce2
commit f0520b9b74
9 changed files with 630 additions and 1 deletions

View File

@ -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

View File

@ -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

View File

@ -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. 测试程序说明
测试函数为insertsearchdeleteheight以及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)

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

View File

@ -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<stdio.h>
#include<string.h>
#include<stdbool.h>
#include<stdlib.h>
#include <transform.h>
#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;i<MAXSIZE;i++){
root->child[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;i<MAXSIZE;i++){
node->child[index]->child[i]=NULL;
}
}
//创建节点并初始化
radixNode* createNode(){
radixNode* node=(radixNode*)malloc(sizeof(radixNode));
node->str='\0';
for(int i=0;i<MAXSIZE;i++){
node->child[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(preIndex<strlen(node->str)-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;i<MAXSIZE;i++){
newNode->child[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(preIndex<strlen(str)-1){
insertChild(tree,node,substring(str,preIndex+1,strlen(str)-preIndex-1));
}
}
void insertChild(radixTree* tree,radixNode* node,char* str){
if(str=="")return;
//没有子节点,则直接新申请一个节点
if(getSize(node)==0){
createRadixNode(str,0,node);
return;
}
//找到是否有子树包含str的前缀,有则插入节点
for(int i=iter(node,BEGIN);i!=END;i=iter(node,i)){
if(isPartPreFix(str,node->child[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;i<MAXSIZE;i++){
if(node->child[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;i<start+len;i++){
*temp=str[i];
temp++;
}
res[len]='\0';
return res;
}
bool deleteNode(char* str,radixTree* tree){
if(str=="")return false;
return deleteFromNode(NULL,tree->root,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)<strlen(str)){
//部分匹配
return deleteFromChild(substring(str,preIndex+1,strlen(str)-preIndex-1),node);
}else{
//str的长度小于当前节点的字符串长度,即当前树中不包含此树
return false;
}
return false;
}
//检查子树中是否包含节点
bool includedWord(radixNode* node){
if(node==NULL)return false;
for(int i=iter(node,BEGIN);i!=END;i=iter(node,i)){
if(includedWord(node->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;i<MAXSIZE;i++){
if(node->child[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;i<MAXSIZE;i++){
if(searchFromNode(word,node->child[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_tree<temp)height_tree=temp;
}
return height_tree+1;
}
//树存储的字符串的个数
int size(radixTree* tree){
int num=0;
sizeOfNode(tree->root,&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<len;i++){
str1[i]=str2[i];
}
strcpy((char*)str1,str2);
}
//孩子节点的迭代器
int iter(radixNode* node,int it){
it++;
if(it<0||it>=MAXSIZE){
return -1;
}
for(;it<MAXSIZE;it++){
if(node->child[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);

View File

@ -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<stdio.h>
#include<stdbool.h>
#include<stdlib.h>
#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

View File

@ -14,4 +14,3 @@ export DEFINES := -DHAVE_CCONFIG_H -DHAVE_SIGINFO
export ARCH = risc-v
export MCU = k210