first commit of radix_tree
This commit is contained in:
parent
310658dce2
commit
f0520b9b74
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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进行裁剪
|
||||

|
||||
编译项目
|
||||

|
||||
启动qemu并且运行Shell命令
|
||||

|
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 |
|
@ -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);
|
|
@ -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
|
|
@ -14,4 +14,3 @@ export DEFINES := -DHAVE_CCONFIG_H -DHAVE_SIGINFO
|
|||
export ARCH = risc-v
|
||||
export MCU = k210
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue