4.1 二叉搜索树
4.1.1 定义与抽象数据类型的基本操作
1. 定义:
一棵二叉树,可以为空;如果不为空,满足以下性质:
1. 非空 左子树 的所有 键值小于其根结点 的键值。
2. 非空 右子树 的所有 键值大于其根结点 的键值。
3. 左、右子树都是二叉搜索树 。
2. 抽象数据类型:
查找:
1.1.Position Find( ElementType X, BinTree BST )
:从二叉搜索树BST中查找元素X ,返回其所在结点的地址;
1.2.Position FindMin( BinTree BST )
:从二叉搜索树BST 中查找并返回最小元素所在结点的地址;
1.3.Position FindMax( BinTree BST )
:从二叉搜索树BST 中查找并返回最大元素所在结点的地址。注:
1. 尾递归都可以用循环实现!
2. 查找效率与树的高度有关!
插入与删除
1.BinTree Insert( ElementType X, BinTree BST )
2.BinTree Delete( ElementType X, BinTree BST )
注:
1. 插入和删除有三种情况:
- 没有左儿子和右儿子;
- 只有左儿子或者右儿子;
- 既有左儿子又有右儿子(选取右子树中最小的那个)。
4.2 平衡二叉树
4.2.1 定义和特点
1. 平衡因子和平衡二叉树
平衡因子定义:
平衡因子 (Balance Factor,简称BF): BF(T)=hL−hR 其中 hL 和 hR 分别为 T 左、右子树的高度。
平衡二叉树的定义:
平衡二叉树 (Balanced Binary Tree)(AVL):
空树,或者任一结点左、右子树高度差的绝对值不超过1 ,即 |BF(T)|≤1 。
2.
平衡因子的高度
4.2.2 平衡二叉树的调整
整体思路:
发现“麻烦节点”,寻找麻烦节点的的原因(RR、LR、LL、RL),最后根据原因进行求解。
-
RR旋转
//函数传入头结点A
Position N = A->Right;
A->Right = N->Left;
N->Left = A;
return N;
-
LL旋转
//函数传入头结点A
Position N = A->Left;
A->Left = N->Right;
N->Right = A;
return N;
-
LR旋转
先左旋转,后右旋转;
-
RL旋转
先右旋转,后左旋转;
4.3
5-4 是否同一棵二叉搜索树 (25分)
给定一个插入序列就可以唯一确定一棵二叉搜索树。然而,一棵给定的二叉搜索树却可以由多种不同的插入序列得到。例如分别按照序列{2, 1, 3}和{2, 3, 1}插入初始为空的二叉搜索树,都得到一样的结果。于是对于输入的各种插入序列,你需要判断它们是否能生成一样的二叉搜索树。输入格式:
输入包含若干组测试数据。每组数据的第1行给出两个正整数N(≤10)和L,分别是每个序列插入元素的个数和需要检查的序列个数。第2行给出N个以空格分隔的正整数,作为初始插入序列。最后L行,每行给出N个插入的元素,属于L个需要检查的序列。简单起见,我们保证每个插入序列都是1到N的一个排列。当读到N为0时,标志输入结束,这组数据不要处理。
输出格式:
对每一组需要检查的序列,如果其生成的二叉搜索树跟对应的初始序列生成的一样,输出“Yes”,否则输出“No”。输入样例:
4 2
3 1 4 2
3 4 1 2
3 2 4 1
2 1
2 1
1 2
0
输出样例:
Yes
No
No
#include<stdio.h>
#include<iostream>
typedef struct TreeNode *Tree;
struct TreeNode{
int v;
Tree Left,Right;
int flag;
};
/*build Tree*/
Tree MakeTree(int N);
Tree Insert(Tree T,int V);
Tree NewNode(int V);
/*distinguish wheather is same tree or not*/
int Judge(Tree T,int N);
int check(Tree T,int V);
/*other function help to distinguish the sameTree */
void ResetT(Tree T);
void FreeTree(Tree T);
int main()
{
int N,L,i;
Tree T;
scanf("%d",&N);
while(N)
{
scanf("%d",&L);
T = MakeTree(N);
for(i=0;i<L;i++)
{
if(Judge(T,N))printf("Yes\n");
else printf("No\n");
ResetT(T);
}
FreeTree(T);
scanf("%d",&N);
}
return 0;
}
Tree MakeTree(int N)
{/*build a tree*/
Tree T;
int i,V;
scanf("%d",&V);
T = NewNode(V);
for(i=1;i<N;i++)
{
scanf("%d",&V);
T = Insert(T,V);
}
return T;
}
Tree NewNode(int V)
{ /* get new space */
Tree T = (Tree)malloc(sizeof(struct TreeNode));
T->v = V;
T->Left = T->Right = NULL;
T->flag = 0;
return T;
}
Tree Insert(Tree T,int V)
{/*Insert the new space*/
if(!T) T = NewNode(V);
else
{
if(T->v < V)
T->Right = Insert(T->Right,V);
else
T->Left = Insert(T->Left,V);
}
return T;
}
int check(Tree T, int V)
{/*check the V weather at T or not*/
if(T->flag)
{
if(V < T->v) return check(T->Left,V);
else if(V > T->v)
return check(T->Right,V);
else
return 0;
}
else
{
if(V == T->v)
{
T->flag = 1;
return 1;
}
else return 0;
}
}
int Judge(Tree T, int N)
{
int i,V,flag = 0;
scanf("%d",&V);
if(V != T->v) flag = 1;
else T->flag = 1;
for(i = 1; i < N;i++){
scanf("%d",&V);
if((!flag)&&(!check(T,V)))flag = 1;
}
if(flag)return 0;
else return 1;
}
void ResetT(Tree T)
{/*clear all the flag in the Tree T*/
if(T->Left) ResetT(T->Left);
if(T->Right)ResetT(T->Right);
T->flag = 0;
}
void FreeTree(Tree T)
{/*Let the space of T free*/
if(T->Left) FreeTree(T->Left);
if(T->Right) FreeTree(T->Right);
free(T);
}
4.4
#include<stdio.h>
#include<iostream>
typedef struct TreeNode *AVLTree;
typedef struct TreeNode *Position;
struct TreeNode{
int Date;
AVLTree Left;
AVLTree Right;
int Height;
};
AVLTree Insert(int Data, AVLTree T);//插入数值
Position RRRotation(Position A);//RR旋转
Position LLRotation(Position A);//LL旋转
Position LRRotation(Position A);//LR旋转
Position RLRotation(Position A);//RL旋转
int Max(int x1,int x2);//返回较大的那个数
int Height(Position p);//返回一个节点的高度
int main()
{
int N = 0,i = 0,data = 0;
AVLTree T = NULL;
scanf("%d",&N);
for(i = 0;i < N; i++)
{
scanf("%d",&data);
T = Insert(data , T);
}
printf("%d\n",T->Date);
//system("pause");
return 0;
}
Position LLRotation(Position A)
{
Position temp = NULL;
temp = A->Left;
A->Left = temp->Right;
temp->Right = A;
A->Height = Max(Height(A->Left),Height(A->Right))+1;
temp->Height = Max(Height(temp->Left),Height(temp->Right))+1;
return temp;
}
Position RRRotation(Position A)
{
Position temp = A->Right;
A->Right = temp->Left;
temp->Left = A;
A->Height = Max(Height(A->Left),Height(A->Right))+1;
temp->Height = Max(Height(temp->Left),Height(temp->Right))+1;
return temp;
}
Position LRRotation(Position A)
{
A->Left = RRRotation(A->Left);
return LLRotation(A);
}
Position RLRotation(Position A)
{
A->Right = LLRotation(A->Right);
return RRRotation(A);
}
AVLTree Insert(int Data, AVLTree T)
{
if(T == NULL)
{
T = (AVLTree)(malloc(sizeof(struct TreeNode)));
T->Date = Data;
T->Left = NULL;
T->Right = NULL;
T->Height = 0;
}
else if(Data < T->Date)//往左子树插入
{
T->Left = Insert(Data,T->Left);
if(Height(T->Left) - Height(T->Right) == 2)
{
if(Data < T->Left->Date)
T = LLRotation(T);
else
T = LRRotation(T);
}
}
else if(Data > T->Date) //往右子树插入
{
T->Right = Insert(Data,T->Right);
if(Height(T->Right) - Height(T->Left) == 2)
{
if(Data > T->Right->Date)
T = RRRotation(T);
else
T = RLRotation(T);
}
}
/*更新节点高度*/
T->Height = Max(Height(T->Left),Height(T->Right))+1;
return T;
}
int Max(int x1, int x2)
{
if (x1 == x2)
return x1;
else
return (x1>x2)? x1 : x2;
}
int Height(Position P)
{
if(P == NULL)
return -1;
else
return P->Height;
}
4.5
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
typedef int ElementType;
typedef struct TNode *Position;
typedef Position BinTree;
struct TNode{
ElementType Data;
BinTree Left;
BinTree Right;
};
void PreorderTraversal( BinTree BT ); /* 先序遍历,由裁判实现,细节不表 */
void InorderTraversal( BinTree BT ); /* 中序遍历,由裁判实现,细节不表 */
BinTree Insert( BinTree BST, ElementType X );
BinTree Delete( BinTree BST, ElementType X );
Position Find( BinTree BST, ElementType X );
Position FindMin( BinTree BST );
Position FindMax( BinTree BST );
int main()
{
BinTree BST, MinP, MaxP, Tmp;
ElementType X;
int N, i;
BST = NULL;
scanf("%d", &N);
for ( i=0; i<N; i++ ) {
scanf("%d", &X);
BST = Insert(BST, X);
}
printf("Preorder:"); PreorderTraversal(BST); printf("\n");
MinP = FindMin(BST);
MaxP = FindMax(BST);
scanf("%d", &N);
for( i=0; i<N; i++ ) {
scanf("%d", &X);
Tmp = Find(BST, X);
if (Tmp == NULL) printf("%d is not found\n", X);
else {
printf("%d is found\n", Tmp->Data);
if (Tmp==MinP) printf("%d is the smallest key\n", Tmp->Data);
if (Tmp==MaxP) printf("%d is the largest key\n", Tmp->Data);
}
}
scanf("%d", &N);
for( i=0; i<N; i++ ) {
scanf("%d", &X);
BST = Delete(BST, X);
}
printf("Inorder:");
InorderTraversal(BST);
printf("\n");
return 0;
}
/* 你的代码将被嵌在这里 */
void PreorderTraversal( BinTree BT )
{
if(BT==NULL) return;
else{
printf(" %c",BT->Data);
PreorderTraversal(BT->Left);
PreorderTraversal(BT->Right);
}
}
void InorderTraversal( BinTree BT )
{
if(BT==NULL) return;
else{
InorderTraversal(BT->Left);
printf(" %c",BT->Data);
InorderTraversal(BT->Right);
}
}
BinTree Insert( BinTree BST, ElementType X )
{
if(!BST)//如果BST为空的话,返回只有一个节点的树
{
BST=(BinTree)malloc(sizeof(struct TNode));
BST->Data=X;
BST->Left=NULL;
BST->Right=NULL;
}
else//如果BST不是为空的话
{//开始寻找要插入的位置
if(X<BST->Data)
BST->Left=Insert(BST->Left,X);
else if(X>BST ->Data)
BST->Right=Insert(BST->Right,X);
}
return BST;
}
BinTree Delete( BinTree BST, ElementType X )
{
BinTree Tmp;
if(!BST) printf("Not Found\n");
else{
if(X<BST->Data)
BST->Left=Delete(BST->Left,X);
else if(X>BST->Data)
{
BST->Right=Delete(BST->Right,X);
}
else//考虑如果找到这个位置,并且有左节点或者右节点或者没有节点三种情况
{
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 if(!BST->Right) BST = BST->Left;/*有左孩子,一定要加else,不然BST可能是NULL,会段错误*/
free(Tmp); /*如无左右孩子直接删除*/
}
}
}
return BST;
}
Position Find( BinTree BST, ElementType X )
{
if(!BST) return NULL;
if(BST->Data==X) return BST;
else if(X<BST->Data) {
return Find(BST->Left,X);
}
else if(X>BST->Data)
{
return Find(BST->Right,X);
}
return BST;
}
Position FindMin( BinTree BST )
{
if(BST!=NULL)
{
while(BST->Left)
BST=BST->Left;
}
return BST;
}
Position FindMax( BinTree BST )
{
if(BST!=NULL)
{
while(BST->Right)
BST=BST->Right;
}
return BST;
}