# 基數樹的簡單實現

``````#pragma once
#include<stdlib.h>
#include<stdio.h>
#define MEMPAGE 4096//內存頁的大小，一般爲4kb
#define INIT_POOL_SIZE (MEMPAGE*32)	//初始內存池大小
#define INIT_FREE_SIZE (INIT_POOL_SIZE/2) //初始備用節點長度
#define INIT_NODE_NUM (16*32)

typedef unsigned int ptr_t;
typedef unsigned int uint32;

#define BITS 2
const int radix_tree_height = sizeof(ptr_t) * 8 / BITS;//樹的高度
//返回key中由pos指定的位的值，位數由BITS指定
#define CHECK_BITS(key,pos) ((((unsigned int)(key))<<sizeof(int)*8-((pos)+1)*BITS)>>(sizeof(int)*8-BITS))
//基數樹節點
ptr_t value;//節點儲存的值
};
//使用內存池是爲減少建立節點時重新申請內存的時間
//內存池描述結構，放在內存池的前段
//已分配內存中還未使用的內存首地址
char* start;
//已分配內存中還未使用的內存長度
size_t size;
//基數樹管理結構
//根節點
//內存池指針
pool_t pool;
//儲存已分配但不在樹中的節點（雙向鏈表，這裏儲存其中的一個節點）
//內存池擴大函數，num：新內存池的大小，=-1使用默認值,單位：頁
{
if (num == -1)num = INIT_POOL_SIZE;
pool_t pool = (pool_t)malloc(num * MEMPAGE);
if (pool == NULL)return NULL;
pool->size = num * MEMPAGE - sizeof(radix_pool);
pool->next = t->pool->next;
pool->prev = t->pool;
t->pool->next->prev = pool;
t->pool->next = pool;
t->pool = pool;
return pool;
}

//創建一個節點，從內存池中取出可以使用的節點
{
if (t->free != NULL) {//從free中提取節點
node = t->free;
t->free = node->parent;
}
else {//在內存池中尋找可以使用的內存
get_new_pool(t, -1);
}
}
node->child[0] = NULL;
node->child[1] = NULL;
node->child[2] = NULL;
node->child[3] = NULL;
node->parent = NULL;
node->value = NULL;
return node;
}
//創建管理結構
{
int i;
if (tree == NULL)return NULL;
char* p = (char*)malloc(INIT_POOL_SIZE);
if (!p) {
free(tree); return NULL;
}
//爲內存池結構分配空間
((pool_t)p)->next = (pool_t)p;
((pool_t)p)->prev = (pool_t)p;

//在內存中創建鏈表
for (i = 1; i < INIT_NODE_NUM - 2; ++i) {
ns[i].parent = &ns[i + 1];
}
ns[i].parent = NULL;
ns[0].child[0] = NULL;
ns[0].child[1] = NULL;
ns[0].child[2] = NULL;
ns[0].child[3] = NULL;
ns[0].parent = NULL;
ns[0].value = NULL;
tree->pool = (pool_t)p;
tree->root = ns;
tree->free = &ns[1];
((pool_t)p)->start = (char*)ns + sizeof(radix_node_t) * INIT_NODE_NUM;
return tree;
}

//插入
{
int i, temp;
node = t->root;
for (i = 0; i < radix_tree_height; i++) {
temp = CHECK_BITS(key, i);
if (!node->child[temp]) {
if (!child)return NULL;
child->parent = node;
node->child[temp] = child;
node = node->child[temp];
}
else {
node = node->child[temp];
}
}
node->value = value;
return 0;
}

//由於插入時會創建很多節點，爲了提高刪除速度這裏只會刪除最底層的指定節點
{
radix_node_t* node = t->root, * par;
int i = 0, temp = 0;
do {
temp = CHECK_BITS(key, i++);
node = node->child[temp];
} while (node && i < radix_tree_height);
//node爲儲存value的節點，在父節點中將此節點的鏈接置空，
//然後清空value後將此節點加入free中
par = node->parent;
par->child[temp] = NULL;
node->value = NULL;
node->child[0] = NULL;
node->child[1] = NULL;
node->child[2] = NULL;
node->child[3] = NULL;
node->parent = t->free->parent;
t->free->parent = node;
return 0;
}
//打印函數，會打印出所有葉節點儲存的值
{
if (node == NULL)return;
if (node->value != NULL)
printf("%x\n", node->value);
}
//節點查找函數
//key爲索引，返回葉節點被查找到的值
{
int i = 0, temp;
node = t->root;
while (node && i < radix_tree_height) {
temp = CHECK_BITS(key, i++);
node = node->child[temp];
}
if (node == NULL)return NULL;
return node->value;
}``````