/* btrees.h */

/*

* 平衡多路树的一种重要方案。

* 在 1970 年由 R. Bayer 和 E. McCreight 发明。

*/

#define M 1

/* B 树的阶,即非根节点中键的最小数目。

* 有些人把阶定义为非根节点中子树的最大数目。

*/

typedef int typekey;

typedef struct btnode { /* B-Tree 节点 */

int d; /* 节点中键的数目 */

typekey k[2*M]; /* 键 */

char *v[2*M]; /* 值 */

struct btnode *p[2*M+1]; /* 指向子树的指针 */

} node, *btree;

/*

* 每个键的左子树中的所有的键都小于这个键,

* 每个键的右子树中的所有的键都大于等于这个键。

* 叶子节点中的每个键都没有子树。

*/

/* 当 M 等于 1 时也称为 2-3 树

* +----+----+

* | k0 | k1 |

* +-+----+----+---

* | p0 | p1 | p2 |

* +----+----+----+

*/

extern int btree_disp; /* 查找时找到的键在节点中的位置 */

extern char * InsValue; /* 与要插的键相对应的值 */

extern btree search(typekey, btree);

extern btree insert(typekey,btree);

extern btree delete(typekey,btree);

extern int height(btree);

extern int count(btree);

extern double payload(btree);

extern btree deltree(btree);

/* end of btrees.h */

/*******************************************************/

/* btrees.c */

#include <stdlib.h>

#include <stdio.h>

#include "btrees.h"

btree search(typekey, btree);

btree insert(typekey,btree);

btree delete(typekey,btree);

int height(btree);

int count(btree);

double payload(btree);

btree deltree(btree);

static void InternalInsert(typekey, btree);

static void InsInNode(btree, int);

static void SplitNode(btree, int);

static btree NewRoot(btree);

static void InternalDelete(typekey, btree);

static void JoinNode(btree, int);

static void MoveLeftNode(btree t, int);

static void MoveRightNode(btree t, int);

static void DelFromNode(btree t, int);

static btree FreeRoot(btree);

static btree delall(btree);

static void Error(int,typekey);

int btree_disp; /* 查找时找到的键在节点中的位置 */

char * InsValue = NULL; /* 与要插的键相对应的值 */

static int flag; /* 节点增减标志 */

static int btree_level = 0; /* 多路树的高度 */

static int btree_count = 0; /* 多路树的键总数 */

static int node_sum = 0; /* 多路树的节点总数 */

static int level; /* 当前访问的节点所处的高度 */

static btree NewTree; /* 在节点分割的时候指向新建的节点 */

static typekey InsKey; /* 要插入的键 */

btree search(typekey key, btree t)

{

int i,j,m;

level=btree_level-1;

while (level >= 0)

{

for(i=0, j=t->d-1; i<j; m=(j+i)/2, (key > t->k[m])?(i=m+1):(j=m));

if (key == t->k [ i ])

{

btree_disp = i;

return t;

}

if (key > t->k [ i ]) /* i == t->d-1 时有可能出现 */

i++;

t = t->p[ i ];

level--;

}

return NULL;

}

btree insert(typekey key, btree t)

{

level=btree_level;

InternalInsert(key, t);

if (flag == 1) /* 根节点满之后,它被分割成两个半满节点 */

t=NewRoot(t); /* 树的高度增加 */

return t;

}

void InternalInsert(typekey key, btree t)

