二叉查找树(binary search tree (BST))--算法导论示例

 二叉查找树(binary search tree (BST))--算法导论示例  

二叉查找树(Binary Search Tree),或者是一棵空树,或者是具有下列性质的二叉树:

   1. 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
   2. 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
   3. 它的左、右子树也分别为二叉排序树。

二叉排序树的查找过程和次优二叉树类似,通常采取二叉链表作为二叉排序树的存储结构。中序遍历二叉排序树可得到一个关键字的有序序列,一个无序序列可以通过构造一棵二叉排序树变成一个有序序列,构造树的过程即为对无序序列进行排序的过程。每次插入的新的结点都是二叉排序树上新的叶子结点,在进行插入操作时,不必移动其它结点,只需改动某个结点的指针,由空变为非空即可。搜索,插入,删除的复杂度等于树高,O(log(n)).

二叉排序树的查找算法

在二叉排序树b中查找x的过程为:

  1. 若b是空树,则搜索失败,否则:
  2. 若x等于b的根结点的数据域之值,则查找成功;否则:
  3. 若x小于b的根结点的数据域之值,则搜索左子树;否则:
  4. 查找右子树。

在二叉排序树插入结点的算法

向一个二叉排序树b中插入一个结点s的算法,过程为:

  1. 若b是空树,则将s所指结点作为根结点插入,否则:
  2. 若s->data等于b的根结点的数据域之值,则返回,否则:
  3. 若s->data小于b的根结点的数据域之值,则把s所指结点插入到左子树中,否则:
  4. 把s所指结点插入到右子树中。

在二叉排序树删除结点的算法

在二叉排序树删去一个结点,分三种情况讨论:

  1. 若*p结点为叶子结点,即PL(左子树)和PR(右子树)均为空树。由于删去叶子结点不破坏整棵树的结构,则只需修改其双亲结点的指针即可。
  2. 右*p结点只有左子树PL或右子树PR,此时只要令PL或PR直接成为其双亲结点*f的左子树即可,作此修改也不破坏二叉排序树的特性。
  3. 若*p结点的左子树和右子树均不空。在删去*p之后,为保持其它元素之间的相对位置不变,可按中序遍历保持有序进行调整,可以有两种做法:其一是令*p的左子树为*f的左子树,*s为*f左子树的最右下的结点,而*p的右子树为*s的右子树;其二是令*p的直接前驱(或直接后继)替代*p,然后再从二叉排序树中删去它的直接前驱(或直接后继)。

二叉排序树性能分析

每个结点的Ci为该结点的层次数。最坏情况下,当先后插入的关键字有序时,构成的二叉排序树蜕变为单支树,树的深度为n,其平均查找长度为(n+1)/2(和顺序查找相同),最好的情况是二叉排序树的形态和折半查找的判定树相同,其平均查找长度和log2n成正比(O(log2n))。

#include "stdio.h"
#include 
"stdlib.h"

struct  Node 
{
    
int key;//结点值

    struct Node *parent;//父结点
    struct Node *left;//左结点
    struct Node *right;//右结点
}
;

//打印二叉树

void PrintTree(struct Node * Root)
{
    
struct Node *pointer=(struct Node*)malloc(sizeof(struct
 Node));
    pointer
=
Root;
    
if(pointer!=
NULL)
    
{
        PrintTree(pointer
->
left);
        printf(
"%d ",pointer->
key);
        PrintTree(pointer
->
right);
    }

}


//删除树,递归释放树的结点
void DeleteTree(struct Node * Root)
{
    
struct Node *pointer=(struct Node*)malloc(sizeof(struct
 Node));
    pointer
=
Root;

    
if(pointer!=
NULL)
    
{
        DeleteTree(pointer
->
left);
        free(pointer);
        DeleteTree(pointer
->
right);
    }

}


