二叉搜索树
**定义:**它是一种对排序和查找都很有用的特殊二叉树;
一个二叉搜索树是一棵二叉树,它可以为空。如果不为空,它将满足以下性质:
非空左子树的所有键值小于其根结点的键值。
非空右子树的所有键值大于其根结点的键值。
左、右子树都是二叉搜索树。
查找操作
静态查找(二分查找)
动态查找
二叉搜索树查找操作
Position Find( ElementType X, BinTree BST )
{
if( !BST )
return NULL; /*查找失败*/
if( X > BST->Data )
return Find( BST->Right, X ); /*在右子树中继续查找*/
else if( X < BST->Data )
return Find( BST->Left, X ); /*在左子树中继续查找*/
else /* X == BST->Data */
return BST; /*查找成功,返回结点的找到结点的地址*/
}
最大数查找
最大元素一定是在树的最右分枝的端结点上
Position FindMin( BinTree BST )
{
if( !BST )
return NULL; /*空的二叉搜索树,返回NULL*/
else if( !BST->Left )
return BST; /*找到最左叶结点并返回*/
else
return FindMin( BST->Left ); /*沿左分支继续查找*/
}
最小数查找
最小元素一定是在树的最左分枝的端结点上
Position FindMax( BinTree BST )
{
if( !BST )
while( BST->Right )
BST = BST->Right;
/*沿右分支一直向下,直到最右端点*/
return BST;
}
二叉搜索树的插入
分析:插入完以后必须要保证依然还是二叉树,将元素X插入二叉搜索树BST中关键是要找到元素应该插入的位置。位置的确定可以利用与查找函数Find类似的方法,如果在树BST中找到X,说明要插入的元素已存在,可放弃插入操作。如果没找到X,查找终止的位置就是X应插入的位置。
BinTree Insert( BinTree BST, ElementType X )
{
if( !BST ) /*若原树为空,生成并返回一个结点的二叉搜索树*/
{
BST = (BinTree)malloc(sizeof(struct TNode));
BST->Data = X;
BST->Left = BST->Right = NULL;
}
else /* 开始找要插入元素的位置 */
{
if( X < BST->Data )
BST->Left = Insert( BST->Left, X );
/*递归插入左子树*/
else if( X > BST->Data )
BST->Right = Insert( BST->Right, X );
/*递归插入右子树*/
/* else X已经存在,什么都不做 */
}
return BST;
}
例题
以一年十二个月的英文缩写为键值,按从一月到十二月顺序输入它们,即输入序列为(Jan, Feb, Mar, Apr, May, Jun, July, Aug, Sep, Oct, Nov, Dec),将产生什么样的二叉搜索树?
分析:就是按照非空左子树的所有键值小于其根结点的键值,非空右子树的所有键值大于其根结点的键值。
二叉搜索树的删除
有三种情况要考虑
1.要删除的是叶结点——可以直接删除,然后再修改其父结点的指针
2.要删除的结点只有一个孩子结点——删除之前需要改变其父结点的指针,指向要删除结点的孩子结点。
3.要删除的结点有左、右两棵子树——为了保持二叉搜索树的有序性,替代被删除的元素的位置可以有两种选择:一种是取其右子树中的最小元素;另一个是取其左子树中的最大元素。
BinTree Delete( BinTree BST, ElementType X )
{
Position Tmp;
if( !BST )
printf("要删除的元素未找到");
else
{
if( X < BST->Data )
BST->Left = Delete( BST->Left, X ); /* 从左子树递归删除 */
else if( X > BST->Data )
BST->Right = Delete( BST->Right, X ); /* 从右子树递归删除 */
else /* BST就是要删除的结点 */
{
/* 如果被删除结点有左右两个子结点 */
if( BST->Left && BST->Right )
{
Tmp = FindMin( BST->Right ); /*从右子树中找最小的元素填充删除结点*/
BST->Data = Tmp->Data;
/* 从右子树中删除最小元素 */
BST->Right = Delete( BST->Right, BST->Data );
}
else /* 被删除结点有一个或无子结点 */
{
Tmp = BST;
if( !BST->Left )
BST = BST->Right; /* 只有右孩子或无子结点 */
else
BST = BST->Left; /* 只有左孩子 */
free( Tmp );
}
}
}
return BST;
}
平衡二叉树
什么是平衡二叉树??,怎样计算平均查找长度ASL
第一个图的ASL=(1+2×2+3×3+4×3+5×2+6×1)/12 = 3.5;
第二个图的ASL=(1+2×2+3×4+4×5)/12 = 3.0;
第三个图的ASL=(1+2×1+3×1+4×1+5×1+6×1+7×1+8×1+9×1+10×1+11×1+12×1)/12 = 6.5;
平衡因子:BF(T)=h(L)-h®;其中h(L)和h®分别为T的左、右子树的高度;
平衡二叉树,又称为“AVL树” 。 AVL树或者是一棵空树,或者是具有下列性质的非空二叉搜索树:“任一结点左、右子树高度差的绝对值不超过1 。”即|BF(T) |≤ 1
平衡二叉树的调整
作用就是要保证二叉树平衡
1.右单旋
2.左单旋
3.左右双旋
4.右左双旋
PAT例题
将给定的一系列数字插入初始为空的AVL树,请你输出最后生成的AVL树的根结点的值。输入格式:输入的第一行给出一个正整数N(≤20),随后一行给出N个不同的整数,其间以空格分隔。输出格式:在一行中输出顺序插入上述整数到一棵初始为空的AVL树后,该树的根结点的值。
输入样例1:5
88 70 61 96 120
输出样例1:
70
输入样例2:
7
88 70 61 96 120 90 65
输出样例2:
88
#include <stdio.h>
#include <stdlib.h>
typedef struct Node Node;
struct Node
{
int Data;
struct Node *Left,*Right;
}*head = NULL;
Node *New(int d)
{
Node *node = (Node *)malloc(sizeof(Node));
node -> Data = d;
node -> Left = node -> Right = NULL;
return node;
}
Node *ll(Node *node)
{
Node *l = node -> Left;
node -> Left = l -> Right;
l -> Right = node;
return l;
}
Node *rr(Node *node)
{
Node *r = node -> Right;
node -> Right = r -> Left;
r -> Left = node;
return r;
}
Node *lr(Node *node)
{
node -> Left = rr(node -> Left);
return ll(node);
}
Node *rl(Node *node)
{
node -> Right = ll(node -> Right);
return rr(node);
}
int max(int a,int b)
{
return a > b ? a : b;
}
int Height(Node *node)
{
return node == NULL ? 0 : max(Height(node -> Left),Height(node -> Right)) + 1;
}
Node* Insert(Node *node,int d)
{
if(node == NULL)
{
node = New(d);
}
else if(d < node -> Data)
{
node -> Left = Insert(node -> Left,d);
}
else
{
node -> Right = Insert(node -> Right,d);
}
if(Height(node -> Left) - Height(node -> Right) == 2)
{
if(d < node -> Left -> Data)
{
node = ll(node);
}
else
{
node = lr(node);
}
}
else if(Height(node -> Left) - Height(node -> Right) == -2)
{
if(d > node -> Right -> Data)
{
node = rr(node);
}
else
{
node = rl(node);
}
}
return node;
}
int main()
{
int n,d;
while(scanf("%d",&n)!=EOF)
{
for(int i = 0; i < n; i ++)
{
scanf("%d",&d);
head = Insert(head,d);
}
printf("%d",head -> Data);
}
return 0;
}