{

int i,j,m;

level--;

if (level < 0) /* 到达了树的底部: 指出要做的插入 */

{

NewTree = NULL; /* 这个键没有对应的子树 */

InsKey = key; /* 导致底层的叶子节点增加键值+空子树对 */

btree_count++;

flag = 1; /* 指示上层节点把返回的键插入其中 */

return;

}

for(i=0, j=t->d-1; i<j; m=(j+i)/2, (key > t->k[m])?(i=m+1):(j=m));

if (key == t->k[ i ])

{

Error(1,key); /* 键已经在树中 */

flag = 0;

return;

}

if (key > t->k[ i ]) /* i == t->d-1 时有可能出现 */

i++;

InternalInsert(key, t->p[ i ]);

if (flag == 0)

return;

/* 有新键要插入到当前节点中 */

if (t->d < 2*M) /* 当前节点未满 */

{

InsInNode(t, i); /* 把键值+子树对插入当前节点中 */

flag = 0; /* 指示上层节点没有需要插入的键值+子树,插入过程结束 */

}

else /* 当前节点已满,则分割这个页面并把键值+子树对插入当前节点中 */

SplitNode(t, i); /* 继续指示上层节点把返回的键值+子树插入其中 */

}

/*

* 把一个键和对应的右子树插入一个节点中

*/

void InsInNode(btree t, int d)

{

int i;

/* 把所有大于要插入的键值的键和对应的右子树右移 */

for(i = t->d; i > d; i--)

{

t->k[ i ] = t->k[i-1];

t->v[ i ] = t->v[i-1];

t->p[i+1] = t->p[ i ];

}

/* 插入键和右子树 */

t->k[ i ] = InsKey;

t->p[i+1] = NewTree;

t->v[ i ] = InsValue;

t->d++;

}

/*

* 前件是要插入一个键和对应的右子树,并且本节点已经满

* 导致分割这个节点,插入键和对应的右子树,

* 并向上层返回一个要插入键和对应的右子树

*/

void SplitNode(btree t, int d)

{

int i,j;

btree temp;

typekey temp_k;

char *temp_v;

/* 建立新节点 */

temp = (btree)malloc(sizeof(node));

/*

* +---+--------+-----+-----+--------+-----+

* | 0 | ...... | M | M+1 | ...... |2*M-1|

* +---+--------+-----+-----+--------+-----+

* |<- M+1 ->|<- M-1 ->|

*/

if (d > M) /* 要插入当前节点的右半部分 */

{

/* 把从 2*M-1 到 M+1 的 M-1 个键值+子树对转移到新节点中,

* 并且为要插入的键值+子树空出位置 */

for(i=2*M-1,j=M-1; i>=d; i--,j--)

{

temp->k[j] = t->k[ i ];

temp->v[j] = t->v[ i ];

temp->p[j+1] = t->p[i+1];

}

for(i=d-1,j=d-M-2; j>=0; i--,j--)

{

temp->k[j] = t->k[ i ];

temp->v[j] = t->v[ i ];

temp->p[j+1] = t->p[i+1];

}

/* 把节点的最右子树转移成新节点的最左子树 */

temp->p[0] = t->p[M+1];

/* 在新节点中插入键和右子树 */

temp->k[d-M-1] = InsKey;

temp->p[d-M] = NewTree;

temp->v[d-M-1] = InsValue;

/* 设置要插入上层节点的键和值 */

InsKey = t->k[M];

InsValue = t->v[M];

}

else /* d <= M */

{

/* 把从 2*M-1 到 M 的 M 个键值+子树对转移到新节点中 */

for(i=2*M-1,j=M-1; j>=0; i--,j--)

{

temp->k[j] = t->k[ i ];

temp->v[j] = t->v[ i ];

temp->p[j+1] = t->p[i+1];

}

if (d == M) /* 要插入当前节点的正中间 */

/* 把要插入的子树作为新节点的最左子树 */

temp->p[0] = NewTree;

/* 直接把要插入的键和值返回给上层节点 */

else /* (d<M) 要插入当前节点的左半部分 */

{

/* 把节点当前的最右子树转移成新节点的最左子树 */

temp->p[0] = t->p[M];

/* 保存要插入上层节点的键和值 */

temp_k = t->k[M-1];

temp_v = t->v[M-1];

/* 把所有大于要插入的键值的键和对应的右子树右移 */

for(i=M-1; i>d; i--)

{

t->k[ i ] = t->k[i-1];

t->v[ i ] = t->v[i-1];

t->p[i+1] = t->p[ i ];

}

/* 在节点中插入键和右子树 */

t->k[d] = InsKey;

t->p[d+1] = NewTree;

t->v[d] = InsValue;

/* 设置要插入上层节点的键和值 */

InsKey = temp_k;

InsValue = temp_v;

}

}

t->d =M;

temp->d = M;

NewTree = temp;

node_sum++;

}

