radix的实现

  • 1.引言
  • 2.介绍
  • 3.实现
    • 如何插入数据

1.引言

我们知道,unoredered_map是一种查找时间复杂度o(1)的数据结构,经常用在数据查找相关的地方,但是在使用unordered_map进行数据查找时,hash冲突是一件令人很头疼的事情,因为hash冲突导致unordered_map的查找效率降低。radix就是一种适用于基于二进制表示的键值的查找树,在数据量增大的时候不会影响其查找效率。由于我在一个项目中发现使用unordered_map在处理大量数据的时候效率并不高,因此来学习radix,本文将介绍radix的原理,并将我所实现并用于项目的代码分享出来。

2.介绍

radix是一种基于前缀树的思想的适用于基于二进制表示的键值的查找树。用图来解释直观明了。

3.实现

在使用radix这种数据结构的时候,会涉及到多次申请空间的过程,unordered_map使用的时STL自己的allocator。我使用的是boost中pool的一个对象池,因为每次申请的对象都是一样大的。

如何插入数据

radix是一种很巧妙的数据结构(感觉想出来的人是个天才),并且很简单,难的地方可能就是这个插入数据部分。难点在于每次如何获取Key值的二进制位上的一位、两位或多位。这个视具体情况,为了不让整个树层数过深,我采用每次获取两二进制的方法来实现的。
话不多说,上代码

#define CHECK_BITS(key,pos) ((((unsigned int)(key))<<sizeof(int)*8-((pos)+1)*BITS)>>(sizeof(int)*8-BITS))

这行代码负责每次获取两位二进制的值。

