二叉搜索树(Binary Search Tree)
1.非空左子树的所有键值小于其根节点的键值
2.非空右子树的所有键值大于其根节点的键值
3.左右子树都是二叉搜索树
二叉搜索树的删除
-
要删除的是叶节点:直接删除,并再修改其父节点指针—置为NULL
-
要删除的节点只有一个孩子节点:将其父节点的指针指向要删除节点的孩子节点
-
要删除的节点有左、右两颗子树:右子树最小元素或左子树最大元素替代被删除的节点
二叉搜索的基本运算
#include <stdio.h>
#include <stdlib.h>
#define N 10
typedef struct TreeNode *Tree;
typedef struct TreeNode *Position;
struct TreeNode{
int Data;
Tree Left,Right;
};
int Retrieve(Position P) {
return P->Data;
}
Tree MakeEmpty(Tree BST) //树置空
{
if(BST != NULL)
{
MakeEmpty(BST->Left);
MakeEmpty(BST->Right);
free(BST);
}
return NULL;
}
Position Find(int x, Tree BST) //找到值为x的元素在树中位置,使用递归方式
{
if(!BST) return NULL;
if(x > BST->Data)
return Find(x,BST->Right);
else if ( x < BST->Data)
return Find(x, BST->Left);
else
return BST;
}
Position IterFind(int x, Tree BST) 找到值为x的元素在树中位置,使用循环迭代方式
{
while(BST){
if(x > BST->Data)
BST = BST->Right;
else if(x < BST->Data)
BST = BST->Left;
else
return BST;
}
return NULL;
}
Position FindMax(Tree BST) //找到树中的最大值
{
if(!BST) return NULL;
else if (!BST->Right)
return BST;
else
return FindMax(BST->Right);
}
Position FindMin(Tree BST) //找到树中的最小值,使用递归方式
{
if(!BST) return NULL;
else if (!BST->Left)
return BST;
else
return FindMin(BST->Left);
}
Position FindMin_1(Tree BST) //找到树中的最小值,使用迭代方式
{
if(BST)
while(BST->Left){
BST = BST->Left;
}
return BST;
}
Tree Insert(int x, Tree BST) //在BST中插入一个元素
{
if(!BST){
BST = malloc(sizeof( struct TreeNode ));
BST->Data = x;
BST->Left = BST->Right =NULL;
} else
if (x < BST->Data)
BST->Left = Insert(x, BST->Left);
else if (x > BST->Data)
BST->Right = Insert(x, BST->Right);
return BST;
}
Tree Delete(int x, Tree BST) //找到树中的x元素,并删除
{
Position Tmp;
if(!BST) printf("未找到需要删除的元素");
else if(x < BST->Data)
BST->Left = Delete(x, BST->Left);
else if(x > BST->Data)
BST->Right = Delete(x, BST->Right);
else
if(BST->Left && BST->Right) {
Tmp = FindMin(BST->Right);
BST->Data = Tmp->Data;
BST->Right = Delete(BST->Data,BST->Right);
} else{
Tmp = BST;
if(!BST->Left)
BST = BST->Right;
else if (!BST->Right)
BST = BST->Left;
free(Tmp);
}
return BST;
}
int main(void)
{
int data[N] = { 16, 24, 51, 12, 32, 2, 15, 44,33,9 };
int i, e;
Tree T;
Position P;
T = MakeEmpty(NULL);
for(i = 0; i < N; ++i)
T = Insert(data[i], T);
P = FindMin(T);
printf("Min: %d\n", P->Data);
P = FindMax(T);
printf("Max: %d\n", P->Data);
T = Delete(2, T);
printf("在删除掉元素x后");
P = FindMin(T);
printf("Min: %d\n", P->Data);
P = FindMax(T);
printf("Max: %d\n", P->Data);
return 0;
}
平衡二叉树
平衡因子(Balance Factor):BF(T)=
H
L
H_{L}
HL-
H
R
H_{R}
HR,其中
H
L
和
H_{L}和
HL和H_{R}$分别为T的左、右子树高度。
平衡二叉树:空树或任一节点的左右子树高度差的绝对值不超过1,即|BF(T)|
≤
\leq
≤ 1
#include <stdio.h>
#include <stdlib.h>
typedef struct AVLNode *Position;
typedef Position AVLTree; //AVL树类型
struct AVLNode{
int Data; //结点数据
AVLTree Left; // 指向左子树
AVLTree Right; // 指向右子树
int Height; // 树高
};
int Max ( int a, int b )
{
return a > b ? a : b;
}
int GetHeight(AVLTree A){
if(A==NULL)
return 0;
return Max( GetHeight(A->Left), GetHeight(A->Right) )+1;
}
AVLTree SingleLeftRotation ( AVLTree A )
{ // 注意:A必须有一个左子结点B
// 将A与B做左单旋,更新A与B的高度,返回新的根结点B
AVLTree B = A->Left;
A->Left = B->Right;
B->Right = A;
A->Height = Max( GetHeight(A->Left), GetHeight(A->Right) ) + 1;
B->Height = Max( GetHeight(B->Left), A->Height ) + 1;
return B;
}
AVLTree SingleRightRotation ( AVLTree A )
{ // 注意:A必须有一个右子结点B
// 将A与B做右单旋,更新A与B的高度,返回新的根结点B
AVLTree B = A->Right;
A->Right = B->Left;
B->Left = A;
A->Height = Max( GetHeight(A->Left), GetHeight(A->Right) ) + 1;
B->Height = Max( GetHeight(B->Right), A->Height ) + 1;
return B;
}
AVLTree DoubleLeftRightRotation ( AVLTree A )
{ // 注意:A必须有一个左子结点B,且B必须有一个右子结点C
// 将A、B与C做两次单旋,返回新的根结点C
// 将B与C做右单旋,C被返回
A->Left = SingleRightRotation(A->Left);
// 将A与C做左单旋,C被返回
return SingleLeftRotation(A);
}
AVLTree DoubleRightLeftRotation ( AVLTree A )
{ // A必须有一个左子结点B,且B必须有一个右子结点C
// 将A、B与C做两次单旋,返回新的根结点C
// 将B与C做右单旋,C被返回
A->Left = SingleLeftRotation(A->Right);
// 将A与C做左单旋,C被返回
return SingleRightRotation(A);
}
AVLTree Insert( AVLTree T, int X )
{ // 将X插入AVL树T中,并且返回调整后的AVL树
if ( !T ) { // 若插入空树,则新建包含一个结点的树
T = (AVLTree)malloc(sizeof(struct AVLNode));
T->Data = X;
T->Height = 0;
T->Left = T->Right = NULL;
}
else if ( X < T->Data ) {
// 插入T的左子树
T->Left = Insert( T->Left, X);
// 如果需要左旋
if ( GetHeight(T->Left)-GetHeight(T->Right) == 2 ) {
if (X < T->Left->Data)
T = SingleLeftRotation(T); // 左单旋
else
T = DoubleLeftRightRotation(T); // 左-右双旋
}
}
else if ( X > T->Data ) {
// 插入T的右子树
T->Right = Insert( T->Right, X );
// 如果需要右旋
if ( GetHeight(T->Left)-GetHeight(T->Right) == -2 ) {
if (X > T->Right->Data)
T = SingleRightRotation(T); // 右单旋
else
T = DoubleRightLeftRotation(T); // 右-左双旋
}
} // else if (插入右子树) 结束
// 更新树高
T->Height = Max( GetHeight(T->Left), GetHeight(T->Right) ) + 1;
return T;
}
void PreOrderTraverse(AVLTree T)
{
if(T==NULL)
return;
printf("%d",T->Data);// 显示结点数据,可以更改为其它对结点操作
PreOrderTraverse(T->Left); // 再先序遍历左子树
PreOrderTraverse(T->Right); // 最后先序遍历右子树
}
int main(){
int N;
scanf("%d", &N);
int num;
AVLTree T=NULL;
for(int i=1; i<=N; i++){
scanf("%d", &num);
T = Insert(T,num);
}
//printf("%d",T->Left->Right->Data);
PreOrderTraverse(T);
return 0;
}