btree delete(typekey key, btree t)

{

level=btree_level;

InternalDelete(key, t);

if (t->d == 0)

/* 根节点的子节点合并导致根节点键的数目随之减少,

* 当根节点中没有键的时候,只有它的最左子树可能非空 */

t=FreeRoot(t);

return t;

}

void InternalDelete(typekey key, btree t)

{

int i,j,m;

btree l,r;

int lvl;

level--;

if (level < 0)

{

Error(0,key); /* 在整个树中未找到要删除的键 */

flag = 0;

return;

}

for(i=0, j=t->d-1; i<j; m=(j+i)/2, (key > t->k[m])?(i=m+1):(j=m));

if (key == t->k[ i ]) /* 找到要删除的键 */

{

if (t->v[ i ] != NULL)

free(t->v[ i ]); /* 释放这个节点包含的值 */

if (level == 0) /* 有子树为空则这个键位于叶子节点 */

{

DelFromNode(t,i);

btree_count--;

flag = 1;

/* 指示上层节点本子树的键数量减少 */

return;

}

else /* 这个键位于非叶节点 */

{

lvl = level-1;

/* 找到前驱节点 */

r = t->p[ i ];

while (lvl > 0)

{

r = r->p[r->d];

lvl--;

}

t->k[ i ]=r->k[r->d-1];

t->v[ i ]=r->v[r->d-1];

r->v[r->d-1]=NULL;

key = r->k[r->d-1];

}

}

else if (key > t->k[ i ]) /* i == t->d-1 时有可能出现 */

i++;

InternalDelete(key,t->p[ i ]);

/* 调整平衡 */

if (flag == 0)

return;

if (t->p[ i ]->d < M)

{

if (i == t->d) /* 在最右子树中发生了删除 */

i--; /* 调整最右键的左右子树平衡 */

l = t->p [ i ];

r = t->p[i+1];

if (r->d > M)

MoveLeftNode(t,i);

else if(l->d > M)

MoveRightNode(t,i);

else

{

JoinNode(t,i);

/* 继续指示上层节点本子树的键数量减少 */

return;

}

flag = 0;

/* 指示上层节点本子树的键数量没有减少,删除过程结束 */

}

}

/*

* 合并一个节点的某个键对应的两个子树

*/

void JoinNode(btree t, int d)

{

btree l,r;

int i,j;

l = t->p[d];

r = t->p[d+1];

/* 把这个键下移到它的左子树 */

l->k[l->d] = t->k[d];

l->v[l->d] = t->v[d];

/* 把右子树中的所有键值和子树转移到左子树 */

for (j=r->d-1,i=l->d+r->d; j >= 0 ; j--,i--)

{

l->k[ i ] = r->k[j];

l->v[ i ] = r->v[j];

l->p[ i ] = r->p[j];

}

l->p[l->d+r->d+1] = r->p[r->d];

l->d += r->d+1;

/* 释放右子树的节点 */

free(r);

/* 把这个键右边的键和对应的右子树左移 */

for (i=d; i < t->d-1; i++)

{

t->k[ i ] = t->k[i+1];

t->v[ i ] = t->v[i+1];

t->p[i+1] = t->p[i+2];

}

t->d--;

node_sum--;

}

/*

* 从一个键的右子树向左子树转移一些键,使两个子树平衡

*/

void MoveLeftNode(btree t, int d)