#pragma once
#include<stdlib.h>
#include<stdio.h>
#include<iostream>
#include<boost\pool\pool.hpp>
#include<stddef.h>
using namespace std;#define RADIX_INSERT_VALUE_OCCUPY -1    //该节点已被占用
#define RADIX_INSERT_VALUE_SAME -2      //插入了相同的值
#define RADIX_DELETE_ERROR -3           //删除错误typedef int k_type;
typedef char* v_type;#define BITS 2
const int radix_tree_height = sizeof(k_type) * 8 / BITS;//树的高度
//返回key中由pos指定的位的值,位数由BITS指定,每次获取两位二进制的值
#define CHECK_BITS(key,pos) ((((unsigned int)(key))<<sizeof(int)*8-((pos)+1)*BITS)>>(sizeof(int)*8-BITS))
//基数树节点
struct radix_node_t {radix_node_t* child[4];//四个指向下层节点的指针数组,分别指向节点储存值为00 01 10 11的节点。radix_node_t* parent;//记录夫结点v_type value;//节点储存的值
};
//基数树头节点
struct radix_head {//根节点radix_node_t* root;//储存已分配但不在树中的节点(双向链表,这里储存其中的一个节点)size_t number;//存储目前有多少个存进来的节点。
};class radix
{public:radix():_pool(sizeof(radix_node_t)){t = (radix_head*)malloc(sizeof(radix_head));t->number = 0;t->root = (radix_node_t*)_pool.malloc();for (int i = 0; i < 4; i++)t->root->child[i] = nullptr;t->root->value = nullptr;}int insert(k_type key, v_type value){int i, temp;radix_node_t* node, *child;node=t->root;for (i = 0; i < radix_tree_height; i++) {//从低位开始获取每两位的值temp = CHECK_BITS(key, i);if (node->child[temp] == nullptr) {child = (radix_node_t*)_pool.malloc();if (!child)return NULL;//显示构造for (int i = 0; i < 4; i++)child->child[i] = nullptr;child->value = nullptr;child->parent = node;node->child[temp] = child;node = node->child[temp];}else {node = node->child[temp];}}//已经插入返回-2if (node->value == value)return RADIX_INSERT_VALUE_SAME;//插入节点有其他值返回-3if (node->value != nullptr)return RADIX_INSERT_VALUE_OCCUPY;node->value = value;//计数加1++t->number;return 0;}int Delete(k_type key){radix_node_t* tar = find(key);if (tar == nullptr){cout << "删除失败" << endl;return RADIX_DELETE_ERROR;//返回-3,删除失败,没有该数据}else{radix_node_t* par = tar->parent;//printf("真正删除%d\n", tar->value->_pageid);tar->value = nullptr;_pool.free(tar);--t->number;for (int i = 0; i < 4; i++){if (par->child[i] == tar){par->child[i] = nullptr;break;}}//printf("减少到%d个\n", t->number);}return 0;}void print(){radix_node_t* node = t->root;_radix_print(node);}radix_node_t* find(k_type key){int i = 0, temp;radix_node_t* node;node = t->root;while (node && i < radix_tree_height) {temp = CHECK_BITS(key, i++);node = node->child[temp];}if (node == nullptr||node->value==nullptr)return nullptr;return node;}
private:void _radix_print(radix_node_t* node){if (node == nullptr)return;if (node->value != nullptr)printf("%s\n", node->value);_radix_print(node->child[0]);_radix_print(node->child[1]);_radix_print(node->child[2]);_radix_print(node->child[3]);}
private:boost::pool<> _pool;radix_head* t;
};

一种高效查找树-radix的实现相关推荐

  1. 数据结构之平衡树:2-3查找树的介绍——16

    平衡树(AVL tree) 引入 之前学习的树,都不是平衡的,查找时需要一个一个往内比较,一个结点只储存一个值,数据量存储较大,树的深度会非常的深,导致数据查询时效率会十分的低,本次学习的平衡树就能解 ...

  2. 2-3查找树-树-数据结构和算法(Java)

    文章目录 1 概述 2 查找 3 插入 3.1 向2-结点中插入新键 3.2 向一个只含有一个3-结点的树中插入新键 3.3 向一个父结点为2-结点的3-结点中插入新键 3.4 向一个父结点为3-结点 ...

  3. 查找算法之平衡查找树

    前面介绍的算法在最坏的情况下还是很糟糕.这次会介绍一种二分查找树并能保证无论如何构造它,他的运行时间都是对数级别的.理想情况下我们希望能够保持二分查找树的平衡性.但是,在动态插入中保证树的完美平衡的代 ...

  4. 二叉搜索树的2层结点统计_植树节,程序猿种的那些树

    公历 3 月 12 日是一年一度的植树节.旨在宣传保护森林,并动员群众参加植树造林活动.说到树,程序猿们肯定不陌生,趁着这个植树节到来之时普及一下程序猿们经常遇见的树. 1. 二叉搜索树 定义 二叉搜 ...

  5. 数据结构—2-3树、2-3-4树、B树、B+树等多路查找树的原理详解

    详细介绍了多路查找树中的2-3树.2-3-4树.B树.B+树的概念的区别,以及它们的应用场景. 文章目录 1 多路查找树的概述 1.1 索引概述 1.2 多路查找树的引出 2 2-3树 2.1 2-3 ...

  6. HTTP协议漫谈 C#实现图(Graph) C#实现二叉查找树 浅谈进程同步和互斥的概念 C#实现平衡多路查找树(B树)...

    HTTP协议漫谈 简介 园子里已经有不少介绍HTTP的的好文章.对HTTP的一些细节介绍的比较好,所以本篇文章不会对HTTP的细节进行深究,而是从够高和更结构化的角度将HTTP协议的元素进行分类讲解. ...

  7. 笔试算法题(58):二分查找树性能分析(Binary Search Tree Performance Analysis)

    议题:二分查找树性能分析(Binary Search Tree Performance Analysis) 分析: 二叉搜索树(Binary Search Tree,BST)是一颗典型的二叉树,同时任 ...

  8. 平衡查找树C语言程序,树4. Root of AVL Tree-平衡查找树AVL树的实现

    对于一棵普通的二叉查找树而言,在进行多次的插入或删除后,容易让树失去平衡,导致树的深度不是O(logN),而接近O(N),这样将大大减少对树的查找效率.一种解决办法就是要有一个称为平衡的附加的结构条件 ...

  9. 数据结构树之二分查找树

    二叉查找树(Binary Search Tree),也称有序二叉树(ordered binary tree),排序二叉树(sorted binary tree),是指一棵空树或者具有下列性质的二叉树: ...

  10. 二分查找树性能分析(Binary Search Tree Performance Analysis)

    经典算法系(21)-二分查找树性能分析(Binary Search Tree Performance Analysis)https://www.douban.com/note/221942390/   ...

最新文章

  1. 5 Best User Interface Design Pattern Libraries
  2. PyQt5 技术篇-设置QComboBox下拉框默认值,获取下拉框当前选择的内容
  3. Codeforces Round #434 (Div. 2)【A、B、C、D】
  4. 学习Java编程equals()和hashCode()方法
  5. 【博士招生】卢森堡大学​SnT(CVI²)研究小组,DeepFake 检测领域
  6. Windows Server 2008 R2 Server Core文件操作命令
  7. TF-IDF算法-golang实现
  8. Linux内存分配器SLOB,深入理解Linux内核之SLOB分配器
  9. java+junit百科_JUnit介绍
  10. 服务器网络连接详细信息,Windows10怎么样查看网络连接详细信息
  11. python汉化界面_python如何设置中文界面
  12. 17、【易混淆概念集】第十一章1 项目风险 风险临界值 VS 风险承受力 风险管理流程 风险管理及变更流程 规划风险管理 识别风险
  13. c语言考试题库大一下学期基础,c语言考试题(全国c语言二级考试题库)
  14. simulink中不能改名_王者荣耀:万格改名教学,空白名、重复名、个性符号名改法!...
  15. Android多媒体添加软解码
  16. 猿辅导python编程老师面试_猿辅导辅导老师面试一系列的感受
  17. 如何在Dynamic CRM 2011中使用自定义Workflow
  18. 5.1声道转化为左右声道
  19. 旋转编码器的原理和使用方法
  20. 基于多时间尺度滚动优化的多能源微网双层调度模型

热门文章

  1. unity3D的FingerGestures插件详细说明
  2. 互联网老辛2022年3月上旬社群精华
  3. 太厉害了,终于有人能把Ansible讲的明明白白了,建议收藏
  4. php 中%3cspan%3e,vue实战(4)——网站统计之——友盟百度统计
  5. php内部网,php – WordPress内部网址重写是如何工作的?
  6. /etc/passwd,/etc/shadow文件详解,及密码复杂度设置
  7. Maxscript - 顶点法线修改脚本Normal Thief源码学习
  8. C语言知识体系框架图
  9. 计算机绘图综合训练大题,工程制图与计算机绘图综合实训报告汇编.doc
  10. java.util.concurrent.ThreadFactory 实例讲解