二叉搜索树(BST)
二叉搜索树也是一种树,适用与一般二叉树的全部操作,但二叉搜索树能够实现数据的快速查找
性质:
非空左子树的所有键值小于其根节点的键值
非空右子树的所有键值大于其根节点的键值
左右子树都是二叉搜索树
二叉搜索树的插入、查找、删除
删除主要分三种情况来讨论:
(1)要删除的是叶子结点:直接删除
(2)要删除的节点只有一个孩子节点:将其父节点的指针指向要删除节点的孩子节点
(3)要删除的节点有左、右两颗子树:
用另一个结点替代被删除结点:右子树的最小元素或者左子树的最大元素
其中删除操作的代码较复杂,暂未给出。
平衡二叉树(AVL树)(此处的AVL起源于一个发现者的人名)
以上已经知道一个数组二分查找的算法,可以以二叉查找树来实现,但一般该二叉查找树的效率比不上/数组的二分查找
这是由于二叉查找树是不平衡的。。要想缩短一个二叉搜索树的查找时间,需要将二叉查找树调整为平衡二叉树。
衡量二叉搜索树搜索效率的标准:平均查找长度(ASL):每个结点比较次数和/结点数
平衡因子(BF):左子树的高度减去右子树的高度。
判断一个二叉搜索树是否为一个平衡二叉树:|BF|小于等于1
当对一个平衡二叉树插入一个结点后,AVL树就变的不平衡了
平衡二叉树的调整:分为四种情况
(1)多余点在树的不平衡子树的根结点的右子树的右边:RR插入,需要RR旋转
(2)多余点在树的不平衡子树的根结点的左子树的左边:LL插入,需要LL旋转
(3)多余点在树的不平衡子树的根结点的右子树的左边:RL插入,需要RL旋转
(3)多余点在树的不平衡子树的根结点的左子树的右边:LR插入,需要LR旋转
平衡二叉树的代码后续会给出
以下代码实现了二叉树 的插入、查找操作。。并给出了一个《剑指offer》上的一道笔试题:查找一个二叉搜索树中第k小的元素。
#include <iostream>
#include <stack>
using namespace std;
typedef int ElementType;
typedef struct TreeNode{
ElementType val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(ElementType x) : val(x),left(NULL),right(NULL){}
}Node, *BST;
int count=1;
/*插入的方式建立一个二叉搜索树*/
BST Insert(ElementType x,BST bst)
{
if(bst==NULL){
bst = new Node(x);
bst->left = NULL;
bst->right = NULL;
}
else{
if(x<bst->val)
bst->left = Insert(x,bst->left);
else
bst->right = Insert(x,bst->right);
}
return bst;
}
/*查找二叉搜索树中的某个元素,并返回该结点*/
BST Find(BST bst, ElementType num)
{
if(!bst)
return NULL;
if(num < bst->val)
return Find(bst->left,num);
else if(num > bst->val)
return Find(bst->right,num);
else
return bst;
//return bst;
}
/*查找第k小的元素!采用前序遍历递归方法,当遍历到第k小的数时返回该节点(非空),并让程序逐级返回----此处不易理解*/
BST KthNode(BST bst, int k)
{
if(bst==NULL)
return NULL;
BST left = KthNode(bst->left,k);
if(left!=NULL)
return left;
if(count==k)
return bst;
count++;
BST right = KthNode(bst->right,k);
if(right!=NULL)
return right;
return NULL;
}
//中序遍历
void inorderTraverse(BST bst)
{
if(bst)
{
cout << bst->val << " ";
inorderTraverse(bst->left);
inorderTraverse(bst->right);
}
}
//前序遍历---只有二叉搜索树的中序遍历输出的结果从小到大排列,后序遍历并不是从大到小排列
void preorderTraverse(BST bst)
{
if(bst)
{
preorderTraverse(bst->left);
cout << bst->val << " ";
preorderTraverse(bst->right);
}
}
int main()
{
BST bst = NULL;
bst = Insert(5,bst);
bst = Insert(3,bst);
bst = Insert(6,bst);
bst = Insert(2,bst);
bst = Insert(4,bst);
bst = Insert(7,bst);
inorderTraverse(bst);
cout << endl;
preorderTraverse(bst);
cout << endl;
Node* Knode = KthNode(bst, 5);
cout << Knode->val << endl;
Node* Fnode = Find(bst,4);
cout << Fnode->val << endl;
}