對之前的基數樹做了修改,減少空間佔用。
頭文件:
#pragma once
#include<stdlib.h>
#include<stdio.h>
#define MEMPAGE 4096
#define INIT_POOL_SIZE (MEMPAGE*1) //初始內存池大小
#define RADIX_INSERT_VALUE_OCCUPY -1 //該節點已被佔用
#define RADIX_INSERT_VALUE_SAME -2 //插入了相同的值
#define RADIX_DELETE_ERROR -3 //刪除錯誤
typedef unsigned int ptr_t;
typedef unsigned int uint32;
#define BITS 2
//返回key指定位的值,位數由BITS指定
#define CHECK_BITS(key,pos) ((((unsigned int)(key))<<sizeof(int)*8-(pos+1)*BITS)>>(sizeof(int)*8-BITS))
//基數樹節點
typedef struct radix_node_t radix_node_t;
struct radix_node_t {
radix_node_t* child[4];
radix_node_t* parent;
};
typedef struct radix_leafnode_t {
struct radix_leafnode_t* next;
uint32 key;//路徑
ptr_t value;//值
}radix_leafnode_t;
//內存池結構,放在內存池的前段
typedef struct radix_pool {
struct radix_pool* next;
struct radix_pool* prev;
char* start;
size_t size;
}radix_pool, * pool_t;
//基數樹管理結構
typedef struct radix_tree_t {
//指向根節點
radix_node_t* root;
//內存池指針,(一頁內存)
pool_t pool;
//儲存已分配但不在樹中的節點(雙向鏈表,這裏儲存其中的一個節點)
radix_node_t* free;
//葉節點內存池
pool_t leafpool;
//儲存已分配但不在樹中的葉節點
radix_leafnode_t* lfree;
}radix_tree_t;
//內存池擴大函數,num:新內存池的大小,=-1使用默認值,單位:頁
pool_t get_new_pool(radix_tree_t* t, int num);
//創建一個節點,從內存池中取出可以使用的節點
radix_node_t* radix_node_alloc(radix_tree_t* t);
//創建管理結構
radix_tree_t* radix_tree_create();
//插入
int radix_tree_insert(radix_tree_t* t, uint32 key, ptr_t value);
//由於插入時會創建很多節點,爲了提高速度這裏只會刪除最底層的指定節點
int radix_tree_delete(radix_tree_t* t, uint32 key);
//打印函數,會打印出所有底層節點的長度
//void radix_print(radix_node_t* node);
//節點查找函數
ptr_t radix_tree_find(radix_tree_t * t, uint32 key);
pool_t get_new_leafpool(radix_tree_t* t, int num);
radix_leafnode_t* radix_leafnode_alloc(radix_tree_t* t);
//遍歷葉節點,返回葉節點數量
int radix_tree_traversal(radix_tree_t* t);
//遍歷葉節點,並指定操作
int radix_tree_traversal_fun(radix_tree_t* t, void(*fun)(uint32, uint32));
實現文件:
#include"radixTree.h"
static radix_leafnode_t* last_leafnode;
static int radix_tree_height = sizeof(ptr_t) * 8 / BITS;
//內存池擴大函數,num:新內存池的大小,=-1使用默認值,單位:頁
pool_t get_new_pool(radix_tree_t*t, int num)
{
if (num <=0 )num = INIT_POOL_SIZE;
else num *= MEMPAGE;
pool_t pool = (pool_t)malloc(num);
if (pool == NULL)return NULL;
pool->next = t->pool->next;
pool->prev = t->pool;
t->pool->next->prev = pool;
t->pool->next = pool;
t->pool = pool;
//格式化,將申請的內存全部設置爲節點
radix_node_t * node=(radix_node_t*)((char*)pool + sizeof(radix_pool));
int i;
for (i = 0; i < (num - sizeof(radix_pool)-1) / sizeof(radix_node_t); ++i) {
node[i].parent = &(node[i + 1]);
}
node[i++].parent = NULL;
t->free = node;
pool->start = (char*)((char*)node+sizeof(radix_node_t)*i);
pool->size = num-sizeof(radix_node_t)*i-sizeof(radix_pool);
return pool;
}
//葉節點內存池擴大
pool_t get_new_leafpool(radix_tree_t* t, int num)
{
if (num <=0)num = INIT_POOL_SIZE;
else { num *= MEMPAGE; }
pool_t leafpool = (pool_t)malloc(num);
if (leafpool == NULL)return NULL;
leafpool->next = t->leafpool->next;
leafpool->prev = t->leafpool;
t->leafpool->next->prev = leafpool;
t->leafpool->next = leafpool;
t->leafpool = leafpool;
radix_leafnode_t* node = (radix_leafnode_t*)((char*)leafpool + sizeof(radix_pool));
int i;
for (i = 0; i < (num - sizeof(radix_pool) - 1) / sizeof(radix_leafnode_t); ++i) {
node[i].next = &(node[i + 1]);
}
node[i++].next = NULL;
t->lfree = node;
leafpool->start = (char*)((char*)node + sizeof(radix_leafnode_t) * i);
leafpool->size = num - sizeof(radix_leafnode_t) * i - sizeof(radix_pool);
return leafpool;
}
//葉節點獲取
radix_leafnode_t* radix_leafnode_alloc(radix_tree_t* t)
{
radix_leafnode_t* node;
if (t->free != NULL) {
node = t->lfree;
t->lfree = node->next;
}
else {
if (t->leafpool->size < sizeof(radix_leafnode_t)) {
get_new_leafpool(t, -1);
}
if (t->lfree != NULL) {
node = t->lfree;
t->lfree = node->next;
}
else {
node = (radix_leafnode_t*)t->leafpool->start;
t->leafpool->start += sizeof(radix_leafnode_t);
t->leafpool->size -= sizeof(radix_leafnode_t);
}
}
node->next = (radix_leafnode_t*)NULL;
node->key = (uint32)NULL;
node->value = (ptr_t)NULL;
return node;
}
//創建一個節點,從內存池中取出可以使用的節點
radix_node_t* radix_node_alloc(radix_tree_t* t)
{
radix_node_t* node;
if (t->free != NULL) {//從free中提取節點
node = t->free;
t->free = node->parent;
}
else {//在內存池中尋找可以使用的內存
if (t->pool->size < sizeof(radix_node_t)) {//如果剩餘空間不夠分配,則重新分配
get_new_pool(t, -1);
}
if (t->free != NULL) {//從free中提取節點
node = t->free;
t->free = node->parent;
}
else {
node = (radix_node_t*)t->pool->start;
t->pool->start += sizeof(radix_node_t);
t->pool->size -= sizeof(radix_node_t);
}
}
node->child[0] = NULL;
node->child[1] = NULL;
node->child[2] = NULL;
node->child[3] = NULL;
node->parent = NULL;
return node;
}
//創建管理結構
radix_tree_t* radix_tree_create()
{
int i;
radix_tree_t* tree = (radix_tree_t*)malloc(sizeof(radix_tree_t));
if (tree == NULL)return NULL;
tree->pool = (pool_t)malloc(INIT_POOL_SIZE);
if (tree->pool == NULL) { free(tree); return NULL; }
tree->leafpool = (pool_t)malloc(INIT_POOL_SIZE);
if (tree->leafpool == NULL) { free(tree->pool); free(tree); return NULL; }
radix_node_t* node = (radix_node_t*)((char*)tree->pool + sizeof(radix_pool));
tree->pool->next = tree->pool;
tree->pool->prev = tree->pool;
for (i = 1; i < (INIT_POOL_SIZE - sizeof(radix_pool) - 1) / sizeof(radix_node_t); ++i) {
node[i].parent = &node[i + 1];
}
node[i++].parent = NULL;
node[0].child[0] = NULL;
node[0].child[1] = NULL;
node[0].child[2] = NULL;
node[0].child[3] = NULL;
node[0].parent = NULL;
i *= sizeof(radix_node_t);
tree->pool->start = ((char*)node +i);
tree->pool->size = INIT_POOL_SIZE - sizeof(radix_pool) - i;
//葉節點
radix_leafnode_t* lnode= (radix_leafnode_t*)((char*)tree->leafpool + sizeof(radix_pool));
tree->leafpool->next = tree->leafpool;
tree->leafpool->prev = tree->leafpool;
for (i = 1; i < (INIT_POOL_SIZE - sizeof(radix_pool) - 1) / sizeof(radix_leafnode_t); ++i) {
lnode[i].next = &(lnode[i + 1]);
}
lnode[i++].next = NULL;
lnode[0].key = (uint32)NULL;
lnode[0].next = lnode;
lnode[0].value = (ptr_t)NULL;
last_leafnode = lnode;
i *= sizeof(radix_leafnode_t);
tree->leafpool->start = ((char*)lnode + i);
tree->leafpool->size = INIT_POOL_SIZE - sizeof(radix_pool) - i;
tree->free = &node[1];
tree->lfree = &lnode[1];
tree->root = node;
return tree;
}
//插入
int radix_tree_insert(radix_tree_t* t, uint32 key, ptr_t value)
{
int i, temp;
radix_node_t* node, * child;
radix_leafnode_t* lnode;
node = t->root;
for (i = 0; i < radix_tree_height-1; i++) {
temp = CHECK_BITS(key, i);
if (!node->child[temp]) {
child = radix_node_alloc(t);
if (child==NULL)return -1;
child->parent = node;
node->child[temp] = child;
node = node->child[temp];
}
else {
node = node->child[temp];
}
}
temp = CHECK_BITS(key, i);
lnode = (radix_leafnode_t*)node->child[temp];
if (lnode != NULL)return -1;
lnode = radix_leafnode_alloc(t);
if (lnode == NULL)return -1;
lnode->next = last_leafnode->next;
last_leafnode->next = lnode;
last_leafnode = lnode;
node->child[temp] =(radix_node_t*) lnode;
if (lnode->value == value)return RADIX_INSERT_VALUE_SAME;
if (lnode->value != (ptr_t)NULL)return RADIX_INSERT_VALUE_OCCUPY;
lnode->value = value;
lnode->key = key;
return 0;
}
//由於插入時會創建很多節點,爲了提高速度這裏只會刪除最底層的指定節點
int radix_tree_delete(radix_tree_t* t, uint32 key)
{
radix_node_t* node = t->root, * par;
int i = 0, temp = 0;
for (i = 0; i < radix_tree_height - 1; ++i) {
temp = CHECK_BITS(key, i);
node = node->child[temp];
if (node == NULL) return RADIX_DELETE_ERROR;
}
temp = CHECK_BITS(key, i);
radix_leafnode_t* lnode;
lnode = (radix_leafnode_t*)node->child[temp];
if (lnode == NULL)return RADIX_DELETE_ERROR;
node->child[temp] = NULL;
//將lnode迴歸內存池
lnode->next = t->lfree->next;
t->lfree->next = lnode;
return 0;
}
//節點查找函數
//key爲索引,返回葉節點被查找到的值
ptr_t radix_tree_find(radix_tree_t* t, uint32 key)
{
int i = 0, temp;
radix_node_t* node;
node = t->root;
for (i; i < radix_tree_height - 1; ++i) {
temp = CHECK_BITS(key, i);
node = node->child[temp];
if (node == NULL)return 0;
}
temp = CHECK_BITS(key, i);
radix_leafnode_t* lnode;
lnode = (radix_leafnode_t*)node->child[temp];
if (lnode == NULL)return 0;
return lnode->value;
}
//遍歷葉節點,打印節點內容,返回葉節點數量
int radix_tree_traversal(radix_tree_t* t)
{
int i = 0;
radix_leafnode_t* temp = last_leafnode,*node=last_leafnode;
do {
printf("key:%x, value:%x\n", node->key, node->value);
node = node->next;
i++;
} while (node != temp);
return i;
}
//遍歷葉節點,可以傳入一個函數進行處理
int radix_tree_traversal_fun(radix_tree_t* t, void(*fun)(uint32,uint32))
{
int i = 0;
radix_leafnode_t* temp = last_leafnode, * node = last_leafnode;
do {
printf("key:%x, value:%x\n", node->key, node->value);
fun(node->key,node->value);
node = node->next;
i++;
} while (node != temp);
return i;
}