#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");
system("PAUSE");
return 0;
}
/* 你的代码将被嵌在这里 */
//先序遍历
void PreorderTraversal(BinTree BT){
if (!BT)return;
printf(" %d", BT->Data);
PreorderTraversal(BT->Left);
PreorderTraversal(BT->Right);
return;
}
//中序遍历
void InorderTraversal(BinTree BT){
if (!BT)return;
InorderTraversal(BT->Left);
printf(" %d", BT->Data);
InorderTraversal(BT->Right);
return;
}
//递归插入
BinTree Insert(BinTree BST, ElementType X){
//如果是一个空节点
if (!BST){
BST = (BinTree)malloc(sizeof(struct TNode));//既然为空所以要生成一个
BST->Data = X;
BST->Left = NULL;
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);//递归插入右子树
}
//如果相等说明X已经存在,什么也不做
}
return BST;
}
//递归删除
BinTree Delete(BinTree BST, ElementType X){
Position temp;
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{//当前BST就是要删除的节点(找到的边界)
/*两种情况:有两个子节点,有一个子节点*/
//有两个子节点用临点(左子树最大的/右子树最小的,用findmax,findmin进入左右子树寻找)代替,删除临点
if (BST->Left && BST->Right){//要被删除的节点有左右两个孩子,就从右子树中找最小的数填充删除的节点
temp = FindMin(BST->Right);//找最小
BST->Data = temp->Data;//填充删除的节点
BST->Right = Delete(BST->Right, temp->Data);//删除拿来填充的那个节点,挂接到父亲的左孩子上
}
/*if (BST->Left && BST->Right){//要被删除的节点有左右两个孩子,就从左子树中找最大的数填充删除的节点
temp = FindMax(BST->Left);//找最大
BST->Data = temp->Data;//填充删除的节点
BST->Left = Delete(BST->Left, temp->Data);//删除拿来填充的那个节点,挂接到父亲的右孩子上*/
else{//只有一个子节点:重接
temp = BST;
if (!BST->Left){//只有右节点
BST = BST->Right;//直接赋值就可以
}
else if (!BST->Right){//只有左节点
BST = BST->Left;//直接赋值就可以
}
free(temp);//如果啥也没有直接删除就可以,当然上面两种情况赋值后也要删除
}
}
}
return BST;
}
Position Find(BinTree BST, ElementType X){
while (BST){
if (BST->Data == X)break;
else if (X > BST->Data)BST = BST->Right;
else BST = BST->Left;
}
return BST;
}
Position FindMin(BinTree BST){
if (!BST)return BST;
while (BST->Left){
BST = BST->Left;
}
return BST;
}
Position FindMax(BinTree BST){
if (!BST)return BST;
while (BST->Right){
BST = BST->Right;
}
return BST;
}
0.结构体
typedef int ElementType;
typedef struct TNode *Position;
typedef Position BinTree;
struct TNode{
ElementType Data;
BinTree Left;
BinTree Right;
};
1.先序和中序遍历
//先序遍历
void PreorderTraversal(BinTree BT){
if (!BT)return;
printf(" %d", BT->Data);
PreorderTraversal(BT->Left);
PreorderTraversal(BT->Right);
return;
}
//中序遍历
void InorderTraversal(BinTree BT){
if (!BT)return;
InorderTraversal(BT->Left);
printf(" %d", BT->Data);
InorderTraversal(BT->Right);
return;
}
2.找X,找最小和找最大
Position Find(BinTree BST, ElementType X){
while (BST){
if (BST->Data == X)break;
else if (X > BST->Data)BST = BST->Right;
else BST = BST->Left;
}
return BST;
}
Position FindMin(BinTree BST){
if (!BST)return BST;
while (BST->Left){
BST = BST->Left;
}
return BST;
}
Position FindMax(BinTree BST){
if (!BST)return BST;
while (BST->Right){
BST = BST->Right;
}
return BST;
}
2.1递归的思想就是
Position FindMax( BinTree BST ){
if(!BST)return NULL;
else if(!BST->Right)return BST;
else return FindMax(BST->Right);
}
3.递归插入
3.1边界条件:当这是一个空节点时,在此处插入
3.2小于向左遍历;大于向右遍历;一直到边界条件
BST->Left = Insert(BST->Left, X);
含义:为了挂接
当BST->Left不空时,返回的就是原来的BST-Left,那么BST->Left=BST->Left一定成立;当BST->Left空时,返回的就是插入元素X后的BST->Left,原来BST->Left接着NULL的就会变成插入的X,此为挂接
//递归插入
BinTree Insert(BinTree BST, ElementType X){
//如果是一个空节点
if (!BST){
BST = (BinTree)malloc(sizeof(struct TNode));//既然为空所以要生成一个
BST->Data = X;
BST->Left = NULL;
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);//递归插入右子树
}
//如果相等说明X已经存在,什么也不做
}
return BST;
}
4.递归删除
1如果树空那么没找到;
2如果树没空
2.1如果根不是删除节点那么根据排序,递归到它的某一子树为根的情况下重新判断
2.2如果根是删除节点那么删除
所以当根节点就是删除节点时执行删除;否则递归
4.1边界条件
找到/没找到
4.1.1如果最终树为空,说明没找到(边界1)
if (!BST){//边界条件
printf("Not Found\n");//如果最终树为空,说明没有
}
4.1.2如果当前树还未空
4.1.2.1序号<根,根的左子树挂接到 进入他的左子树递归删除 后重接的树的根
if (X < BST->Data){
BST->Left = Delete(BST->Left, X);//从左子树递归删除,挂接到父亲的左孩子上
}
4.1.2.2序号>根,根的右子树挂接到 进入他的右子树递归删除 后重接的树的根
else if (X > BST->Data){
BST->Right = Delete(BST->Right, X);//从右子树递归删除,挂接到父亲的右孩子上
}
4.1.2.3否则就是序号=根,即找到了以要求删除的节点为根的树(边界2)
两种情况:有两个子节点,有一个子节点
4.1.2.3.1有两个子节点(两种方法)
用临点(左子树最大的/右子树最小的,用findmax,findmin进入左右子树寻找)代替,删除临点
4.1.2.3.1.1从右子树中找最小的数填充删除的节点
1.找右子树最小
2.用最小填充删除节点
3.递归删除拿来填充的那个节点,并把根的右孩子挂接到 以根的右孩子为根,递归删除拿来填充的那个节点重接后的树
if (BST->Left && BST->Right){//要被删除的节点有左右两个孩子,就从右子树中找最小的数填充删除的节点
temp = FindMin(BST->Right);//找最小
BST->Data = temp->Data;//填充删除的节点
BST->Right = Delete(BST->Right, temp->Data);//删除拿来填充的那个节点,挂接到父亲的左孩子上
}
4.1.2.3.1.2从左子树中找最大的数填充删除的节点
1.找左子树最大
2.用最大填充删除节点
3.递归删除拿来填充的那个节点,并把根的左孩子挂接到 以根的左孩子为根,递归删除拿来填充的那个节点重接后的树
if (BST->Left && BST->Right){//要被删除的节点有左右两个孩子,就从左子树中找最大的数填充删除的节点
temp = FindMax(BST->Left);//找最大
BST->Data = temp->Data;//填充删除的节点
BST->Left = Delete(BST->Left, temp->Data);
4.1.2.3.2只有一个节点:重接
只需考虑重接,由于递归返回了重接后的树的根,所以所有情况的树到此都已经有了挂接的公式
1.1若删除节点不是根节点,那么在寻找该节点的过程中必定有挂接的步骤
1.2若删除节点是根节点
1.2.1它有两个孩子,那么在删除填充点的时候也必定有挂接的步骤
1.2.2它只有一个节点,那么直接让根变为它的孩子即可,没有需要挂接的部分
2.temp暂存删除节点BST,BST变成重接过的树
3.释放删除节点temp的空间
else{//只有一个子节点:重接
temp = BST;
if (!BST->Left){//只有右节点
BST = BST->Right;//直接赋值就可以
}
else if (!BST->Right){//只有左节点
BST = BST->Left;//直接赋值就可以
}
free(temp);//如果啥也没有直接删除就可以,当然上面两种情况赋值后也要删除
}
总结:
BinTree Delete(BinTree BST, ElementType X){
Position temp;
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{//当前BST就是要删除的节点(找到的边界)
/*两种情况:有两个子节点,有一个子节点*/
//有两个子节点用临点(左子树最大的/右子树最小的,用findmax,findmin进入左右子树寻找)代替,删除临点
if (BST->Left && BST->Right){//要被删除的节点有左右两个孩子,就从右子树中找最小的数填充删除的节点
temp = FindMin(BST->Right);//找最小
BST->Data = temp->Data;//填充删除的节点
BST->Right = Delete(BST->Right, temp->Data);//删除拿来填充的那个节点,挂接到父亲的左孩子上
}
/*if (BST->Left && BST->Right){//要被删除的节点有左右两个孩子,就从左子树中找最大的数填充删除的节点
temp = FindMax(BST->Left);//找最大
BST->Data = temp->Data;//填充删除的节点
BST->Left = Delete(BST->Left, temp->Data);//删除拿来填充的那个节点,挂接到父亲的右孩子上*/
else{//只有一个子节点:重接
temp = BST;
if (!BST->Left){//只有右节点
BST = BST->Right;//直接赋值就可以
}
else if (!BST->Right){//只有左节点
BST = BST->Left;//直接赋值就可以
}
free(temp);//如果啥也没有直接删除就可以,当然上面两种情况赋值后也要删除
}
}
}
return BST;
}