{

btree l,r;

int m; /* 应转移的键的数目 */

int i,j;

l = t->p[d];

r = t->p[d+1];

m = (r->d - l->d)/2;

/* 把这个键下移到它的左子树 */

l->k[l->d] = t->k[d];

l->v[l->d] = t->v[d];

/* 把右子树的最左子树转移成左子树的最右子树

* 从右子树向左子树移动 m-1 个键+子树对 */

for (j=m-2,i=l->d+m-1; j >= 0; j--,i--)

{

l->k[ i ] = r->k[j];

l->v[ i ] = r->v[j];

l->p[ i ] = r->p[j];

}

l->p[l->d+m] = r->p[m-1];

/* 把右子树的最左键提升到这个键的位置上 */

t->k[d] = r->k[m-1];

t->v[d] = r->v[m-1];

/* 把右子树中的所有键值和子树左移 m 个位置 */

r->p[0] = r->p[m];

for (i=0; i<r->d-m; i++)

{

r->k[ i ] = r->k[i+m];

r->v[ i ] = r->v[i+m];

r->p[ i ] = r->p[i+m];

}

r->p[r->d-m] = r->p[r->d];

l->d+=m;

r->d-=m;

}

/*

* 从一个键的左子树向右子树转移一些键,使两个子树平衡

*/

void MoveRightNode(btree t, int d)

{

btree l,r;

int m; /* 应转移的键的数目 */

int i,j;

l = t->p[d];

r = t->p[d+1];

m = (l->d - r->d)/2;

/* 把右子树中的所有键值和子树右移 m 个位置 */

r->p[r->d+m]=r->p[r->d];

for (i=r->d-1; i>=0; i--)

{

r->k[i+m] = r->k[ i ];

r->v[i+m] = r->v[ i ];

r->p[i+m] = r->p[ i ];

}

/* 把这个键下移到它的右子树 */

r->k[m-1] = t->k[d];

r->v[m-1] = t->v[d];

/* 把左子树的最右子树转移成右子树的最左子树 */

r->p[m-1] = l->p[l->d];

/* 从左子树向右子树移动 m-1 个键+子树对 */

for (i=l->d-1,j=m-2; j>=0; j--,i--)

{

r->k[j] = l->k[ i ];

r->v[j] = l->v[ i ];

r->p[j] = l->p[ i ];

}

/* 把左子树的最右键提升到这个键的位置上 */

t->k[d] = l->k[ i ];

t->v[d] = l->v[ i ];

l->d-=m;

r->d+=m;

}

/*

* 把一个键和对应的右子树从一个节点中删除

*/

void DelFromNode(btree t, int d)

{

int i;

/* 把所有大于要删除的键值的键左移 */

for(i=d; i < t->d-1; i++)

{

t->k[ i ] = t->k[i+1];

t->v[ i ] = t->v[i+1];

}

t->d--;

}

/*

* 建立有两个子树和一个键的根节点

*/

btree NewRoot(btree t)

{

btree temp;

temp = (btree)malloc(sizeof(node));

temp->d = 1;

temp->p[0] = t;

temp->p[1] = NewTree;

temp->k[0] = InsKey;

temp->v[0] = InsValue;

btree_level++;

node_sum++;

return(temp);

}

/*

* 释放根节点,并返回它的最左子树

*/

btree FreeRoot(btree t)

{

btree temp;

temp = t->p[0];

free(t);

btree_level--;

node_sum--;

return temp;

}

void Error(int f,typekey key)

{

if (f)

printf("Btrees error: Insert %d!\n",key);

else

printf("Btrees error: delete %d!\n",key);

}

int height(btree t)

{

return btree_level;

}

int count(btree t)

{

return btree_count;

}

double payload(btree t)

{

if (node_sum==0)

return 1;

return (double)btree_count/(node_sum*(2*M));

}

btree deltree (btree t)

{

level=btree_level;

btree_level = 0;

return delall(t);

}

btree delall(btree t)

{

int i;

level--;

if (level >= 0)

{

for (i=0; i < t->d; i++)

if (t->v[ i ] != NULL)

free(t->v[ i ]);

if (level > 0)

for (i=0; i<= t->d ; i++)

t->p[ i ]=delall(t->p[ i ]);

free(t);

}

return NULL;

}

/* end of btrees.c */

B-tree造价信息