//最小值
struct Node *Minimum(struct Node * Root)
{
    
struct Node *pointer=(struct Node*)malloc(sizeof(struct
 Node));
    pointer
=
Root;

    
while(pointer->left!=
NULL)
        pointer
=pointer->
left;

    
return
 pointer;
}


//最大值
struct Node *Maximum(struct Node * Root)
{
    
struct Node *pointer=(struct Node*)malloc(sizeof(struct
 Node));
    pointer
=
Root;

    
while(pointer->right!=
NULL)
        pointer
=pointer->
right;

    
return
 pointer;
}


//查找
struct Node *Search(struct Node *Root,int  value)
{
    
struct Node *pointer=(struct Node*)malloc(sizeof(struct
 Node));
    pointer
=
Root;

    
while(pointer!=NULL&&pointer->key!=
value)
    
{
        
//如果查找值比结点值小,查找它的左子树

        if(value<pointer->key)
            pointer
=pointer->
left;
        
else

            pointer
=pointer->right;//如果查找值比结点值大,查找它的右子树
    }


    
return pointer;
}


//后继
struct Node *Successor(struct Node * pointer)
{
    
if(pointer->right!=
NULL)
        
return Minimum(pointer->
right);

    
struct Node *y=(struct Node*)malloc(sizeof(struct
 Node));
    y
=pointer->
parent;
    
while(y!=NULL&&y->right==
pointer)
    
{
        pointer
=
y;
        y
=pointer->
parent;    
    }


    
return y;
}


//前驱
struct Node *Predecessor(struct Node * pointer)
{
    
if(pointer->left!=
NULL)
        
return Maximum(pointer->
left);

    
struct Node *y=(struct Node*)malloc(sizeof(struct
 Node));
    y
=pointer->
parent;
    
while(y!=NULL&&y->left==
pointer)
    
{
        pointer
=
y;
        y
=pointer->
parent;    
    }


    
return y;
}


//插入新结点
struct Node *Insert(struct Node *Root,struct Node * newNode)
{
    
struct Node *back=(struct Node*)malloc(sizeof(struct
 Node));
    
struct Node *pointer=(struct Node*)malloc(sizeof(struct
 Node));
    back
=
NULL;
    pointer
=
Root;

    
//找到要插入的位置

    while(pointer!=NULL)
    
{
        back
=
pointer;
        
if(newNode->key<pointer->
key)
            pointer
=pointer->
left;
        
else

            pointer
=pointer->right;
    }


    
//新结点的Parent指针先指向父结点
    newNode->parent=back;
    
    
if(back==
NULL)
        Root
=newNode;//树为空,新结点成为树根

    else 
    
{
        
if(newNode->key<back->
key)
            back
->left=
newNode;
        
else
 
            back
->right=
newNode;
    }


    
return Root;
}


//删除结点
struct Node *Delete(struct Node *Root,struct Node * pointer)
{
    
struct Node *y=(struct Node*)malloc(sizeof(struct
 Node));
    y
->parent=
NULL;
    y
->left=
NULL;
    y
->right=
NULL;
    
//找到实际要删除的结点

    if(pointer->left==NULL||pointer->right==NULL)
        y
=
pointer;
    
else

        y
=Successor(pointer);

    
struct Node *x=(struct Node*)malloc(sizeof(struct
 Node));
    x
->parent=
NULL;
    x
->left=
NULL;
    x
->right=
NULL;
    
//要删除结点的子结点

    if(y->left!=NULL)
        x
=y->
left;
    
else

        x
=y->right;

    
if(x!=
NULL)
        x
->parent=y->
parent;
    
    
if(y->parent==
NULL)
        Root
=x;//删除的是根结点

    else
    
{
        
if(y==y->parent->
left)
            y
->parent->left=
x;
        
else

            y
->parent->right=x;
    }


    
if(y!=pointer)
        pointer
->key=y->
key;

    
if(y!=
NULL)
    
{
        free(y);
        printf(
"Delete success! "
);
    }

    
else
        printf(
"Delete failure! ");

    
return
 Root;    
}


int  main()
{
    
struct Node *Root=
NULL;
    
int
 value;
    
    
int flag=1
;
    
while
(flag)
    
{    
        printf(
"1:Insert "
);
        printf(
"2:Delete "
);
        printf(
"3:Search "
);
        printf(
"4:Minimum "
);
        printf(
"5:Maximum "
);
        printf(
"6:Successor "
);
        printf(
"7:Predecessor "
);
        printf(
"0:Exit "
);
        printf(
"Please input your choice:"
);
        scanf(
"%d",&
flag);

        
switch
(flag)
        
{
        
case 0
:
            
return 0
;
        
case 1
:
            
{
                printf(
"Please input the value you want to input:"
);
                scanf(
"%d",&
value);
                
struct Node *newNode=(struct Node*)malloc(sizeof(struct
 Node));
                newNode
->key=
value;
                newNode
->parent=
NULL;
                newNode
->left=
NULL;
                newNode
->right=
NULL;
                Root
=
Insert(Root,newNode);
                
break
;
            }

        
case 2:
        
{
            printf(
"Please input the value you want to delete:"
);
            scanf(
"%d",&
value);
            
struct Node *newNode=(struct Node*)malloc(sizeof(struct
 Node));
            newNode
=
Search(Root,value);
            
if(newNode!=
NULL)
                Root
=
Delete(Root,newNode);
            
else

                printf(
"%d does'n exist in this tree! ",value);
            
break
;
        }

        
case 3:
        
{
            printf(
"Please input the value you want to input:"
);
            scanf(
"%d",&
value);
            
struct Node *newNode=(struct Node*)malloc(sizeof(struct
 Node));
            newNode
=
Search(Root,value);
            
if(newNode!=
NULL)
                printf(
"%d exist in this tree! ",newNode->
key);
            
else

                printf(
"%d does'n exist in this tree! ",value);
            
break
;
        }

        
case 4:
        
{        
            
if(Root!=
NULL)
            
{
                
struct Node *newNode=(struct Node*)malloc(sizeof(struct
 Node));
                newNode
=
Minimum(Root);
                printf(
"The minimum value of this tree is %d! ",newNode->
key);
            }

            
else
                printf(
"This tree is empty! ");
            
break
;
        }

        
case 5:
        
{        
            
if(Root!=
NULL)
            
{
                
struct Node *newNode=(struct Node*)malloc(sizeof(struct
 Node));
                newNode
=
Maximum(Root);
                printf(
"The Maximum value of this tree is %d! ",newNode->
key);
            }

            
else
                printf(
"This tree is empty! ");
            
break
;
        }

        
case 6:
        
{
            printf(
"Please input the value:"
);
            scanf(
"%d",&
value);
            
struct Node *newNode=(struct Node*)malloc(sizeof(struct
 Node));
            newNode
=
Search(Root,value);
            
if(newNode!=
NULL)
            
{
                newNode
=
Successor(newNode);
                
if(newNode!=
NULL)
                    printf(
"%d's successor is %d! ",value,newNode->
key);
                
else

                    printf(
"%d has't successor int this tree! ",value);
            }

            
else
                printf(
"%d does'n exist in this tree! ",value);
            
break
;
        }

        
case 7:
        
{
            printf(
"Please input the value:"
);
            scanf(
"%d",&
value);
            
struct Node *newNode=(struct Node*)malloc(sizeof(struct
 Node));
            newNode
=
Search(Root,value);
            
if(newNode!=
NULL)
            
{
                newNode
=
Predecessor(newNode);
                
if(newNode!=
NULL)
                    printf(
"%d's Predecessor is %d! ",value,newNode->
key);
                
else

                    printf(
"%d has't predecessor int this tree! ",value);
            }

            
else
                printf(
"%d does'n exist in this tree! ",value);
            
break
;
        }

        
default:
            
break
;
        }


        PrintTree(Root);
    }


    DeleteTree(Root);
    
return 0;
}

 
 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值