文章目录
一、二叉树的遍历
1.先、中、后序遍历
2.层序遍历
二、二叉搜索树
1.定义
2.Find(查找)
3.Insert(插入)
4.Delete(删除)
typedef struct tnode *Position;
typedef Position Bintree;
struct tnode {
int data;
Bintree left;
Bintree right;
};
一、二叉树的遍历
1.先、中、后序遍历
(1)先序遍历
遍历过程为:
- 访问根结点;
- 先序遍历其左子树
- 先序遍历其右子树
void PreorderTraversal(Bintree BT)
{
if(BT)
{
printf("%d",BT->data);
PreorderTraversal(BT->left);
PreorderTraversal(BT->right);
}
}
例:
顺序是:ABDFECGHI
(2)中序遍历
遍历过程为:
- 中序遍历其左子树
- 访问根结点
- 中序遍历其右子树
void InorderTraversal(Bintree BT)
{
if(BT) {
InorderTraversal(BT->left);
printf("%d",BT->data);
InorderTraversal(BT->right);
}
}
例:
顺序是:DBEFAGHCI
(3)后序遍历
遍历过程为:
- 后序遍历其左子树
- 后序遍历其右子树
- 访问跟结点
void PostorderTraversal(Bintree BT)
{
if(BT) {
printf("%d",BT->data);
PostorderTraversal(BT->left);
PostorderTraversal(BT->right);
}
}
例:
顺序是:DEFBHGICA
2、层序遍历
遍历从根结点开始,首先,将根结点入队,然后开始执行循环:结点出队,访问该结点,其左右儿子入队。
层序遍历基本过程:先根结点入队,然后:
- 从队列中取出一个元素
- 访问该元素所指结点
- 若该元素所指的左、右孩子的指针顺序入队
void levelordertravelsal(Bintree BT)
{
Queue Q;
Bintree T;
if(!BT) {
return;//若是空树直接返回
}
Q=CreateQueue(Maxsize);//创建并初始化队列
AddQ(Q,BT);
while(!isEmptyQ(Q)) {
T=DeleteQ(Q);//出队
printf("%d\n",T->data);
if(T->left)
AddQ(Q,T->left);//入队
if(T->right)
AddQ(Q,T->right);
}
}
二、二叉搜索树
1、定义
二叉搜索树(也称二叉排序树,二叉查找树):一颗二叉树,可以为空;如果不为空,满足以下性质:
1.非空左子树的所有键值小于根结点的键值。
2.非空右子树的所有键值大于其跟结点的键值。
3.左右子树都是二叉搜索树。
2、Find(查找)
若搜索树非空,则根结点关键字和X进行比较,并进行不同处理:
- 若X小于根结点键值,只需在左子树中继续搜索。
- 如果X小于根结点的键值,在右子树中进行继续搜索。
- 若两者比较结果是相等,搜索完成,返回指向此结点的指针。
用尾递归实现:
Position Find(int x,Bintree BST)
{
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 Find(int x,Bintree BST)
{
while(BST) {
if(x>BST->data) {
BST=BST->right;
} else if(x<BST->right) {
BST=BST->left;
} else {
return BST;
}
}
return NULL;
}
查找最大和最小元素:
1.最大元素一定是树的最右分支的端结点上:
Position Findmin(int x,Bintree BST)
{
if(!BST) {
return NULL:
} else if(!BST->left) {
return BST;//找到最左叶结点并返回
} else if(!BST->right) {
return Findmin(BST->left);//沿左分支继续查找
}
}
2.最小元素一定是在树的最左分支的端结点上:
Position Findmax(int x,Bintree BST)
{
if(BST) {
while(BST->right) {
BST=BST->right;//沿右分支继续查找,直到最右叶结点
}
}
return BST;
}
3、Insert(插入)
关键在于找到元素应该插入的位置
Bintree Insert(int x,Bintree BST)
{
if(!BST) {
//若原树为空,生成并返回一个结点的二叉搜索树
BST=malloc(sizeof(struct tnode));
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;
}
4、Delete(删除)
Bintree Delete(int X,Bintree BST,Position Temp)
{
if(!BST )
printf("未找到要删除的结点\n");
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) {//被删除结点有左右两个子结点
Temp=Findmin(BST->right);//在右子树中找最小的元素填充删除结点
BST->Data=Temp->Data;
BST->Right=Delete(BST->data,BST->right);//在删除结点的右子树中删除最小元素
} else{ //被删除的结点只有一个结点或者无子结点
Temp=BST;
if(!BST->left) {//有左子节点或者无子结点
BST=BST->right;
}
else if(!BST->right) {//有左孩子或无子结点
BST=BST->left;
}
free(Temp);
}
}
return BST;
}
考虑三种情况:
1.删除叶结点
直接删除,并再修改其父结点指针,置为NULL。
2.要删除的结点只有一个孩子结点
将其父结点的指针指向要删除结点的孩子结点
3.要删除的结点有左右两颗子树
用另一个结点替代被删除结点,右子树的最小元素或者左子树的最大元素