市场价 信息价 询价
材料名称 规格/型号 市场价
(除税)
工程建议价
(除税)
行情 品牌 单位 税率 供应商 报价日期
平衡 J17F-16T DN20 查看价格 查看价格

盾安阀门

13% 浙江迪艾智控科技股份有限公司
平衡 J17F-16T DN50 查看价格 查看价格

盾安阀门

13% 浙江迪艾智控科技股份有限公司
平衡 J17F-16T DN25 查看价格 查看价格

盾安阀门

13% 浙江迪艾智控科技股份有限公司
平衡 J17F-16T DN40 查看价格 查看价格

盾安阀门

13% 浙江迪艾智控科技股份有限公司
平衡 530×70×40 查看价格 查看价格

达创

13% 河北达创体育器材有限公司
平衡 J17F-16T DN32 查看价格 查看价格

盾安阀门

13% 浙江迪艾智控科技股份有限公司
平衡臂路灯 LED 180W+180W H=10m+10m 查看价格 查看价格

济南三星灯饰

13% 贵州光明航专业照明有限公司
压差旁通平衡 800X-16Q DN50 查看价格 查看价格

盾安阀门

13% 浙江迪艾智控科技股份有限公司
材料名称 规格/型号 除税
信息价
含税
信息价
行情 品牌 单位 税率 地区/时间
平衡重式叉车 提升质量4t 查看价格 查看价格

台班 汕头市2012年3季度信息价
平衡重式叉车 提升质量4t 查看价格 查看价格

台班 汕头市2010年2季度信息价
平衡重式叉车 提升质量4t 查看价格 查看价格

台班 汕头市2008年4季度信息价
平衡重式叉车 提升质量4t 查看价格 查看价格

台班 汕头市2007年4季度信息价
平衡重式叉车 提升重量3t 查看价格 查看价格

台班 广州市2007年3季度信息价
平衡重式叉车 提升质量4t 查看价格 查看价格

台班 汕头市2007年3季度信息价
平衡重式叉车 提升重量3t 查看价格 查看价格

台班 广州市2007年9月信息价
平衡重式叉车 提升重量3t 查看价格 查看价格

台班 广州市2007年8月信息价
材料名称 规格/需求量 报价数 最新报价
(元)
供应商 报价地区 最新报价时间
AI算法训练 AI算法训练|25天 3 查看价格 广州市熹尚科技设备有限公司 广东   2021-07-16
AI算法训练 AI算法训练|60天 3 查看价格 浙江大华技术股份有限公司深圳分公司 广东   2021-03-31
客流算法授权 客流分析算法授权|109路 2 查看价格 广州天锐信息工程有限公司 全国   2021-05-31
人脸算法授权 人脸算法,按照接入路数收费,前端抓拍机数量|1000路 1 查看价格 广州帝视尼电子科技有限公司 广东   2019-10-30
500万高空抛物摄像机-算法 高空抛物算法|42路 1 查看价格 广州市熹尚科技设备有限公司 全国   2021-12-02
算法软件 /|1台 1 查看价格 广州市熹尚科技设备有限公司 广东  深圳市 2021-12-27
海康威视高空抛物算法软件系统 海康威视高空抛物算法软件系统|1项 1 查看价格 广州赛瑞电子有限公司 广东  深圳市 2022-08-12
人脸识别算法 1.包含算法系统和承载服务器;2.支持多达200台终端,最高可支撑2万用户量;3.提供web管理服务;4.识别日志可保持六个月;5.处理器:不低于Intel至强E3-1200;CPU频率:3.3|1台 1 查看价格 南京小牛智能科技有限公司 全国   2019-12-03

鉴于B-tree具有良好的定位特性,其常被用于对检索时间要求苛刻的场合,例如:

1、B-tree索引是数据库中存取和查找文件(称为记录或键值)的一种方法。

2、硬盘中的结点也是B-tree结构的。与内存相比,硬盘必须花成倍的时间来存取一个数据元素,这是因为硬盘的机械部件读写数据的速度远远赶不上纯电子媒体的内存。与一个结点两个分支的二元树相比,B-tree利用多个分支(称为子树)的结点,减少获取记录时所经历的结点数,从而达到节省存取时间的目的。

B-tree性能

B-tree有以下特性:

1、关键字集合分布在整棵树中;

2、任何一个关键字出现且只出现在一个结点中;

3、搜索有可能在非叶子结点结束;

4、其搜索性能等价于在关键字全集内做一次二分查找;

5、自动层次控制;

由于限制了除根结点以外的非叶子结点,至少含有M/2个儿子,确保了结点的至少利用率,其最低搜索性能为:

其中,M为设定的非叶子结点最多子树个数,N为关键字总数;

所以B-树的性能总是等价于二分查找(与M值无关),也就没有B树平衡的问题;

由于M/2的限制,在插入结点时,如果结点已满,需要将结点分裂为两个各占M/2的结点;删除结点时,需将两个不足M/2的兄弟结点合并。

B-tree平衡算法常见问题

  • 求教此圆柱里面箍筋B边的算法

    按11G新平法,保护层取20mm,那么圆箍筋的直径就是860mm,半径为430mm,8根纵筋把圆分成八等分,则每两点之间的圆心角为360/8=45°,下图中三角形的度数标注在图上,因此运用三角函数可以...

  • b6-174~176长度算法

    您好!您指的是混凝土内植筋的长度吗?这个长度就是根数和单根长度得到的啊!

  • 算法?

    短跑的就是计算150厚度,按其水平投影面积计算,包含一半的梯井调出的板应该是单独计算,计入在挑檐板中吧

B-tree中,每个结点包含:

1、本结点所含关键字的个数;

2、指向父结点的指针;

3、关键字;

4、指向子结点的指针;

对于一棵m阶B-tree,每个结点至多可以拥有m个子结点。各结点的关键字和可以拥有的子结点数都有限制,规定m阶B-tree中,根结点至少有2个子结点,除非根结点为叶子节点,相应的,根结点中关键字的个数为1~m-1;非根结点至少有[m/2]([],向上取整)个子结点,相应的,关键字个数为[m/2]-1~m-1。

另外还有一种与此类似的树结构叫B+树,像 Berkerly DB , sqlite , mysql 数据库都使用了B+树算法处理索引。

B+和B-(即B)是因为每个结点上的关键字不同。一个多一个,一个少一个。

对于B+树,其结点结构与B-tree相同,不同的是各结点的关键字和可以拥有的子结点数。如m阶B+树中,每个结点至多可以拥有m个子结点。非根结点至少有[m/2]个子结点,而关键字个数比B-tree多一个,为[m/2]~m。

这两种处理索引的数据结构的不同之处:

1。B树中同一键值不会出现多次,并且它有可能出现在叶结点,也有可能出现在非叶结点中。而B+树的键一定会出现在叶结点中,并且有可能在非叶结点中也有可能重复出现,以维持B+树的平衡。

2。因为B树键位置不定,且在整个树结构中只出现一次,虽然可以节省存储空间,但使得在插入、删除操作复杂度明显增加。B+树相比来说是一种较好的折中。

3。B树的查询效率与键在树中的位置有关,最大时间复杂度与B+树相同(在叶结点的时候),最小时间复杂度为1(在根结点的时候)。而B+树的时间复杂度对某建成的树是固定的。

B-tree平衡算法文献

边坡稳定性计算极限平衡计算法的园弧形计算法 边坡稳定性计算极限平衡计算法的园弧形计算法

格式:pdf

大小:433KB

页数: 3页

评分: 4.8

边坡稳定性计算极限平衡计算法的园弧形计算法

立即下载
边坡稳定性计算极限平衡计算法的平面形计算法 边坡稳定性计算极限平衡计算法的平面形计算法

格式:pdf

大小:433KB

页数: 3页

评分: 4.5

边坡稳定性计算极限平衡计算法的平面形计算法

立即下载
B-tree相关推荐
  • 相关百科
  • 相关知识
  • 相关专栏