可以运行。设计了测试用例覆盖了所有的情况,测试后结果正确。
2-3树具体的讲解请看文档,文档是东南大学邓建明老师上课使用的。
测试插入{11,22,34,42,6,3,28,24,36 }
删除28:
删除36:
//f.h
#include <stdio.h>
#include <malloc.h>
#define NUM 10
#define INTERIOR 0
#define LEAF 1
#define FALSE 0
#define TRUE 1
typedef struct Node//节点
{
int type;
int key;
int low2;
int low3;
struct Node * son1;
struct Node * son2;
struct Node * son3;
}TreeNode,*BiTree;
typedef struct sNode
{
struct sNode *preNode;
BiTree pTree;
}StackNode, *BiStack;
typedef struct stackn
{
BiStack head;
BiStack tail;
}Stacks,*Stack;
Stack stack;
void push(BiTree bt){
BiStack bs=(BiStack)malloc(sizeof(StackNode));
bs->preNode=stack->head;
bs->pTree=bt;
stack->head=bs;
}
BiTree pop(){
if (stack->head == stack->tail)
{
return NULL;
}
BiTree bt=stack->head->pTree;
BiStack bs=stack->head;
if (bs!=stack->tail)
{
stack->head=bs->preNode;
}
free(bs);
return bt;
}
void clean(){
while(stack->head!=stack->tail){
BiStack tmp=stack->head;
stack->head=stack->head->preNode;
free(tmp);
}
}
BiTree createNode(int type,int key){
BiTree t=(BiTree)malloc(sizeof(TreeNode));
t->type=type;
t->low2=t->low3=0;
t->son1=t->son2=t->son3=NULL;
t->key=key;
return t;
}
/************************************************************************/
/*
input:
x : the leaf node to insert
tp : the tree or the sun tree x will insert to
pback: : null - the function is complete. if it is not null, it means
a bother node of tp, it is created in the function because
tp has three sun node,so the function created it to stored
new node;It is used for father node(out function) to coordinate
the tree;
the node is right to tp
output:
lowBack: it is the least key number of the nodes of pback;
*/
/************************************************************************/
int addson(BiTree x,BiTree* tp_point,BiTree *pBack){
BiTree tp=*tp_point;
int low_back=0;
if (tp->type == LEAF)
{
if (tp->key > x->key)
{
BiTree tmp=x;
x=tp;
(*tp_point)=tmp;
}
*pBack=x;
return (*pBack)->key;
}
//tp node is a interior node
int child;//it means which child node to insert;
BiTree tp_next;
if (x->key < tp->low2)
{
child =1;
tp_next=tp->son1;
}
else if (x->key <tp->low3 || (tp->low3 ==0&&tp->son3 == NULL))
{
child =2;
tp_next=tp->son2;
}
else
{
child =3;
tp_next=tp->son3;
}
BiTree pNewBack=NULL;
//set the tp_next as the tree to insert
//iterate the function until dealing with the leaf node
int low_number=addson(x,&tp_next,&pNewBack);
if (pNewBack != NULL)
{
if (tp->son3 == NULL)//if tp only have two child node, the new node which is create in the iteration function can be stored by tp node
{
if (child ==1)
{
tp->son3=tp->son2;
tp->son2=pNewBack;
tp->son1=tp_next;//tp_next is a pointer who point to the node/tree to insert
tp->low3=tp->low2;
tp->low2=low_number;
}
else//child == 2
{
tp->son3=pNewBack;
tp->son2=tp_next;
tp->low3=low_number;
}
}
else{
//tp have three child node so a new interior node(tp's right bother) should be create to store the new child node
*pBack=createNode(INTERIOR,0);
if (child ==1)
{
(*pBack)->son1=tp->son2;
(*pBack)->son2=tp->son3;
tp->son2=pNewBack;
tp->son1=tp_next;
tp->son3=NULL;
(*pBack)->low2=tp->low3;
low_back=tp->low2;
tp->low2=low_number;
tp->low3=0;
}
else if (child == 2)
{
(*pBack)->son1=pNewBack;
(*pBack)->son2=tp->son3;
tp->son2=tp_next;
tp->son3=NULL;
(*pBack)->low2=tp->low3;
tp->low3=0;
low_back=low_number;
}
else
{
//child ==3
(*pBack)->son1=tp_next;
(*pBack)->son2=pNewBack;
tp->son3=NULL;
(*pBack)->low2=low_number;
low_back=tp->low3;
tp->low3=0;
}
}
}
return low_back;
}
void insert(int key,BiTree *ts){
BiTree tree=*ts;
BiTree x=createNode(LEAF,key);
if (tree == NULL)//如果2-3树为空树
{
*ts=x;
return;
}
BiTree tp=tree;
BiTree pBack=NULL;
int low_number=addson(x,&tp,&pBack);
if (pBack!=NULL)
{
//create a new interior node used as the new tree node
BiTree newHead=createNode(INTERIOR,0);
newHead->low2=low_number;
newHead->son1=tp;
newHead->son2=pBack;
*ts=newHead;
}
return;
}
/************************************************************************/
/*
find the node to delete by key.On the same time,stack will store the router of nodes which have been searched.
intup:
key : the key of the node which is supposed to delete
tree : the tree to search for the node to delete
p : point to a node whose low2 or low3 equal to the key to delete
output:
if a node is searched successfully,return true;otherwise return false;
*/
/************************************************************************/
bool find_node(int key,BiTree tree,BiTree *p){
if (tree==NULL)
{
return false;
}
push(tree);
if (tree->type == LEAF)
{
if (tree->key == key)
{
return true;
}
else
{
return false;
}
}
if (key==tree->low2 || key ==tree->low3)
{
*p=tree;
}
if (key<tree->low2)
{
find_node(key,tree->son1,p);
}
else if (key == tree->low2 || key<tree->low3||tree->low3==0)
{
find_node(key,tree->son2,p);
}
else{
find_node(key,tree->son3,p);
}
}
void changePpoint(BiTree a,BiTree p,int key){
if (p->low2==a->key)
{
p->low2=key;
}else{
p->low3=key;
}
}
int getLeastKey(BiTree t){
if (t->type==INTERIOR)
{
return getLeastKey(t->son1);
}else{
return t->key;
}
}
void deleteNode(BiTree *a_pointer,BiTree *f_pointer,BiTree *ff_pointer,BiTree p,BiTree *t_pointer){
BiTree a=*a_pointer;
printf("delete node begin! ");
printf("node:%d %d %d %d\n",a->key,a->low2,a->low3,a->type);
BiTree f=*f_pointer;
BiTree ff=*ff_pointer;
BiTree tLeft=NULL;
BiTree tRight=NULL;
int fchild=0;
int achild=0;
if (a==f->son1)
{
achild=1;
}
else if (a==f->son2)
{
achild=2;
}
else{
achild=3;
}
if (f->low3!=0)//father node have three child node;
{
if (a==f->son3)
{
f->son3=NULL;
f->low3=0;
free(a);
}
else if (a==f->son2)
{
f->low2=f->low3;
f->low3=0;
f->son2=f->son3;
f->son3=NULL;
free(a);
}
else if (a==f->son1)
{
if (a->type==LEAF&&p!=NULL)
{
changePpoint(a,p,f->low2);
}
f->low2=f->low3;
f->low3=0;
f->son1=f->son2;
f->son2=f->son3;
f->son3=NULL;
free(a);
}
else
{
printf("err:a不是f的子节点。\n");
}
}
else{//father node have two child node,a =1,2
BiTree b=NULL;
if (achild ==1)
{
b=f->son2;
}
else{
b=f->son1;
}
if (ff==NULL)//f is the root node
{
*t_pointer=b;
free(a);
free(f);
return;
}
if (f==ff->son1)
{
tRight=ff->son2;
fchild=1;
}
else if (f==ff->son2)
{
tLeft=ff->son1;
tRight=ff->son3;
fchild=2;
//ff->low2=getLeastKey(f);
}
else if (f == ff->son3)
{
tLeft=ff->son2;
fchild=3;
//ff->low3=getLeastKey(f);
}
else{
printf("err1:f not a child node of ff!\n");
}
//获得了父节点左右的分支,开始根据四种情况处理
if (tLeft!=NULL&&tLeft->low3!=0)
{//父节点由一个兄弟节点在左边,并且有三个子节点. done!
f->son2=b;
f->son1=tLeft->son3;
tLeft->son3=NULL;
if (a->type=LEAF&&a->key<b->key&&p!=NULL)
{
changePpoint(a,p,tLeft->low3);
}
int tmp=0;
if (fchild==2)
{
tmp=ff->low2;
ff->low2=tLeft->low3;
}
else{
tmp=ff->low3;
ff->low3=tLeft->low3;
}
if (achild=2)//如果a是父节点的第二个孩子,则b为第一个孩子,将b改为f的第二个字孩子以后,可以从ff中获得b的最小节点值。
{
f->low2=tmp;
}
tLeft->low3=0;
free(a);
}
else if (tRight!=NULL&&tRight->low3!=0)
{
f->son1=b;
f->son2=tRight->son1;
tRight->son1=tRight->son2;
tRight->son2=tRight->son3;
tRight->son3=NULL;
if (a->type=LEAF&&a->key<b->key&&p!=NULL)
{
changePpoint(a,p,b->key);
}
int tmp=0;
if (fchild==1)
{
tmp=ff->low2;
ff->low2=tRight->low2;
}else{
tmp=ff->low3;
ff->low3=tRight->low2;
}
f->low2=tmp;
if (tmp!=getLeastKey(f->son2))
{
printf("err:not equal to getLeastKey:2~");
}
//f->low2=getLeastKey(f->son2);
tRight->low2=tRight->low3;
tRight->low3=0;
free(a);
}
else if (tLeft!=NULL)//左侧兄弟节点有两个儿子
{
tLeft->son3=b;
if (achild==2)//修改tleft->low3
{
int tmp=0;
if (fchild==2)
{
tmp=ff->low2;
}
else{
tmp=ff->low3;
}
tLeft->low3=tmp;
}
else{
tLeft->low3=f->low2;
}
*a_pointer=*f_pointer;
*f_pointer=*ff_pointer;
BiTree bitmp=pop();
*ff_pointer=bitmp;
free(a);
deleteNode(a_pointer,f_pointer,ff_pointer,p,t_pointer);
}
else{//右侧兄弟节点有两个儿子
tRight->son3=tRight->son2;
tRight->son2=tRight->son1;
tRight->son1=b;
if (a->type=LEAF&&a->key<b->key&&p!=NULL)
{
changePpoint(a,p,b->key);
}
tRight->low3=tRight->low2;
if (fchild==1)
{
tRight->low2=ff->low2;
}else{
tRight->low2=ff->low3;
}
*a_pointer=*f_pointer;
*f_pointer=*ff_pointer;
BiTree bitmp=pop();
*ff_pointer=bitmp;
free(a);
deleteNode(a_pointer,f_pointer,ff_pointer,p,t_pointer);
}
}
//删除节点的父节点的对于该节点的low信息不需要使用
}
int deletes(int key,BiTree *t){
BiTree tree=*t;
BiTree p=NULL;//point to a node whose low2 or low3 equal to the key to delete
clean();
if (tree==NULL||!find_node(key,tree,&p))
{
return FALSE;
}
if (tree->type=LEAF&&tree->key == key)
{
free(tree);
*t=NULL;
}
BiTree a=pop();//the LEFT node
BiTree f=pop();//father node
BiTree ff=pop();//father node 's father node
deleteNode(&a,&f,&ff,p,t);
return TRUE;
}
//main.cpp
#include "f.h"
void main(){
stack=(Stack)malloc(sizeof(Stacks));
stack->tail=(BiStack)malloc(sizeof(StackNode));
stack->tail->preNode=NULL;
stack->tail->pTree=NULL;
stack->head=stack->tail;
//for the delete function
BiTree t=NULL;//指向2-3树根节点
int inputs=1;
int input_set[10]={11,22,34,42,6,3,28,24,36,9};
for (int i=0;i<10;i++)
{
insert(input_set[i],&t);
}
/*
while (inputs!=0)
{
printf("\n请输入一个正整数插入到2-3树中:");
scanf("%d",&inputs);
if (inputs!=0)
{
insert(inputs,&t);
}
}*/
int key=-1;
int key_set[9]={28,36,24,34,6,3,22,42,11};
deletes(11,&t);
/*
for (int i=0;i<6;i++)
{
if (i==14)
{
int sss=0;
}
if (!deletes(key_set[i],&t))
{
printf("there is no node in the tree you want to delete");
}
}
/*
while(key!=0){
printf("\n请输入要删除节点的key值:");
scanf("%d",&key);
if (!deletes(key,&t))
{
printf("there is no node in the tree you want to delete");
}
}*/
int s;
}
- 大小: 18.9 KB
- 大小: 22.7 KB
- 大小: 18.5 KB
分享到:
相关推荐
2-3树是B树的一种特殊形式,它在查找、插入和删除等操作中保持了数据的有序性,同时通过内部节点的2个或3个子节点来提高平衡性能。以下将详细介绍2-3树的概念、特性、操作以及在实际中的应用。 1. **2-3树的概念** ...
在这个“B-树的源代码”项目中,开发者使用C++语言实现了B-树的基本操作,包括构造、查找、插入和删除节点。C++是一种广泛应用的面向对象编程语言,具有高效和灵活的特点,适合编写这种底层数据结构的代码。 B-树的...
B-树(Balanced Tree)和B+树是两种常见的自平衡的多路搜索树,广泛应用于数据库和文件系统中,以优化大容量数据的访问效率。这两种数据结构都是为了在磁盘等慢速存储设备上实现高效的查找、插入和删除操作。 B-树...
B-树(B-tree)是一种自平衡的树数据结构,特别适用于大型数据库和文件系统,因为它能够保持数据有序,便于快速查找、插入和删除操作。在本项目中,我们将深入探讨B- B-树(通常指的是B-树或B+树)的实现,并以C语言...
通过分析和理解这个源代码,开发者不仅可以定制SQLite3的行为,还可以深入学习数据库引擎的工作原理,如查询计划的生成、B树数据结构的实现、事务管理等。这对于数据库开发、软件工程以及嵌入式系统的开发者来说,都...
在给定的压缩包文件"2-3-tree-master"中,很可能包含了C++实现2-3树的源代码。这个代码库可能包括了节点类的定义、插入、查找和删除等操作的实现,以及相关的测试用例,帮助用户理解和学习2-3树的工作原理。 通过...
3. **平衡性质**:B-树的高度保持较低,确保查找、插入和删除操作的效率,时间复杂度接近O(log n)。 4. **叶子节点**:所有叶子节点都通过指针链相连,便于顺序遍历所有数据。 **B+树(B+Tree)** 1. **扩展B-树**...
在"rbtree-master"这个压缩包中,很可能包含了红黑树的C语言实现源代码,包括数据结构定义、插入、删除、查找等操作的函数,以及可能的测试用例和示例。通过学习和理解这些源代码,你可以深入了解红黑树的内部工作...
数据结构是计算机科学中的核心课程,它...KCSJ文件很可能是你的源代码或文档,对于学习和参考会有很大帮助。在实际开发中,结合数据库理论,B-树还可以应用于更复杂的数据索引场景,例如数据库的主键索引和区间查询。
在压缩包内的文件“140201021022张瑞强”中,很可能是包含了C语言实现的源代码。通过阅读和理解这些代码,你可以更深入地了解B+树的内部工作机制,以及如何在实际编程中应用这种数据结构。 总结,这个压缩包提供了...
使用《算法导论》中的2-3-4树策略,使得删除操作相对于仅使用2-3树更简单,因为2-3-4树允许节点有更多种类的状态,简化了调整树结构的过程。 总之,这个项目为理解和实践B-树提供了一个很好的实例,对于学习数据...
这个压缩包"算法-理论基础- 树- 树的存储结构(包含源程序).rar"提供了一个关于树的存储结构的理论基础和实际源代码,对于学习和理解树的实现具有很高的价值。 树的基本概念: 树是一种非线性的数据结构,由一个或...
2. **HashMap**: HashMap是基于哈希表实现的,提供了快速的平均时间复杂度为O(1)的插入、删除和查找操作。键和值可以是任何对象,但键必须是唯一的。 3. **TreeMap**: TreeMap基于红黑树数据结构,保持键的自然排序...
这个压缩包"sqlite-source-3_6_20"包含了SQLite在3.6.20版本时的完整源代码,这对于想要深入理解SQLite工作原理、进行定制开发或者在没有预编译库的情况下构建SQLite的人来说是宝贵的资源。 1. **btree.c**: 这个...
在这个"数据结构C++-源代码"的压缩包中,我们很可能会找到一系列用于实现各种数据结构的C++源代码。 1. **数组**:数组是最基本的数据结构,它是一个元素类型相同的集合,可以通过索引访问。在C++中,数组可以是一...
源代码可能会包括一维数组、二维数组的实现,以及关于数组操作的函数,如插入、删除、搜索等。 2. **链表**:链表是一种动态数据结构,每个元素(节点)包含数据和指向下一个节点的指针。链表分为单链表、双链表和...
1. 可能包含每个数据结构(如链表、栈、队列、树、图等)的创建、插入、删除、查找等操作的代码示例。 2. 各种排序和查找算法的实现,以及性能测试。 3. 指针在实际数据结构实现中的应用,如用指针实现链表的动态...
这个“红黑树C源代码”可能包含了红黑树节点结构定义、插入函数、删除函数、查找函数以及相关的平衡调整算法。通过阅读和理解源代码,可以深入学习红黑树的实现细节,对于理解和掌握数据结构与算法有着极大的帮助。...
1. `cdat`:这个文件可能是关于链表或树的数据结构实现,可能包含了创建、插入、删除等操作。链表是一种动态数据结构,而树则用于表示层次关系,如二叉搜索树、AVL树、红黑树等。 2. `bbknap.cpp`:这个名字暗示了...