二叉搜索树的查找、插入、删除操作

原创 2016年05月30日 20:37:52

定义:
二叉排序树或者是一棵空树,或者是具有下列性质的二叉树
(1)若左子树不空,则左子树上所有结点的值均小于它的根结点的值;
(2)若右子树不空,则右子树上所有结点的值均大于它的根结点的值;
(3)左、右子树也分别为二叉排序树;
(4)没有键值相等的结点


对于查找和插入操作相对来说比较简单,删除操作则需要考虑的情况较多。

比如有以下些情况,可能有些可以合并,但是我没想到更好的方法,因此代码里有一堆if else,虽然我不喜欢写这样的代码,但也没找到更好的方法。


1. 考虑是否是空树、或者需要删除的结点不在树中。

2. 考虑整棵树只有一个结点,删除后需要修改入参,将整棵树置空。

3. 考虑删除的结点是叶子结点。

4. 待删除的结点只有左子树,或者只有右子树。

5.待删除的结点有左右子树。


下面是我的代码,简单测试过不同的用例,没什么问题,但是由于一堆if  else让我很不放心,还有问题也说不定。

//bsearchtree.h

#include <stdio.h>

typedef struct Item{
    int m_item;
    /**/
}Item;

typedef struct Node{
    int key;
    Item item;
}Node;

typedef struct Tree{
    Node node;
    struct Tree * lchild;
    struct Tree * rchild;
}Tree;

typedef struct Tree * TreePointer;

const Tree * mybsearch(const Tree * tree, int key);
int binsert(TreePointer * ptree, const Node * nd);
int bdelete(TreePointer * ptree, int key);
void threeWayJoin(Tree * small, Tree * mid, Tree * big);
void twoWayJoin(Tree * small, Tree * big);
void split(Tree * tree, int k, Tree * small, Tree * mid, Tree * big);
void show(TreePointer tree);


//bsertchtree.c


#include "bsearchtree.h"
#include <stdlib.h>

const Tree * mybsearch(const Tree * tree, int key)
{
    if(NULL == tree)
    {
        return NULL;
    }
    if(key == tree->node.key)
        return tree;
    if(key > tree->node.key)
        return mybsearch(tree->rchild, key);
    else
        return mybsearch(tree->lchild, key);
}
/*循环实现
{
    while(tree)
    {
        if(key == tree->node.key)
            return tree;
        if(key > tree->node.key)
        {
            tree = tree->rchild;
        }
        else
        {
            tree = tree->lchild;
        }
    }
    return NULL;
}
*/
int binsert(TreePointer * ptree, const Node * nd)
{
    Tree * current = *ptree;
    Tree * prev = NULL;
    Tree * pnew;
    
    while(current)
    {
        if(nd->key == current->node.key)
        {
            return 0;
        }
        prev = current;
        if(nd->key > current->node.key)
            current = current->rchild;
        else
            current = current->lchild;
    }
    
    pnew = (Tree *)malloc(sizeof(Tree));
    pnew->node = *nd;
    pnew->lchild = pnew->rchild = NULL;
    
    if(prev)
    {
        if(nd->key > prev->node.key)
            prev->rchild = pnew;
        else
            prev->lchild = pnew;
    }
    else
        *ptree = pnew;
    
    return 1;
}

int bdelete(TreePointer * ptree, int key)
{
    Tree * current = *ptree;
    Tree * prev = NULL;
    int flag = 0;//找到关键字为1, 没找到为0
    
    /*查找树中是否存在关键字项key, current 指向含key的结点, prev指向其前驱结点*/
    while(current)
    {
        if(key == current->node.key)
        {
            flag = 1;
            break;
        }
        prev = current;
        if(key > current->node.key)
            current = current->rchild;
        else
            current = current->lchild;
    }
    //没有查找到需要删除的结点
    if(!flag)
    {
        return 0;
    }
    //整棵树只有一个结点
    if((*ptree)->lchild == NULL && (*ptree)->rchild == NULL)
    {
        free(*ptree);
        *ptree = NULL;
        return 1;
    }
    //待删除的结点是叶子结点
    if(current->lchild == NULL && current->rchild == NULL)
    {
        if(prev->lchild == current)
            prev->lchild = NULL;
        else
            prev->rchild = NULL;
    }
    //待删除的结点只有一个右子结点
    else if(current->lchild == NULL)
    {
        if(prev->lchild == current)//前驱结点的左指针指向当前结点
            prev->lchild = current->rchild;
        else //前驱结点的右指针指向当前结点
            prev->rchild = current->rchild;
    }
    //待删除的结点只有一个左子结点
    else if(current->rchild == NULL)
    {
        if(prev->lchild == current)
            prev->lchild = current->lchild;
        else
            prev->rchild = current->lchild;
    }
    //待删除的结点有2个子结点
    else
    {
        //寻找左子树中key最大的结点, save保存其前驱结点
        Tree * save = current;
        Tree * temp = current->lchild;
        
        while(temp->rchild)
        {
            save = temp;
            temp = temp->rchild;
        }
        if(save == current)
            save->lchild = temp->lchild;
        else
            save->rchild = temp->lchild;
        current->node = temp->node;
        current = temp;
    }
    free(current);
    return 1;
}

