B树一个Node可以有N个key, N+1个下级Node, 二叉树就是简化版,一个key两个下级node
2-3树和2-3-4树的区不大,2-3树在插入时先找到叶子节点(没有子节点),然后插入,过程中如果已经是3Node(2 key)就分裂,向上冒泡,一直可能冒泡到顶上。
2-3-4树则在向下找叶子节点时就做调整,把4Node(3 key)提前分裂掉,为下级节点腾出空间,所以叶子节点插入后不会不停向上冒泡。
2-3-4树冗余更大,如果不提前分裂就是2-3树
红黑树是2-3-4树的2节点表示,采用左倾和旋转来简化和冒泡,Rober Segwick的ppt很经典
B+树感觉都是数据库中数据和索引的关系。索引可以没有,有了是用来加速某种查找。
在数据增删时索引维护时个问题。
顺便提下skip list, 对排序好的数据提取N个做索引,再对N个做同样采样索引,重复向上。对于大量数据很好理解,也很容易实现。索引和数据分开。
2-3树删除算法比较复杂,这里没实现。仅仅实现了插入和搜索,测试结果:
E A R C H X M P L
A C E H L M P R X
(A
C)
(E)
(H
L)
(M)
(P)
(R)
(X)
16 7 15 15 18 3 6 15 5 11 9 12 7 10 19 18 12 14 2 12
2 3 5 6 7 9 10 11 12 14 15 16 18 19
(2)
(3
(5)
6)
(7)
(9
(10)
(11)
(12
14)
15)
(16)
(18)
(19)
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <assert.h>
#include <string.h>
typedef int T;
typedef struct TreeNodeT {
T v; //value left
T v2; //value right
int twins;
struct TreeNodeT *up;
struct TreeNodeT *left;
struct TreeNodeT *center; //center if twins node
struct TreeNodeT *right;
} TreeNode;
typedef int Callback(TreeNode *node, int n, int level, void *ctx); //return stop or not
TreeNode *tree_del(TreeNode *node, T v); //TODO
TreeNode *tree_top(TreeNode *e) {
TreeNode *top = NULL;
while (e && e->up)
top = e->up;
return top;
}
int tree_callback_locate(TreeNode *node, int n, int level, void *ctx) {
T v = n == 0 ? node->v : node->v2;
T t = (T) ctx;
return v == t;
}
int tree_callback_verify(TreeNode *node, int n, int level, void *ctx) {
assert(ctx);
T v = n == 0 ? node->v : node->v2;
T *last = (T *) ctx;
assert(v > *last);
*last = v;
return 0;
}
int tree_callback_print_h(TreeNode *node, int n, int level, void *ctx) {
printf("%d ", n == 0 ? node->v : node->v2);
return 0;
}
int tree_callback_print_hc(TreeNode *node, int n, int level, void *ctx) {
printf("%c ", n == 0 ? node->v : node->v2);
return 0;
}
int tree_callback_print_v(TreeNode *node, int n, int level, void *ctx) {
int i;
for (i = 0; i < level; ++i) {
printf("\t");
}
if (n == 0)
printf("(");
printf("%d", n == 0 ? node->v : node->v2);
if ((node->twins && n == 1) || !node->twins)
printf(")");
printf("\n");
return 0;
}
int tree_callback_print_vc(TreeNode *node, int n, int level, void *ctx) {
int i;
for (i = 0; i < level; ++i) {
printf("\t");
}
if (n == 0)
printf("(");
printf("%c", n == 0 ? node->v : node->v2);
if ((node->twins && n == 1) || !node->twins)
printf(")");
printf("\n");
return 0;
}
/* return stop or not */
int tree_walk(TreeNode *node, int level, Callback cb, void *ctx) {
if (node->left && tree_walk(node->left, level + 1, cb, ctx))
return 1;
if (cb(node, 0, level, ctx))
return 1;
if (node->twins) {
if (node->center && tree_walk(node->center, level + 1, cb, ctx))
return 1;
if (cb(node, 1, level, ctx))
return 1;
}
if (node->right && tree_walk(node->right, level + 1, cb, ctx))
return 1;
return 0;
}
static void tree_node_init_single(TreeNode* node, T v, TreeNode* left,
TreeNode* right) {
//shrink left to Single Node
node->v = v;
node->twins = 0;
node->v2 = 0;
node->left = left;
if (left)
left->up = node;
node->center = NULL;
node->right = right;
if (right)
right->up = node;
}
static TreeNode* tree_node_alloc(TreeNode* up, T v, TreeNode* left,
TreeNode* right) {
// new upper Single Node
TreeNode* node = (TreeNode*) calloc(sizeof(TreeNode), 1);
tree_node_init_single(node, v, left, right);
node->up = up;
return node;
}
static TreeNode *tree_node_insert(TreeNode *node, T v, TreeNode *left,
TreeNode *right);
static TreeNode *tree_node_split(TreeNode *node, T v1, T v2, T v3, //
TreeNode *n1, TreeNode *n2, TreeNode *n3, TreeNode *n4) {
TreeNode *left = node; //reuse node
//shrink left to Single Node
tree_node_init_single(left, v1, n1, n2);
//Create new right Single Node
TreeNode *right = tree_node_alloc(node->up, v3, n3, n4);
TreeNode *up = node->up;
if (up == NULL) { // new upper Single Node
up = tree_node_alloc(NULL, v2, left, right);
return up;
} else { //upper node exist, escalate
return tree_node_insert(up, v2, left, right);
}
}
/* insert v to up:
* if up is single, make it twins
* if up is twins, split
* return NULL if no new top tree node created;
*/
static TreeNode *tree_node_insert(TreeNode *node, T v, TreeNode *left,
TreeNode *right) {
if (!node->twins) { //Single node -> Twins
node->twins = 1;
if (v < node->v) {
node->v2 = node->v;
node->v = v;
node->left = left;
node->center = right;
} else {
node->v2 = v;
node->center = left;
node->right = right;
}
return NULL;
} else { //twins, must have 3 child, split and escalate the middle one
if (v < node->v) {
node = tree_node_split(node, v, node->v, node->v2, left, right,
node->center, node->right);
} else if (v < node->v2) {
node = tree_node_split(node, node->v, v, node->v2, node->left, left,
right, node->right);
} else {
node = tree_node_split(node, node->v, node->v2, v, node->left,
node->center, left, right);
}
return node;
}
}
static void tree_node_check(TreeNode* node) {
assert(node);
assert(
(node->left && node->right) || (node->left == NULL && node->right == NULL));
if (node->left)
assert(node->left->up == node);
if (node->center)
assert(node->center->up == node);
if (node->right)
assert(node->right->up == node);
}
/* NULL: v exists, no action */
static TreeNode *tree_search_leaf_add(TreeNode *node, T v) {
tree_node_check(node);
if (v == node->v || (node->twins && node->v2 == v))
return NULL;
if (node->left) { // has children, 2 or 3
if (v < node->v) //less than v
return tree_search_leaf_add(node->left, v);
if (node->twins && v < node->v2) //twins node
return tree_search_leaf_add(node->center, v);
else
return tree_search_leaf_add(node->right, v);
}
return node;
}
/* TreeNode grow strategy:
* 1. Grow up from leaf!
* 2. Single -> Twins, so each twins node must have 3 children
* 3. Twins -> 3 Single, so each new parent must have 2 children
* 4. left and right must exist!
* 5. if twins, center must exist!
*/
TreeNode *tree_add(TreeNode *tree, T v) {
if (tree == NULL)
return tree_node_alloc(NULL, v, NULL, NULL);
tree_node_check(tree);
TreeNode *leaf = tree_search_leaf_add(tree, v);
if (!leaf) //already exits on tree
return tree;
TreeNode *node = tree_node_insert(leaf, v, NULL, NULL);
return node ? node : tree;
}
void tree_test_number(int n, int random) {
TreeNode* t;
int i;
T last = 0;
T v;
for (i = 1; i <= n; ++i) {
v = random ? ((double) rand() * n) / RAND_MAX : i;
printf("%d ", v);
t = tree_add(t, v);
// tree_walk(t, 0, tree_callback_print_v, 0);
// printf("===================\n");
}
printf("\n");
tree_walk(t, 0, tree_callback_verify, &last);
tree_walk(t, 0, tree_callback_print_h, NULL);
printf("\n");
tree_walk(t, 0, tree_callback_print_v, 0);
}
void tree_test_chars() {
TreeNode *t = NULL;
int i;
T last = 0;
char c;
// http://blog.csdn.net/yang_yulei/article/details/26066409
char* str = "EARCHXMPL";
for (i = 0; i < strlen(str); ++i) {
c = str[i]; //random();
printf("%c ", c);
t = tree_add(t, c);
}
printf("\n");
tree_walk(t, 0, tree_callback_verify, &last);
tree_walk(t, 0, tree_callback_print_hc, NULL);
printf("\n");
tree_walk(t, 0, tree_callback_print_vc, NULL);
}
int main(int argc, char **argv) {
tree_test_chars();
tree_test_number(20, 1);
return EXIT_SUCCESS;
}
分享到:
相关推荐
标题 "2-3树的插入及删除操作源代码" 指向了关于数据结构中2-3树的实现细节,特别是涉及如何在这样的数据结构中执行插入和删除操作的关键算法。2-3树是一种自平衡的搜索树,它保证了任何节点的左子树和右子树的高度...
在这个场景中,我们关注的是C语言实现的FP-growth算法。C语言以其高效性和灵活性,成为实现这种算法的理想选择,尤其是在处理大数据量时。 首先,我们要了解FP-growth的基本原理。它是由Han、Pei和Jia在2000年提出...
### 红黑树——C语言实现 #### 红黑树简介 红黑树(Red-Black Tree)是一种自平衡二叉查找树,在计算机科学领域有着广泛的应用,尤其是在实现关联数组方面。作为一种高效的查找、插入与删除操作的数据结构,红黑树...
"C 语言算法集--超多C语言算法实现"是一个珍贵的资源库,包含了大量经典且实用的C语言实现的算法,对于学习者和开发者来说具有很高的参考价值。下面将详细探讨C语言中的关键算法类别及其重要性。 1. 排序算法:排序...
本压缩包“b+b-树c语言版”提供了C语言实现的B+树相关功能,包括创建、删除、查询和插入操作。以下是关于B+树及其C语言实现的详细知识。 **B+树简介** B+树(B Plus Tree)是一种自平衡的树,它的设计目的是为了...
数据结构---C语言描述-(耿国华)-高等教育出版社出版-课后习题答案 数据结构是计算机科学中一个基础课题,涉及到数据的存储、操作和管理。数据结构可以分为线性结构、树形结构、图状结构等多种类型,每种结构都有其...
在C语言实现B- B-树时,首先需要定义一个结构体来表示节点,包括键值、子节点指针以及指向数据的指针。接下来,我们需要实现以下关键函数: 1. **初始化**:创建根节点,通常为一个空节点。 2. **查找**:从根节点...
1. **M**: 定义为1,表示节点中键的最大数量为2*M = 2,因此这是一个2阶的B-树(即2-3树)。在实际应用中,M通常是一个较大的数值。 2. **结构体定义**: B-树的节点结构体`struct btnode`包括: - `int d`: 节点...
通过上述分析,我们可以看出`fp-growth的c实现`项目是利用C语言编写的一个数据挖掘工具,它实现了fp-growth算法,用于从`test.txt`数据集中挖掘频繁项集。项目中可能包括了数据预处理、fp树构建、频繁项集计算以及...
基于C语言实现了红黑树及用户测试程序源码+详细注释+exe执行程序.zip数据结构课程作业-基于C语言实现了红黑树及用户测试程序源码+详细注释+exe执行程序.zip数据结构课程作业-基于C语言实现了红黑树及用户测试程序...
本教程将深入探讨栈的概念以及如何使用C语言实现它。 栈是一种线性数据结构,它的主要操作包括压栈(push)和弹栈(pop)。压栈是在栈顶添加元素,而弹栈则是移除栈顶元素。除此之外,还有查看栈顶元素但不移除的...
通过阅读和理解这些代码,你可以深入学习k-means算法的C语言实现细节,同时也可以了解如何处理基因表达数据。这个实现可以帮助你理解数据聚类的基本原理,并且可以在其他领域如图像分割、市场细分等应用中进行类似的...
1. 采用类C语言定义相关的数据类型 3 2. 各模块的伪码算法 7 3. 函数的调用关系图 13 4. 调试分析 13 5. 测试结果 14 6. 源程序(带注释) 14 总 结 20 参考文献 20 附件Ⅰ 部分源程序代码 21 摘 要 哈夫曼编译码...
该资源中为【数据结构】专栏——C语言实现二叉树篇章中涉及到的代码 代码中包含以下内容: 1. 二叉树相关头文件: - 二叉链表的数据类型声明 - 链队列结点类型声明 - 链队列类型声明 - 二叉树基本功能(二叉树的...
1. **结构特性**:B-树是一种多路搜索树,每个节点可以有多个子节点,一般为2到32个。每个节点包含键值对,键用于排序,而对应的值则指向子节点。 2. **中间节点**:非叶节点不存储数据,只存储键和子节点指针,这...
根据给定的文件信息,以下是对B-树基本操作实现的相关知识点的详细解析: ### B-树概述 B-树是一种自平衡的树数据结构,它保持了数据的有序性,使得查找、插入和删除操作都非常高效。在数据库和文件系统中广泛应用...
红黑树是一种自平衡二叉查找树,由Rudolf Bayer在1972年提出,它的设计目标是在保持查询效率的同时,通过特定的规则...理解并熟练掌握红黑树的原理和C语言实现,对于提升编程技能和解决复杂问题的能力具有重要意义。
### 0-1背包问题分支界限法求解——C语言实现 #### 一、背景介绍 在计算机科学中,背包问题是一类优化问题的经典案例,它涉及到如何在满足一定约束条件下(例如背包的最大承重),从一系列物品中选择最优组合以达到...
本篇将详细探讨FP-Growth算法的C语言实现,包括其核心思想、数据结构以及如何利用C语言进行编程。 FP-Growth的核心在于频繁项集(Frequent Itemset)的发现和FP树(Frequent Pattern Tree)的构建。首先,我们需要理解...