`
bcyy
  • 浏览: 1832704 次
文章分类
社区版块
存档分类
最新评论

二叉搜索树(Binary Search Tree )的定义及分析

 
阅读更多

定义:

二叉搜索树或者是一棵空树,或者是具有下列性质的二叉树:

  1. 每个结点都有一个作为搜索依据的关键码(key),所有结点的关键码互不相同。

  2. 左子树(如果非空)上所有结点的关键码都小于根结点的关键码。

  3. 右子树(如果非空)上所有结点的关键码都大于根结点的关键码。

  4. 左子树和右子树也是二叉搜索树。

  5. 结点左子树上所有关键码小于结点关键码;

  6. 右子树上所有关键码大于结点关键码;

  7. 若从根结点到某个叶结点有一条路径,路径左边的结点的关键码不一定小于路径上的结点的关键码。

  8. 如果对一棵二叉搜索树进行中序遍历,可以按从小到大的顺序,将各结点关键码排列起来,所以也称二叉搜索树为二叉排序树。 下图为二叉搜索树的一个图

二叉搜索树时一个用于查找操作的搞笑数据结构,因为在最坏的情况下只要查找其中一个分支上的数据就可以了。复杂度为O(nlg n),n为二叉树元素的个数。所以在实际使用中,尽可能的保证二叉树的平衡,这样对搜索来说是最高效的。
二叉树的实现和分析
前面提到,只有当二叉树搜索树保持平衡时对搜索来说才是最高效的,如何保持平衡,实际上很难得。在实际运用中使用最多的就是AVL树,专门在百度百科上专门搜索了下。下面是概述:
********************************************************************************
概述
在计算机科学中,AVL树是最先发明的自平衡二叉查找树。AVL树得名于它的发明者 G.M. Adelson-Velsky 和 E.M. Landis,他们在 1962 年的论文 "An algorithm for the organization of information" 中发表了它。

AVL 节点数计算

高度为 h 的 AVL 树,节点数 N 最多2^h − 1; 最少 (其中)。
最少节点数 n 如以费伯纳西数列可以用数学归纳法证明:
Nh= F【h+ 2】 - 1 (F【h+ 2】是 Fibonacci polynomial 的第h+2个数)。
即:
N0 = 0 (表示 AVL Tree 高度为0的节点总数)
N1 = 1 (表示 AVL Tree 高度为1的节点总数)
N2 = 2 (表示 AVL Tree 高度为2的节点总数)
Nh= N【h− 1】 + N【h− 2】 + 1 (表示 AVL Tree 高度为h的节点总数)
换句话说,当节点数为 N 时,高度 h 最多为。
节点的平衡因子是它的右子树的高度减去它的左子树的高度。带有平衡因子 1、0 或 -1 的节点被认为是平衡的。带有平衡因子 -2 或 2 的节点被认为是不平衡的,并需要重新平衡这个树。平衡因子可以直接存储在每个节点中,或从可能存储在节点中的子树高度计算出来。

操作

AVL树的基本操作一般涉及运做同在不平衡的二叉查找树所运做的同样的算法。但是要进行预先或随后做一次或多次所谓的"AVL 旋转"。
假设由于在二叉排序树上插入结点而失去平衡的最小子树根结点的指针为a(即a是离插入点最近,且平衡因子绝对值超过1的祖先结点),则失去平衡后进行进行的规律可归纳为下列四种情况:
  • 单向右旋平衡处理LL:(在百度百科上,这好像写错了)

由于在*a的左子树根结点的左子树上插入结点,*a的平衡因子由1增至2,致使以*a为根的子树失去平衡,则需进行一次右旋转操作;

  • 单向左旋平衡处理RR:

由于在*a的右子树根结点的右子树上插入结点,*a的平衡因子由-1变为-2,致使以*a为根的子树失去平衡,则需进行一次左旋转操作;

  • 双向旋转(先左后右)平衡处理LR:

由于在*a的左子树根结点的右子树上插入结点,*a的平衡因子由1增至2,致使以*a为根的子树失去平衡,则需进行两次旋转(先左旋后右旋)操作。

  • 双向旋转(先右后左)平衡处理RL:

由于在*a的右子树根结点的左子树上插入结点,*a的平衡因子由-1变为-2,致使以*a为根的子树失去平衡,则需进行两次旋转(先右旋后左旋)操作。

**********************************************************************************
头文件定义:
/*bistree.h*/
#ifndef BISTREE_H
#define BISTREE_H

/*定义平衡因子为AVL树*/
#define  AVL_LFT_HEAVY               1
#define  AVL_BALANCED                0
#define  AVL_RGT_HEAVY             -1

/*定义AVL树的节点*/

typedef struct AvlNode_ {
    void *data;
    int hidden;
    int factor;/*平衡因子*/
}AvlNode;

/*定义二叉树结构体*/
typedef struct BisTree_ {
    int size;/*存放数据个数*/
    int (*compare) (const void *key1,const void *key2);/*预留的一个接口*/
    void (*destroy)(void *data);/*封装的析构函数,作用是释放data空间*/
    BiTreeNode *root;/*指向根节点的一个指针*/
}BisTree;

/*函数接口*/
void bistree_init (BisTree *tree, int (*compare)(const void *key1,const void 
                               *key2),void (*destroy)(void *data));
void bistree_destory(BisTree *tree);
int bistree_insert(BisTree *tree,const void *data);
int bistree_remove (BisTree *tree,const void *data);
int bistree_lookup(BisTree *tree,void **data);
#define  bistree_size(tree)  ((tree)->size)


#endif

左旋:(在算法精解上面说的是右旋,和百度百科上描述的一样,但我就按照我理解的写吧)这个单凭看代码真的比较乱的,最好在图纸上画个图,把实现过程画一遍,其他也不是很难理解的。RR可以参照LL右旋的操作。RL也一样。
/*bistree.c*/
#include <stdlib.h>
#include <string.h>
#include "../include/bistree.h"
#include "../include/bitree.h"

/*左旋*/
static void rotate_left(BiTreeNode **node)
{
    BiTreeNode *right ,grandchild;
    right = bitree_right(*node);

    if (((AvlNode *)bitree_data(right) ->factor == AVL_RGT_HEAVY){
        /* RR */
        bitree_right(*node) = bitree_left(right);
        bitree_left(right) = *node;
        ((AvlNode *)bitree_data(*node))->factor = AVL_BALANCED;
        ((AvlNode *)bitree_data(right)) ->factor = AVL_BALANCED;
        *node = right;
        
    } else { /*RL*/
        grandchild = bitree_left(right);
        bitree_left(right) = bitree_right(grandchild);
        bitree_right(grandchild) = right;
        bitree_right(*node) = bitree_left(grandchild);
        bitree_left(grandchild) = *node;

        switch (((AvlNode *)bitree_data(grandchild)) ->factor){
            case AVL_LFT_HEAVY:
                ((AvlNode *)bitree_data(*node)) ->factor = AVL_BALANCED;
                ((AvlNode *)bitree_data(right)) ->factor = AVL_RGT_HEAVY;
                break;
                
            case AVL_BALANCED:
                ((AvlNode *)bitree_data(*node)) ->factor = AVL_BALANCED;
                ((AvlNode *)bitree_data(right)) ->factor = AVL_BALANCED;
                break;
                
            case AVL_RGT_HEAVY:
                ((AvlNode *)bitree_data(*node)) ->factor = AVL_LFT_HEAVY;
                ((AvlNode *)bitree_data(right)) ->factor = AVL_BALANCED;
                break;
                
            default:
                break;
        }
        ((AvlNode *)bitree_data(grandchild)) ->factor = AVL_BALANCED;
        *node = grandchild;
    }
    return;
}

右旋
左旋的逆操作
/*右旋*/
static void rotata_right(BiTreeNode **node)
{
    BiTreeNode *left ,grandchild;
    left = bitree_left(*node);

    if (((AvlNode *)bitree_data(left) ->factor == AVL_LFT_HEAVY){
        /* LL */
        bitree_left(*node) = bitree_right(left);
        bitree_right(left) = *node;
        ((AvlNode *)bitree_data(*node))->factor = AVL_BALANCED;
        ((AvlNode *)bitree_data(left)) ->factor = AVL_BALANCED;
        *node = left;
        
    } else { /*LR*/
        grandchild = bitree_right(left);
        bitree_right(left) = bitree_left(grandchild);
        bitree_left(grandchild) = left;
        bitree_left(*node) = bitree_right(grandchild);
        bitree_right(grandchild) = *node;

        switch (((AvlNode *)bitree_data(grandchild)) ->factor){
            case AVL_LFT_HEAVY:
                ((AvlNode *)bitree_data(*node)) ->factor = AVL_RGT_HEAVY;
                ((AvlNode *)bitree_data(left)) ->factor = AVL_BALANCED;
                break;
                
            case AVL_BALANCED:
                ((AvlNode *)bitree_data(*node)) ->factor = AVL_BALANCED;
                ((AvlNode *)bitree_data(left)) ->factor = AVL_BALANCED;
                break;
                
            case AVL_RGT_HEAVY:
                ((AvlNode *)bitree_data(*node)) ->factor = AVL_BALANCED;
                ((AvlNode *)bitree_data(left)) ->factor = AVL_LFT_HEAVY;
                break;
                
            default:
                break;
        }
        ((AvlNode *)bitree_data(grandchild)) ->factor = AVL_BALANCED;
        *node = grandchild;
    }
    return;
}

AVL树初始化及删除节点
/*删除当前节点的左子树
  * 如过参数2为NULL,表示删除所有节点
  */

static void destroy_left (BisTree * tree, BiTreeNode * node)
{ 
    BiTreeNode ** position;
    /*当树为空时,直接返回*/
    if (bistree_size(tree) == 0){
        return;
    }
    /*当删除节点为NULL时,当前位置指向树根
        否则,指向当前节点的左子树*/
    if (node == NULL){
        position = &tree->root;
    } else {
        position = &node->left;
    }
    /*删除节点*/
    if (*position != NULL){
        destroy_left(tree,*position);
        destroy_right(tree, *position);

        if (tree ->destroy != NULL){
            tree->destroy(((AvlNode *)(*position)->data)->data);
        }
        free ((*position)->data);
        free(*position);
        *position = NULL;

        tree->size --;
    }
    return ;
}

/*删除节点的右子树
  *如果节点为NULL,删除整个树
  */
static void destroy_right(BisTree * tree, BiTreeNode * node)
{
    BiTreeNode ** position;
    /*当树为空时,直接返回*/
    if (bistree_size(tree) == 0){
        return;
    }
    /*当删除节点为NULL时,当前位置指向树根
        否则,指向当前节点的左子树*/
    if (node == NULL){
        position = &tree->root;
    } else {
        position = &node->right;
    }
    /*删除节点*/
    if (*position != NULL){
        destroy_left(tree,*position);
        destroy_right(tree, *position);

        if (tree ->destroy != NULL){
            tree->destroy(((AvlNode *)(*position)->data)->data);
        }
        free ((*position)->data);
        free(*position);
        *position = NULL;

        tree->size --;
    }
    return ;
}
/*初始化AVL*/
void bistree_init(BisTree * tree, int(* compare)(const void * key1, const void * key2), void(* destroy)(void * data))
{
    bitree_init(tree, destroy);
    tree->compare = compare;
    return;
}

/*销毁*/
void bistree_destory(BisTree * tree)
{ 
    /*删除所有节点*/
    destroy_left( tree, NULL);
    memset(tree,0,sizeof(BisTree));
    return;
}

插入和删除
static int insert(BisTree *tree,BiTreeNode **node,const void *data,int *balanced)
{
    AvlNode *avl_data;
    int cmpval,retval;
    /**/
    if (bitree_is_eob(*node)){/*插入到根节点*/
         /*申请空间,并赋值*/
         if ((avl_data = (AvlNode *) malloc(sizeof(AvlNode))) == NULL)
            return -1;
         avl_data ->factor = AVL_BALANCED;
         avl_data ->hidden = 0;
         avl_data -> data = (void *) data;

         return bitree_ins_left(tree, * node, avl_data);
    } else {/*插入不为空的情况*/
         /*比较插入数值与节点数值大小*/
         cmpval = tree->compare(data,((AvlNode*)bitree_data(*node))->data);
         if (cmpval < 0){
              /*插入数值小于节点数值时,插入左子树*/
              if (bitree_is_eob(bitree_left(*node))){
                /*当插入节点左子树为空时,直接插入并且树平衡*/
                   if ((avl_data = (AvlNode *) malloc(sizeof(AvlNode))) == NULL)
                       return -1;
                   avl_data ->factor = AVL_BALANCED;
                   avl_data ->hidden = 0;
                   avl_data -> data = (void *) data;
                   *balanced = 0;
                   return bitree_ins_left(tree, * node, avl_data);
              } else { /*当不为空时,继续判断*/
                  if (retval = insert( tree, &bitree_left(*node), data, balanced) != 0)
                      return retval;
              }

              /*确保树的平衡*/
              if (!(*balanced)){
                  switch (((AvlNode *)bitree_data(*node)->factor){
                      case AVL_LFT_HEAVY:
                          rotata_right(node);
                          *balanced = 1;
                          break;
                      case AVL_BALANCED:
                          ((AvlNode*)bitree_data(*node) -> factor = AVL_LFT_HEAVY;
                          break;
                      case AVL_RGT_HEAVY:
                          ((AvlNode*)bitree_data(*node) -> factor = AVL_BALANCED;
                          *balanced = 1;
                          break;
                  }
              }
         }else if (cmpval > 0){
             /*插入右子树*/
             if (bitree_is_eob(bitree_right(*node))){
                  if ((avl_data = (AvlNode *) malloc(sizeof(AvlNode))) == NULL)
                       return -1;
                  avl_data ->factor = AVL_BALANCED;
                  avl_data ->hidden = 0;
                  avl_data -> data = (void *) data;
                  *balanced = 0;
                  return bitree_ins_right(tree, * node, avl_data);
             } else {/*节点不为空时,继续插入*/
                  if (retval = insert( tree, &bitree_right(*node), data, balanced) != 0)
                      return retval;
             }

             /*确保树的平衡*/
              if (!(*balanced)){
                  switch (((AvlNode *)bitree_data(*node)->factor){
                      case AVL_RGT_HEAVY:
                          rotata_right(node);
                          *balanced = 1;
                          break;
                      case AVL_BALANCED:
                          ((AvlNode*)bitree_data(*node) -> factor = AVL_RGT_HEAVY;
                          break;
                      case AVL_LFT_HEAVY:
                          ((AvlNode*)bitree_data(*node) -> factor = AVL_BALANCED;
                          *balanced = 1;
                          break;
                  }
              }

         } else { /*cmpval = 0*/
             /*插入数据相同*/
             if (!((AvlNode *)bitree_data(*node))->hadden){
                 return 1;
             } else {/*将替换掉原来的数值*/
                 if (tree ->destroy != NULL){
                     tree ->destroy(((AvlNode*)bitree_data(*node)) ->data);
                 }
                 ((AvlNode*)bitree_data(*node) -> data = (void *)data;
                 ((AvlNode*)bitree_data(*node) ->hadden = 0;

                 *balanced = 1;
             }
         }
    }        
    return 0;
}

static int hide(BisTree *tree, BiTreeNode *node, const void *data)
{
    int cmpval,retval;
    if (bitree_is_eob(node)
        return -1;
    cmpval = tree->compare(data,((AvlNode*)bitree_data(node))->data);
    if (cmpval < 0 ){/*去左子树查找*/
        retval = hide(tree, bitree_left(node),data);
    } else if (cmpval > 0){
        retval = hide( tree, bitree_right(node), data);
    } else {
        /*设置为隐藏*/
        ((AvlNode *)bitree_data(node))->hidden = 1;
        retval = 0
    }
    return retval;
}
/*插入数据
  *  返回值:
  * 0: 成功
  *  1: 插入数据已经存在树中
  *  -1: 失败
  */

int bistree_insert(BisTree * tree, const void * data)
{
    /*balance 作用是设置一个标志位用来对二叉树的
      *左右旋操作及设置factor的数值
      * 0:表示不平衡,需要重新设置
      * 1:则正好相反。
      */
    int balance = 0;
    return insert(tree,&bitree_root(tree),data,&balance);
}

/*删除数据
  * 原则上并未删除这个节点,只是将节点标志设置
  * 为隐藏。
  */

int bistree_remove(BisTree * tree, const void * data)
{
    return hide (tree,bitree_root(tree),data);
}

查找数据
/*查找数据*/
int look_up(BisTree *tree, BiTreeNode *node, void **data)
{
    int cmpval,retval;
    if (bitree_is_eob(node))
        return -1;
    
    cmpval = tree->compare(data,((AvlNode*)bitree_data(node))->data);
    if (cmpval < 0 ){/*去左子树查找*/
        retval = look_up(tree, bitree_left(node),data);
    } else if (cmpval > 0){
        retval = look_up( tree, bitree_right(node), data);
    } else {
        
        if (!((AvlNode *)bitree_data(node))->hidden ){
            *data = ((AvlNode *)bitree_data(node))->data;
            retval =0;
        } else {
            return -1;
        }
    }
    return retval;
}


分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics