B树,B+树原理及操作请点击这里

B树代码实现:


#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#define KeyType int
#define Record stringconst int m = 3;
using namespace std;
typedef struct BTNode {int keynum;             //节点当前关键字个数KeyType key[m + 1];       //关键字数组,key[0]未用struct BTNode* parent;  //双亲结点指针struct BTNode* ptr[m + 1]; //孩子结点指针数组Record* recptr[m + 1];BTNode() {keynum = 0;parent = NULL;for (int i = 0; i < m + 1; i++){ptr[i] = NULL;}}
}BTNode, * BTree;
BTree T = NULL;
typedef struct {BTree pt;               //指向找到的结点int i;                  //1<=i<=m,在结点中的关键字位序int tag;                //1:查找成功,0:查找失败
}result;                    //B树的查找结果类型
//3. 算法设计int Search(BTree p, int k) {  //在p->key[1..p->keynum]找kint i = 1;while (i <= p->keynum && k > p->key[i]) i++;return i;
}
void SearchBTree(BTree t, int k, result& r) {//在m阶B树t上查找关键字k,用r返回(pt,i,tag).//若查找成功,则标记tag=1,指针pt所指结点中第i个关键字等于k;//否则tag=0,若要插入关键字为k的记录,应位于pt结点中第i-1个和第i个关键字之间int i = 0, found = 0;BTree p = t, q = NULL;//初始,p指向根节点,p将用于指向待查找结点,q指向其双亲while (p != NULL && 0 == found) {i = Search(p, k);if (i <= p->keynum && p->key[i] == k) found = 1;else { q = p; p = p->ptr[i - 1]; }//指针下移}if (1 == found) {//查找成功,返回k的位置p及ir = { p,i,1 };}else {//查找不成功,返回k的插入位置q及ir = { q,i,0 };}
}
void split(BTree& q, int s, BTree& ap) {//将q结点分裂成两个结点,前一半保留在原结点,后一半移入ap所指新结点int i, j, n = q->keynum;ap = (BTNode*)malloc(sizeof(BTNode));//生成新结点ap->ptr[0] = q->ptr[s];for (i = s + 1, j = 1; i <= n; i++, j++) {    //后一半移入ap结点ap->key[j] = q->key[i];ap->ptr[j] = q->ptr[i];}ap->keynum = n - s;ap->parent = q->parent;for (i = 0; i <= n - s; i++)if (ap->ptr[i] != NULL) ap->ptr[i]->parent = ap;q->keynum = s - 1;
}
void newRoot(BTree& t, BTree p, int x, BTree ap) {//生成新的根结点t = (BTNode*)malloc(sizeof(BTNode));t->keynum = 1; t->ptr[0] = p; t->ptr[1] = ap; t->key[1] = x;if (p != NULL) p->parent = t;if (ap != NULL) ap->parent = t;t->parent = NULL;
}
void Insert(BTree& q, int i, int x, BTree ap) {//关键字x和新结点指针ap分别插到q->key[i]和q->ptr[i]int j, n = q->keynum;for (j = n; j >= i; j--) {q->key[j + 1] = q->key[j];q->ptr[j + 1] = q->ptr[j];}q->key[i] = x; q->ptr[i] = ap;if (ap != NULL) ap->parent = q;q->keynum++;
}
void InsertBTree(BTree& t, int k, BTree q, int i) {//在B树中q结点的key[i-1]和key[i]之间插入关键字k//若插入后结点关键字个数等于b树的阶,则沿着双亲指针链进行结点分裂,使得t仍是m阶B树int x, s, finished = 0, needNewRoot = 0;BTree ap;if (NULL == q) newRoot(t, NULL, k, NULL);else {x = k; ap = NULL;while (0 == needNewRoot && 0 == finished) {Insert(q, i, x, ap);//x和ap分别插到q->key[i]和q->ptr[i]if (q->keynum < m) finished = 1;//插入完成else {s = (m + 1) / 2; split(q, s, ap); x = q->key[s];if (q->parent != NULL) {q = q->parent; i = Search(q, x);//在双亲结点中查找x的插入位置}else needNewRoot = 1;}}if (1 == needNewRoot)//t是空树或者根结点已经分裂成为q和ap结点newRoot(t, q, x, ap);}
}
void Remove(BTree& p, int i)
{int j, n = p->keynum;for (j = i; j < n; j++) {p->key[j] = p->key[j + 1];p->ptr[j] = p->ptr[j + 1];}p->keynum--;
}
void Successor(BTree& p, int i) {//由后继最下层非终端结点的最小关键字代替结点中关键字key[i]BTree child = p->ptr[i];while (child->ptr[0] != NULL) child = child->ptr[0];p->key[i] = child->key[1];p = child;
}
void Restore(BTree& p, int i, BTree& T) {//对B树进行调整int j;BTree ap = p->parent;if (ap == NULL) //若调整后出现空的根结点,则删除该根结点,树高减1{T = p; //根结点下移p = p->parent;return;}BTree lc, rc, pr;int finished = 0, r = 0;while (!finished){r = 0;while (ap->ptr[r] != p) r++; //确定p在ap子树中的位置if (r == 0){r++;lc = NULL, rc = ap->ptr[r];}else if (r == ap->keynum){rc = NULL; lc = ap->ptr[r - 1];}else{lc = ap->ptr[r - 1]; rc = ap->ptr[r + 1];}if (r > 0 && lc != NULL && (lc->keynum > (m - 1) / 2))//向左兄弟借关键字{p->keynum++;for (j = p->keynum; j > 1; j--)//结点关键字右移{p->key[j] = p->key[j - 1];p->ptr[j] = p->ptr[j - 1];}p->key[1] = ap->key[r];//父亲插入到结点p->ptr[1] = p->ptr[0];p->ptr[0] = lc->ptr[lc->keynum];if (NULL != p->ptr[0])//修改p中的子女的父结点为p{p->ptr[0]->parent = p;}ap->key[r] = lc->key[lc->keynum];//左兄弟上移到父亲位置lc->keynum--;finished = 1;break;}else if (ap->keynum > r && rc != NULL && (rc->keynum > (m - 1) / 2)) //向右兄弟借关键字{p->keynum++;p->key[p->keynum] = ap->key[r]; //父亲插入到结点p->ptr[p->keynum] = rc->ptr[0];if (NULL != p->ptr[p->keynum]) //修改p中的子女的父结点为pp->ptr[p->keynum]->parent = p;ap->key[r] = rc->key[1]; //右兄弟上移到父亲位置rc->ptr[0] = rc->ptr[1];for (j = 1; j < rc->keynum; j++)  //右兄弟结点关键字左移{rc->key[j] = rc->key[j + 1];rc->ptr[j] = rc->ptr[j + 1];}rc->keynum--;finished = 1;break;}r = 0;while (ap->ptr[r] != p) //重新确定p在ap子树的位置r++;if (r > 0 && (ap->ptr[r - 1]->keynum <= (m - 1) / 2)) //与左兄弟合并//if(r>0) //与左兄弟合并{lc = ap->ptr[r - 1];p->keynum++;for (j = p->keynum; j > 1; j--) //将p结点关键字和指针右移1位{p->key[j] = p->key[j - 1];p->ptr[j] = p->ptr[j - 1];}p->key[1] = ap->key[r]; //父结点的关键字与p合并p->ptr[1] = p->ptr[0]; //从左兄弟右移一个指针ap->ptr[r] = lc;for (j = 1; j <= lc->keynum + p->keynum; j++) //将结点p中关键字和指针移到p左兄弟中{lc->key[lc->keynum + j] = p->key[j];lc->ptr[lc->keynum + j] = p->ptr[j];}if (p->ptr[0]) //修改p中的子女的父结点为lc{for (j = 1; j <= p->keynum; j++)if (p->ptr[p->keynum + j])   p->ptr[p->keynum + j]->parent = lc;}lc->keynum = lc->keynum + p->keynum;  //合并后关键字的个数for (j = r; j < ap->keynum; j++)//将父结点中关键字和指针左移{ap->key[j] = ap->key[j + 1];ap->ptr[j] = ap->ptr[j + 1];}ap->keynum--;pr = p; free(pr);pr = NULL;p = lc;}else //与右兄弟合并{rc = ap->ptr[r + 1];if (r == 0)r++;p->keynum++;p->key[p->keynum] = ap->key[r]; //父结点的关键字与p合并p->ptr[p->keynum] = rc->ptr[0]; //从右兄弟左移一个指针rc->keynum = p->keynum + rc->keynum;//合并后关键字的个数ap->ptr[r - 1] = rc;for (j = 1; j <= (rc->keynum - p->keynum); j++)//将p右兄弟关键字和指针右移{rc->key[p->keynum + j] = rc->key[j];rc->ptr[p->keynum + j] = rc->ptr[j];}for (j = 1; j <= p->keynum; j++)//将结点p中关键字和指针移到p右兄弟{rc->key[j] = p->key[j];rc->ptr[j] = p->ptr[j];}rc->ptr[0] = p->ptr[0]; //修改p中的子女的父结点为rcif (p->ptr[0]){for (j = 1; j <= p->keynum; j++)if (p->ptr[p->keynum + j])    p->ptr[p->keynum + j]->parent = rc;}for (j = r; j < ap->keynum; j++)//将父结点中关键字和指针左移{ap->key[j] = ap->key[j + 1];ap->ptr[j] = ap->ptr[j + 1];}ap->keynum--;//父结点的关键字个数减1pr = p;free(pr);pr = NULL;p = rc;}ap = ap->parent;if (p->parent->keynum >= (m - 1) / 2 || (NULL == ap && p->parent->keynum > 0))finished = 1;else if (ap == NULL) //若调整后出现空的根结点,则删除该根结点,树高减1{pr = T;T = p; //根结点下移free(pr);pr = NULL;finished = 1;}p = p->parent;}
}
void DeleteBTree(BTree& p, int i, BTree& T) {//删除B树上p结点的第i个关键字if (p->ptr[i] != NULL) {//若不是在最下层非终端结点Successor(p, i);//在Ai子树中找出最下层非终端结点的最小关键字替代kiDeleteBTree(p, 1, T);//转换为删除最下层非终端结点的最小关键字}else {//若是最下层非终端结点Remove(p, i);if (p->keynum < (m - 1) / 2)//删除后关键字个数小于(m-1)/2Restore(p, i, T);//调整B树}
}void show_Btree(BTree& p)
{if (p == NULL) { puts("B tree does not exist"); return; }bool have_child = false;printf("[");for (int i = 1; i <= p->keynum; i++){if (i == 1);else printf(" ");printf("%d", p->key[i]);}printf("]");for (int i = 0; i <= p->keynum; i++){if (p->ptr[i] != NULL){if (i == 0) printf("<");else printf(",");show_Btree(p->ptr[i]);have_child = true;}}if (have_child) printf(">");
}void show_Btree2(BTree& p, int deep)
{if (p == NULL) { return; }int i;for (i = 0; i < p->keynum; i++){show_Btree2(p->ptr[i], deep + 1);for (int i = 0; i < deep; i++){printf("\t");}printf("%d\n", p->key[i + 1]);}show_Btree2(p->ptr[i], deep + 1);}
void Destory(BTree& t)
{int i = 0;if (t != NULL){while (i < t->keynum){Destory(t->ptr[i]);free(t->ptr[i]);i++;}}free(t);t = NULL;
}
void creat_btree()
{T = new BTNode;T->keynum = 0;puts("New success");
}
void insert_keytype()
{puts("Enter an element to be inserted");KeyType temp;cin >> temp;result p;SearchBTree(T, temp, p);if (p.tag == 0){InsertBTree(T, temp, p.pt, p.i);puts("Insert success"); show_Btree(T);puts("");}else puts("The element is already in the B tree.");
}
void find_keytype()
{puts("Enter an element to find");KeyType temp;cin >> temp;result p;SearchBTree(T, temp, p);if (p.tag){puts("Find success");}else puts("Lookup failure");
}
void delete_keytype()
{puts("Enter an element to be deleted");KeyType temp;cin >> temp;result p;SearchBTree(T, temp, p);if (p.tag){DeleteBTree(p.pt, p.i, T);puts("Delete success"); show_Btree(T);puts("");}else puts("The element does not exist in the B tree.");
}int main()
{puts("*************************************************************************");puts("> File Name: d.cpp");puts("> Author: MentalOmega");puts("> Created Time: 2016.11.5 21:23:30");puts("> Reference material:");puts("http://blog.csdn.net/jesseshen/article/details/6643747");puts("http://www.cnblogs.com/vincently/p/4526560.html");puts("http://blog.csdn.net/quitepig/article/details/8041308");puts("*************************************************************************");int order = 0;while (order != 7){puts("---------------------------------------------------------------------");puts("Select menu");puts("1:Creat a new 3-B-tree");puts("2:Insert element");puts("3:Find element");puts("4:Delete element");puts("5:Print B-tree");puts("6:exit");cin >> order;switch (order){case 1: {Destory(T); creat_btree(); break; }case 2: {insert_keytype(); break; }case 3: {find_keytype(); break; }case 4: {delete_keytype(); break; }case 5: {show_Btree(T); puts(""); break; }case 6: {return 0; }}}return 0;
}

