二叉查找树BST_legend



二叉排序、搜索树:BST
(一)二叉查找树的概念以及类型定义,特点:

(1)定义:
二叉查找树为空树,或者满足以下条件:
1.左子树非空,则左子树上所有记录均小于根节点的记录;
2.右子树非空,则右子树上所有记录均大于根节点的记录;
3.左右子树又是一棵二叉查找树。
(2)类型定义:
typedef struct node{
 DataType data;
 node* lchild, * rchild;
}BSTNode;
(3)特点:
中序遍历二叉查找树,得到一个递增的有序序列;

(二)二叉找树的查找:
(1)递归:
BSTNode* bstSearch(BSTNode* root, DataType k){
 if(root==NULL) return NULL;
 if(root->data==k) return root;
 else if(k<root->data) //在左子树中查找
 return bstSearch(root->lchild,k);
 else if(k>root->data)//在右子树中查找
 return bstSearch(root->rchild,k);
}

(2)非递归:
/*
在以root为根节点的二叉排序树中查值为x的节点,father保存的是所查节的父节点;
father为引用型参数
*/

BSTNode* bstSearch(BSTNode* root ,DataType x, BSTNode* & father){
 BSTNode* pnode=root;
 father=NULL;

 while(pnode!=NULL && x!=pnode->data){
  father=pnode;
  if(x<pnode->data)
  pnode=pnode->lchild;
  else pnode=pnode->rchild;
 }//没有找到,循环结束则pnode==NULL,father为值很接近data的叶子节点;
 return pnode;
}

(三)二叉查找树的遍历:

(四)二叉查找树的插入与创建:

(1)插入:
注意:新节点都是作为叶子节点插入的,所以树是向下生长的。

/*

目的:在以root为根节点的二叉排序树中插入一个值为x的节点,插入成功返回1,否则0;
注意:root为引用型参数;
思想:若原二叉查找树为空,则直接插入节点作为根节点;
若x小于根节点的data,则插在左子树中,否则右子树中。
*/
int bstInsert(BSTNode* & root, DataType x){
 if(NULL==root){
  root=(BSTNode* )malloc(sizeof(BSTNode));
  root->data=x;
  root->lchild=root->lchild=NULL;
  return 1;
 }

 else if(root->data==x){//如果二叉查找树中已经存在值为x的节点,则失败。
 return 0;
 }

 else if(x<root->data){//插入到左子树中。
 return bstInsert(root->lchild,x);
 }
 else bstInsert(root->rchild,x);
}

或者:非递归方法:

int bstInsert(BSTNode* & root,DataType x){
 BSTNode* pnode,*newNode,*father;
 pnode=bstSearch(root,x,father);//调用上面的非递归的查找
 //如果找到则pnode非空,没有找到则pnode为空,father为值很接近x的叶子节点。

 if(pnode!=NULL )//已经存在值为x的节点
 return 0;

 newNode=(BSTNode* )malloc(sizeof(BSTNode));
 newNode->data=x;
 newNode->lchild=newNode->rchild=NULL;

 if(NULL==father) //如果原二叉查找树为空
 root=newNode;

 else if(x<father->data)
 father->lchild=newNode;
 else  father->rchild=newNode;
 return 1;
}

(2)二叉查找树的构造:
void createBST(BSTNode* & root ,DataType[] dataArray, int length){
 root=NULL;
 for(int i=0;i<length;i++)
 bstInsert(root,dataArray[i]);
}

(五)二叉查找树的删除:

二叉查找树中删除一个节点,不能把以该节点为根的子树都删除,删除二叉查找树的一个节点就相当于删除有序序列中的一个元素。

设:被删除的节点为pnode,father为其父节点,分为四种情况:
(1)pnode为叶子节点:
直接删除pnode.
(2)pnode为左单分支节点:
pnode只有左子树,而没有右子树。
将pnode的左子树直接代替pnode。
(3)pnode为右单分支节点:
将pnode的右子树直接代替pnode。
(4)pnode为双分支节点:
1)方法一:
将pnode的左子树的最右节点与pnode交换,(pnode的左子树的最右节点没有右孩子),采用情况2删除左子树的最右节点。
2)方法二:
将pnode的右子树的最左节点与pnode交换,(pnode的右子树的最左节点没有左孩子),采用情况3删除右子树的最左节点。

代码实现:
/*
目的:在以root为根节点的二叉查找树中删除值为x的节点,成功则返回1,否则返回0;
注意:root为引用型参数,因为root也可能被删除。
*/
int bstDelete(BSTNode* &root , DataType x ){
 BSTNode* father,*node_x;

 node_x=bstSearch(root,x,father);//调用上面的非递归的search
 if(node_x==NULL)
 return 0;//没有该节点。

 BSTNode* temp_nodeX=node_x;//保存node_x的值;
 if(NULL==node_x->rchild)//右孩子为空,为左单分支节点
 {
 node_x=node_x->lchild;
 }

 else if(NULL==node_x->lchild)//左孩子为空,为右单分支节点
 {
 node_x=node_x->rchild;
 delete temp_nodeX;
 return 1;
 }

 else {//node_x为双分支节点
  BSTNode* pnode=node_x->lchild;
  father=node_x;
  //寻找node_x的左子树的最右节点,father为其父节点;
  while(pnode->rchild!=NULL)
  {
  father=pnode;
  pnode=pnode->rchild;
  }

  node_x->data=pnode->data;//将node_x的左子树的最右节点的值保存在node_x中
  //删除node_x的左子树的最右节点
  if(father==node_x)
  father->lchild=pnode->lchild;
  else
  father->rchild=pnode->lchild;

  delete pnode;
  return 1;
 }

}
——

(六)二叉查找树的其他操作:
http://blog.csdn.net/legend050709/article/details/38847103

(七)二叉平衡树:AVL
(1)定义:
高度平衡的二叉查找树为AVL树,即左右子树高度差的绝对值小于等于1的二叉查找树。
(2)节点的平衡因子:bf
节点 的平衡因子为该节点的左子树的高度减去右子树的高度,所以AVL树的所有节点的平衡因子为-1,0,或1.
(3)AVL树的节点的类型定义:

typedef struct AVLNode{
 DataType data;
 AVLNode* lchild, *rchild;
 int bf;//平衡因子
}

(4)完全二叉树是高度平衡的,但是它不一定满足二叉查找树的定义。



    原文作者:二叉查找树
    原文地址: https://blog.csdn.net/legend050709/article/details/38847183
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