通过引入结点度大于2的查找树,可以得到一种插入算法和删除算法都比AVL树简单的树结构,且这些算法的时间复杂性是O(logn)。这种树结构称为2-3树。2-3树的名字反映了2-3树具有如下性质:一棵2-3树中每个内部结点的度或者是2,或者是3。其中度为2的结点称为2结点,度为3的结点称为3结点。
定义:一棵2-3树(2-3 Tree)是一棵查找树,该查找树或者为空,或者满足如下性质:
1,每个内部结点或者是一个2结点,或者是一个3结点。一个2结点存放一个元素,而一个3结点存放两个元素。
2,令lchild和mchild表示2结点的两个儿子,datal表示该节点存放的元素,且datal.key是该元素的关键字。以lchild为根的子树中所有结点的关键字都小于datal.key,而以mchild为根的子树中所有结点的关键字都大于datal.key。
3,零lchild,mchild和rchild表示3结点的三个儿子,datal和datar表示该节点存放的左右两个元素,且datal.key < datar.key。以lchild为根的子树的所有结点的关键字都小于datal.key,以mchild为根的子树的所有结点的关键子都大于datal.key而小于datar.key,而以rchild为根的子树中所有结点的关键字都大于datar.key。
4,所有外部结点位于同一层。
2-3树的查询操作不用细说,实现比较容易,重点在于2-3树的插入和删除操作,2-3树的插入操作涉及结点拆分,删除操作涉及数据的转移(或者称为旋转吧)以及结点合并(三种情况的旋转以及三种情况的合并,详细见REF[1]的2-3树章节)等等操作。
具体的插入和删除的原理可以可以参考文章《2-3树删除和插入操作的小结》,后面的代码主要是对REF[1]中的算法的实现:
代码:
#include <iostream>
#include <stack>
using namespace std;
typedef struct Tree23Node * Tree23;
typedef struct Tree23Node {
int datal;
int datar;
Tree23 lchild,mchild,rchild;
} Tree23Node;
#define INT_MAX 0x3f3f3f3f
stack<Tree23> s;
int compare(int x, Tree23 t)
{
if (x < t->datal)
return 1;
else if (x > t->datar)
return 3;
else if ( x < t->datar && x > t->datal)
return 2;
else
return 4;
}
Tree23 createNode(int key)
{
Tree23 t = new Tree23Node;
t->datal = key;
t->datar = INT_MAX;
t->lchild = t->mchild = t->rchild = NULL;
return t;
}
void newRoot(Tree23 *root,int key,Tree23 midSub)
{
Tree23 t = createNode(key);
t->lchild = *root;
t->mchild = midSub;
*root = t;
}
bool isleaf(Tree23 root)
{
if (root && root->datal < INT_MAX && root->lchild == NULL &&
root->mchild == NULL && root->rchild == NULL)
return true;
return false;
}
Tree23 findNode(Tree23 root, int key)
{
Tree23 t = NULL;
while (root){
if (!isleaf(root))
s.push(root);
if (isleaf(root))
t = root;
switch (compare(key,root)) {
case 1: root = root->lchild;
break;
case 2: root = root->mchild;
break;
case 3: root = root->rchild;
break;
case 4: return NULL;
}
}
return t;
}
void put(Tree23 *root, int key,Tree23 q)
{
if (key < (*root)->datal){
(*root)->datar = (*root)->datal;
(*root)->datal = key;
(*root)->rchild = (*root)->mchild;
(*root)->mchild = q;
}
else {
(*root)->datar = key;
(*root)->rchild = q;
}
}
void split(Tree23 p,int *key,Tree23 *q)
{
Tree23 t = createNode(INT_MAX);
if (*key < p->datal) {
t->datal = p->datar;
/*swap *key and p->datal */
p->datar = *key;
*key = p->datal;
p->datal = p->datar;
/* set p->datar to non sense */
p->datar = INT_MAX;
}
else if (*key > p->datar) {
t->datal = *key;
*key = p->datar;
p->datar = INT_MAX;
}
else {
t->datal = p->datar;
p->datar = INT_MAX;
}
t->lchild = p->rchild;
p->rchild = NULL;
t->mchild = *q;
*q = t;
}
Tree23 del()
{
if (!s.empty()){
Tree23 t = s.top();
s.pop();
return t;
}
return NULL;
}
void insert23(Tree23 *root,int key)
{
Tree23 p,q,temp;
if (*root == NULL) {
/* tree is empty */
newRoot(root,key,NULL);
}
else {
/* insert into an empty tree */
p = findNode(*root,key);
if (p == NULL) {
cout<<"The key is currently in the tree."<<endl;
return;
}
q = NULL;
for(;;) {
if (p->datar == INT_MAX) {
/* two sub node */
put(&p,key,q);
break;
}
else {
/* three sub node */
split(p,&key,&q);
if ( p == *root) {
/* split the root */
newRoot(root,key,q);
break;
}
else
/* remove a node from stack */
p = del();
}
}
}
}
void visit(Tree23 T)
{
if (T->datar < INT_MAX) {
cout<<"("<<T->datal<<","<<T->datar<<") ";
}
else if (T->datal < INT_MAX) {
cout<<"("<<T->datal<<",) ";
}
else cout<<"(,) ";
}
void inOrder(Tree23 T)
{
if(T)
{
visit(T);
//cout<<endl;
if (T->lchild == NULL)
return;
cout<<"(";
inOrder(T->lchild);
cout<<",";
inOrder(T->mchild);
cout<<",";
inOrder(T->rchild);
cout<<")";
}
}
Tree23 search23(Tree23 root,int key)
{
while (root) {
s.push(root);
switch (compare(key,root)) {
case 1: root = root->lchild;
break;
case 2: root = root->mchild;
break;
case 3: root = root->rchild;
break;
case 4: return root;
}
}
return NULL;
}
Tree23 min23(Tree23 root)
{
while(root->lchild){
s.push(root);
root = root->lchild;
}
s.push(root);
return root;
}
void deletex(Tree23 t,int key)
{
/* delete key from node t */
if(key == t->datal){
/* delete first key */
if(t->datar < INT_MAX){
/* three sub node*/
t->datal = t->datar;
t->datar = INT_MAX;
}
else
/* two sub node */
t->datal = INT_MAX;
}
else
/* delete second key */
t->datar = INT_MAX;
}
void leftRotate(Tree23 &p,Tree23 &q,Tree23 &r)
{
p->datal = r->datal;
r->datal = q->datal;
q->datal = q->datar;
q->datar = INT_MAX;
p->mchild = q->lchild;
q->lchild = q->mchild;
q->mchild = q->rchild;
q->rchild = NULL;
}
void leftCombine(Tree23 &p,Tree23 &q,Tree23 &r)
{
p->datal = r->datal;
p->datar = q->datal;
p->mchild = q->lchild;
p->rchild = q->mchild;
delete q;
if (r->datar == INT_MAX){
/* r is two sub node*/
r->datal = INT_MAX;
r->mchild = NULL;
}
else{
r->datal = r->datar;
r->datar = INT_MAX;
r->mchild = r->rchild;
r->rchild = NULL;
}
}
void middleRotate(Tree23 &p,Tree23 &q,Tree23 &r)
{
p->datal = r->datal;
r->datal = q->datar;
q->datar = INT_MAX;
p->mchild = q->rchild;
q->rchild = NULL;
}
void middleCombine(Tree23 &p, Tree23 &q, Tree23 &r)
{
q->datar = r->datal;
q->rchild = p->lchild;
delete p;
if(r->datar < INT_MAX) {
r->datal = r->datar;
r->datar = INT_MAX;
r->mchild = r->rchild;
r->rchild = NULL;
}
else {
r->datal = INT_MAX;
r->mchild = NULL;
}
}
void rightRotate(Tree23 &p,Tree23 &q,Tree23 &r)
{
p->datal = r->datar;
r->datar = q->datar;
q->datar = INT_MAX;
p->mchild = q->rchild;
q->rchild = NULL;
}
void rightCombine(Tree23 &p,Tree23 &q,Tree23 &r)
{
q->datar = r->datar;
r->datar = INT_MAX;
q->rchild = p->lchild;
delete p;
r->rchild = NULL;
}
bool delete23(Tree23 *root, int key)
{
Tree23 t = search23(*root,key);
Tree23 p;
Tree23 r ;
Tree23 q = NULL;
if (t == NULL)
return false;
else{
if (!isleaf(t)){
if (t->datal == key){
p = min23(t->mchild);
t->datal = p->datal;
key = p->datal;
}
else{
p = min23(t->rchild);
t->datar = p->datal;
key = p->datal;
}
}
else
p = t;
deletex(p,key);
del();
for(;;){
if (p->datal == INT_MAX && p->datar == INT_MAX){
r = del();
if (r == NULL)
break;
if (r->lchild == p){
/* */
q = r->mchild;
if (q->datar < INT_MAX){
/* rotate when p is the left child of r */
leftRotate(p,q,r);
}
else{
/* combine when p is the left child of r*/
leftCombine(p,q,r);
}
}
else if (r->mchild == p) {
q = r->lchild;
if (q->datar < INT_MAX){
middleRotate(p,q,r);
}
else{
middleCombine(p,q,r);
}
}
else {
q = r->mchild;
if (q->datar < INT_MAX){
rightRotate(p,q,r);
}
else{
rightCombine(p,q,r);
}
}
p = r;
}
else
break;
}
if (p->datal == INT_MAX){
*root = p->lchild;
delete p;
}
}
}
int main()
{
Tree23 tree = NULL;
for(int i = 0; i < 11; i++){
insert23(&tree,i);
inOrder(tree);
cout<<endl;
cout<<"-----------------------------------------"<<endl;
}
insert23(&tree,8);
inOrder(tree);
cout<<endl;
cout<<"--------------------------------------------"<<endl;
while(!s.empty())
s.pop();
delete23(&tree,10);
inOrder(tree);
cout<<endl;
cout<<"--------------------------------------------"<<endl;
while(!s.empty())
s.pop();
delete23(&tree,9);
inOrder(tree);
cout<<endl;
cout<<"--------------------------------------------"<<endl;
while(!s.empty())
s.pop();
delete23(&tree,8);
inOrder(tree);
cout<<endl;
cout<<"--------------------------------------------"<<endl;
while(!s.empty())
s.pop();
delete23(&tree,7);
inOrder(tree);
cout<<endl;
cout<<"--------------------------------------------"<<endl;
while(!s.empty())
s.pop();
delete23(&tree,6);
inOrder(tree);
cout<<endl;
cout<<"--------------------------------------------"<<endl;
for(int i = 5;i >= 0; i--){
while(!s.empty())
s.pop();
delete23(&tree,i);
inOrder(tree);
cout<<endl;
cout<<"--------------------------------------------"<<endl;
}
}
测试结果:
Key = 0 inserted:
(0,)
---------------------------------------------------------------------
Key = 1 inserted:
(0,1)
---------------------------------------------------------------------
Key = 2 inserted:
(1,) ((0,) ,(2,) ,)
---------------------------------------------------------------------
Key = 3 inserted:
(1,) ((0,) ,(2,3) ,)
---------------------------------------------------------------------
Key = 4 inserted:
(1,3) ((0,) ,(2,) ,(4,) )
---------------------------------------------------------------------
Key = 5 inserted:
(1,3) ((0,) ,(2,) ,(4,5) )
---------------------------------------------------------------------
Key = 6 inserted:
(3,) ((1,) ((0,) ,(2,) ,),(5,) ((4,) ,(6,) ,),)
---------------------------------------------------------------------
Key = 7 inserted:
(3,) ((1,) ((0,) ,(2,) ,),(5,) ((4,) ,(6,7) ,),)
---------------------------------------------------------------------
Key = 8 inserted:
(3,) ((1,) ((0,) ,(2,) ,),(5,7) ((4,) ,(6,) ,(8,) ),)
---------------------------------------------------------------------
Key = 9 inserted:
(3,) ((1,) ((0,) ,(2,) ,),(5,7) ((4,) ,(6,) ,(8,9) ),)
---------------------------------------------------------------------
Key = 10 inserted:
(3,7) ((1,) ((0,) ,(2,) ,),(5,) ((4,) ,(6,) ,),(9,) ((8,) ,(10,) ,))
---------------------------------------------------------------------
The key is currently in the tree.
Key = 8 inserted:
(3,7) ((1,) ((0,) ,(2,) ,),(5,) ((4,) ,(6,) ,),(9,) ((8,) ,(10,) ,))
--------------------------------------------------------------------------
Key = 10 deleted:
(3,) ((1,) ((0,) ,(2,) ,),(5,7) ((4,) ,(6,) ,(8,9) ),)
--------------------------------------------------------------------------
Key = 9 deleted:
(3,) ((1,) ((0,) ,(2,) ,),(5,7) ((4,) ,(6,) ,(8,) ),)
--------------------------------------------------------------------------
Key = 8 deleted:
(3,) ((1,) ((0,) ,(2,) ,),(5,) ((4,) ,(6,7) ,),)
--------------------------------------------------------------------------
Key = 7 deleted:
(3,) ((1,) ((0,) ,(2,) ,),(5,) ((4,) ,(6,) ,),)
----------------------------------------------------------------------------
Key = 6 deleted:
(1,3) ((0,) ,(2,) ,(4,5) )
---------------------------------------------------------------------------
Key = 5 deleted:
(1,3) ((0,) ,(2,) ,(4,) )
---------------------------------------------------------------------------
Key = 4 deleted:
(1,) ((0,) ,(2,3) ,)
---------------------------------------------------------------------------
Key = 3 deleted:
(1,) ((0,) ,(2,) ,)
---------------------------------------------------------------------------
Key = 2 deleted:
(0,1)
---------------------------------------------------------------------------
Key = 1 deleted:
(0,)
---------------------------------------------------------------------------
Key = 0 deleted:
---------------------------------------------------------------------------
1,数据结构(C语言版) Ellis Horowitz等
2,http://blog.youkuaiyun.com/sumoyu/article/category/1054287
3,http://www.bkjia.com/Pythonjc/815204.html

本文介绍了2-3树的概念,这是一种插入和删除操作时间复杂性为O(logn)的数据结构。2-3树的内部节点度数为2或3,分为2结点和3结点。文章重点讨论了2-3树的插入和删除操作,包括结点拆分、数据转移和结点合并等,并提供了相关操作的代码实现。
3069

被折叠的 条评论
为什么被折叠?