参考:https://blog.csdn.net/qq965194745/article/details/78323470

> 参考网站:
    http://blog.csdn.net/jesseshen/article/details/6643747
    http://www.cnblogs.com/vincently/p/4526560.html
    http://blog.csdn.net/quitepig/article/details/8041308

B树代码实现--C++相关推荐

  1. python树代码_浅析AST抽象语法树及Python代码实现

    在计算机科学中,抽象语法树(abstract syntax tree或者缩写为AST),或者语法树(syntax tree),是源代码的抽象语法结构的树状表现形式,这里特指编程语言的源代码.树上的每个 ...

  2. java兄弟_java实现兄弟孩子树代码

    树的表示方法很多,双亲儿子,双亲,儿子,儿子兄弟表示法. 但是用来表示树的最多的方式是儿子兄弟表示法. 第一,可以用来表示孩子节点不相同的树. 第二,不浪费存储空间. 一下贴出代码: ======== ...

  3. 爱情树代码python_love: 一缕青丝一缕魂,锦绳系命送爱人。

    爱情树 这是一棵网上流传了很久的爱情树. 2020.03.10,我搭建了属于自己的爱情树,修补了大量不规范的代码,加了自动循环播放背景音乐. 爱情树地址: 示例图: 应小伙伴们的需求,整理了下源码,提 ...

  4. extjs6.0 动态加载_Extjs入门之动态加载树代码

    Extjs动态加载树的实现代码,需要的朋友可以参考下. Extjs动态加载树,首先在数据库里面设计存放树信息的表 USE [KimiExtjs] GO /****** 对象: Table [dbo]. ...

  5. 统计学习方法第五章作业:ID3/C4.5算法分类决策树、平方误差二叉回归树代码实现

    ID3/C4.5算法分类决策树 import numpy as np import math class Node:def __init__(self,feature_index=None,value ...

  6. tire树代码示例和例题

    tire树 [模板]字典树 题目描述 给定 n n n 个模式串 s 1 , s 2 , - , s n s_1, s_2, \dots, s_n s1​,s2​,-,sn​ 和 q q q 次询问, ...

  7. php樱花许愿树代码_怪事笔记

    樱花许愿树(三) 发布于2016-08-22 09:47 "柔柔,你怎么了?柔柔?你醒醒啊!" 是谁?我,我在哪儿? "嗯--"睡梦中的苏依柔发出一串低声的呢喃 ...

  8. 爱情树代码python_Python表白爱情树

    from turtle import * from random import * from math import * import turtle import time def tree(n, l ...

  9. 爱情树代码的修改(MAC)

    1.首先下载到模版,我现在用的这个模版. 2.文件解压 . 3.修改后缀html为txt. 4.进入后可以修改网页名称/姓名/时间/表白语/背景音乐,这里给出相关位置. (1)网页名称,在开头部分.

最新文章

  1. server正式的环境性能测试nginx-php 指着寻求突破的表现
  2. Python3NumPy——数组(2)之数学空间与NumPy空间
  3. dio 上传文件报错_Vue+Element UI实现断点续传、分片上传、秒传
  4. 【视频课】图像分类最新内容来了(言有三录制6大理论部分讲解)
  5. about quartus, FPGA and verilog 琐记
  6. [原创]Toolbar setNavigationIcon无效
  7. dragon编译linux,在Linux系统中安装Alibaba Dragonwell8的方法
  8. 杭电1596find the safest road(spfa)
  9. linux平均负载什么意思_在Linux中什么是平均负载?
  10. jquery监听html状态,jquery监听页面刷新
  11. JSTL fmt 标签 使用
  12. css3弹性盒子+小程序布局
  13. Drools7.5.0教程-目录
  14. 浅谈内存分配方式以及堆和栈的区别
  15. 穿山甲广告。swift穿山甲广告40001报错
  16. 叁德悟带你认识四大名香
  17. uni-app web-view跳转自定义html
  18. Python match case结构化模式匹配
  19. 【C语言进阶】字符串函数模拟实现
  20. 实现基于XDP/eBPF的快速路由转发功能

热门文章

  1. Python选修课第一届Turtle绘图大赛田康林赵冰珂组
  2. git branch 相关命令
  3. Protel和Altium是什么关系?
  4. 荣耀全家桶框架插件(关联P30pro、Mate20、荣耀20pro等)
  5. 超低功耗研发-STM32L151C8T6芯片(三)RTC自动唤醒机制
  6. 起底币圈地下骗局:传销币、资金盘横行,百亿财富被黑手收割
  7. Linux软件集成开发环境
  8. 寄存器寻址和寄存器间接寻址的区别
  9. 级联选择器el-cascader处理复杂数据(四层、五层数据),回显部门以及部门下的人员
  10. 理解Javascript的正则表达式