二叉排序/搜索/查找树

二叉排序树(Binary Sort Tree)又称二叉查找树或二叉搜索树。 它或者是一棵空树;或者是具有下列性质的二叉树:
(1)若左子树不空,则左子树上所有结点的值均小于它的根结点的值;
(2)若右子树不空,则右子树上所有结点的值均大于它的根结点的值;
(3)左、右子树也分别为二叉排序树。

通俗地讲很简单:一句话就是左孩子比父节点小,右孩子比父节点大,还有一个特性就是”中序遍历“可以让结点有序。如下图:

几种常见的操作:

1、二叉树数据结构

struct BSTNode
{
    int data;        // value of node
    BSTNode *lchild; // left child of node
    BSTNode *rchild; // right child of node
}BSTNode,*BSTree; 

2、创建二叉排序树

/* 递归建立二叉排序树 */
void addBSTNode(BSTree &pCurrent,int value)//在这个函数中会要改变指针值,一定要记得使用引用传递
{
    if (pCurrent==NULL)
    {
        BSTree pBSTree=new BSTNode();
        //BSTree pBSTree = (BSTree)malloc(sizeof(BSTNode));
        pBSTree->data=value;
        pBSTree->lchild=NULL;
        pBSTree->rchild=NULL;
        pCurrent=pBSTree;
    }
    else if (pCurrent->data<value)
        addBSTNode(pCurrent->rchild,value);
    else if (pCurrent->data>value)
        addBSTNode(pCurrent->lchild,value);
    else
        cout<<"node repeated"<<endl;
}

3、二叉排序树的插入(跟创建时操作一样,只是返回根节点),二叉查找树的插入过程如下:1.若当前的二叉查找树为空,则插入的元素为根节点,2.若插入的元素值小于根节点值,则将元素插入到左子树中,3.若插入的元素值不小于根节点值,则将元素插入到右子树中。首先找到插入的位置,要么向左,要么向右,直到找到空结点,即为插入位置,如果找到了相同值的结点,插入失败。 

(1)递归版本:

BSTree insert(BSTree root, int value)
{
    BSTree pBSTree=new BSTNode();
    pBSTree->data=value;
    pBSTree->lchild=NULL;
    pBSTree->rchild=NULL;
    if(root==NULL){
        root=pBSTree;    
    }    
    else if(value<root->data)
        root->lchild=insert(root->lchild,value);    
    else
        root->rchild=insert(root->rchild,value);    
    return root;
}

(2)非递归版本:

void insert_BST(BSTree q, int value)
{
    BSTree p = new BSTNode();
    p->data = value;
    p->lchild = NULL;
    p->rchild = NULL;
    if(q == NULL){
        q = p;
        return ;    
    }        
    while(q->lchild != p && q->rchild != p){
        if(value < q->data){
            if(q->lchild){
                q = q->lchild;    
            }    
            else{
                q->lchild = p;
            }        
        }    
        else{
            if(q->rchild){
                q = q->rchild;    
            }    
            else{
                q->rchild = p;    
            }
        }
    }
    return;
}

4、二叉排序树的删除

二叉查找树的删除,分三种情况进行处理:
1.p为叶子节点,直接删除该节点,再修改其父节点的指针(注意分是根节点和不是根节点),如图a。
2.p为单支节点(即只有左子树或右子树)。让p的子树与p的父亲节点相连,删除p即可;(注意分是根节点和不是根节点);如图b。
3.有两个孩子的情况,当前结点与左子树中最大的元素交换,然后删除当前结点。左子树最大的元素一定是叶子结点,交换后,当前结点即为叶子结点,删除参考没有孩子的情况。另一种方法是,当前结点与右子树中最小的元素交换,然后删除当前结点。如图c。

bool bst_delete(BSTree &node, int value) {
  BSTree parent = NULL;
  BSTree tmp;
  while(node != NULL) {
    if(value < node->data) { // 向左 
      parent = node;
      node = node->lchild;
    }
    else if(value > node->data) { // 向右 
      parent = node;
      node = node->rchild;
    }
    else { // 找到了 
      if(NULL==node->lchild && NULL==node->rchild) { // 叶子结点         
        if(parent == NULL) { // 根结点 
          delete node;
          node = NULL;
        }
        else { // 非根结点 
          (parent->lchild==node)?(parent->lchild=NULL):(parent->rchild=NULL);
          delete node;
          node = NULL;
        }        
      }
      else if(NULL!=node->lchild && NULL==node->rchild) { // 只有左孩子
        if(parent == NULL) { // 根结点 
          tmp = node;
          node = node->lchild;
          delete tmp;          
        }
        else { // 非根结点 
          (parent->lchild==node)?(parent->lchild=node->lchild):(parent->rchild=node->lchild);
          delete node;
        }
      }
      else if(NULL!=node->rchild && NULL==node->lchild) { // 只有右孩子 
        if(parent == NULL) { // 根结点 
          tmp = node;
          node = node->rchild;
          delete tmp;          
        }
        else { // 非根结点 
          (parent->lchild==node)?(parent->lchild=node->rchild):(parent->rchild=node->rchild);
          delete node;
        }
      }
      else { // 既有左孩子也有右孩子 
        BSTree leftNode = node;
        while(leftNode->rchild != NULL) {
          parent = leftNode;
          leftNode = leftNode->rchild;
        }
        // 交换leftNode与node
        int swapValue = leftNode->data;
        leftNode->data = node->data;
        node->data = swapValue;
        // 删除leftNode,parent肯定不为空 
        (parent->lchild==node)?(parent->lchild=NULL):(parent->rchild=NULL);
        delete node;
      }
    }
  }
  return false; // 失败
}

(3)二叉排序树的查找

这个比较简单,要么找到了,要么向左,要么向右。

BSTree bst_search(BSTree node, int value) {
  while(node != NULL) {
    if(value < node->data) // 向左 
      node = node->lchild;
    else if(value > node->data) // 向右 
      node = node->rchild;
    else // 找到 
      return node;
  }
  return NULL; // 失败 
}

主函数测试代码:

int main()
{
    BSTree pRoot=NULL; 
    int a[7];
    for(int i=0;i<7;i++)
    {
        cin>>a[i];
        addBSTNode(pRoot,a[i]);
    }
    //各种函数测试... 
    system("pause");
    return 0;
}

 

posted @ 2013-04-18 15:56  一枚程序员  阅读(366)  评论(0编辑  收藏  举报