void threeWayJoin(Tree * small, Tree * mid, Tree * big);
void twoWayJoin(Tree * small, Tree * big);
void split(Tree * tree, int k, Tree * small, Tree * mid, Tree * big);
void show(TreePointer tree)
{
    if(tree)
    {
        printf("key = %d, data = %d\n", tree->node.key, tree->node.item.m_item);
        show(tree->lchild);
        show(tree->rchild);
    }
}



//test.c  ,测试的数据可以自己修改

#include "bsearchtree.h"
#include <stdlib.h>
#include <time.h>


int main(void)
{
    int i;
    Node node;
    TreePointer tree;
    
    srand(time(NULL));
    tree = NULL;
    
    /*
    for(i =0; i < 10; i++)
    {
        node.key = rand() % 10;
        node.item.m_item = i;
        binsert(&tree, &node);
        printf("insert: key = %d, data = %d\n", node.key, node.item.m_item);
    }
    */
    node.key = 1;
    node.item.m_item = 0;
    binsert(&tree, &node);
    
    node.key = 8;
    binsert(&tree, &node);
    
    node.key = 3;
    binsert(&tree, &node);
    
    node.key = 2;
    binsert(&tree, &node);
    
    
    node.key = 9;
    binsert(&tree, &node);
    
    printf("after insert: \n");
    show(tree);
    printf("after delete: \n");
    bdelete(&tree, 8);
    show(tree);
    
    return 0;
}

二叉查找树(二叉排序树)创建,插入,删除操作。

二叉排序树 二叉排序树是一个基础的树的数据结构。应用非常多。它的特性就是,左孩子小于parent,右孩子大于parent. 寻找节点 寻找节点就是直接根据数值的大小,从root节点开...
  • chenfs1992
  • chenfs1992
  • 2014年07月31日 22:29
  • 1179

二叉排序树(查询、插入、删除)

“二叉排序树,又称为二叉查找树。它或者是一颗空树,或者具有下列性质的二叉树。 若它的左子树不空,则左子树上所有节点的值均小于它的根节点的值; 若它的右子树不空,则右子树上所有节点的值均...
  • wangyunyun00
  • wangyunyun00
  • 2014年04月14日 22:00
  • 17348

二叉搜索树的定义、查找、插入和删除

二叉搜索树的定义 二叉搜索树,也称有序二叉树,排序二叉树,是指一棵空树或者具有下列性质的二叉树: 1. 若任意节点的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 2. 若任意节点的...
  • yanxiaolx
  • yanxiaolx
  • 2016年07月21日 21:59
  • 5164

二叉搜索树的插入,删除

先来介绍一下, 一棵非空的二叉搜索树满足以下特征: 1.每个结点都有一个作为搜索依据的关键码,所有结点的关键码互不相同。 2.左子树(如果存在)上的所有结点的关键码均小于根结点的关键...
  • li_zhenxing
  • li_zhenxing
  • 2014年06月01日 21:59
  • 1006

二叉排序树的建立、插入、删除、查找、4种遍历 C++完整实现

#include #include #include using namespace std; typedef int KeyType; #define NUM 13 class BinSTree;...
  • u010367506
  • u010367506
  • 2014年04月01日 15:25
  • 2847

二叉查找树(1) - 查找以及插入

在WikiPedia中,对二叉查找树的定义如下: 二叉查找树,是一种基于节点的二叉树,有下面的性质: 节点的左子树中任意节点值小于根节点; 节点的右子树中任意节点值大于根节点; 左右子树都必须是二叉...
  • shltsh
  • shltsh
  • 2015年06月15日 23:03
  • 1352

【算法导论】二叉搜索树的插入和删除

阐述二叉搜索树的插入和删除节点操作。
  • cyp331203
  • cyp331203
  • 2015年01月11日 11:47
  • 1655

二叉搜索树(Binary Search Tree)的递归和非递归代码实现(C++)

二叉搜索树简单介绍二叉搜索树(Binary Search Tree)是满足: 左子树的根节点比树的根节点小 右子树的根节点比树的根节点大 的二叉树。 由于这种数据结构具有很高的查询效率,故多用于需要...
  • dawning7670
  • dawning7670
  • 2016年03月11日 22:59
  • 726

二叉排序树的操作(建立、插入、删除和查找)

二叉排序树的建立、插入、删除和查找(删除待补充) #include #include typedef struct node { int key; struct node *lc...
  • yushanjin0767
  • yushanjin0767
  • 2013年08月22日 15:55
  • 1551

二叉排序树的查找、插入、删除、建立

二叉排序树的定义: (1)、如果
  • u011028179
  • u011028179
  • 2014年08月16日 10:45
  • 485
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:二叉搜索树的查找、插入、删除操作
举报原因:
原因补充:

(最多只允许输入30个字)