题目:编写程序,从键盘输入10个整数,逐个插入到二叉排序树中。根据你输入的整数序列,在草稿纸上画出该树。
(1)分别用先序、中序、后序遍历该树并输出结果,检查结果是否正确。
(2)输出该树的高度,检查结果是否正确。
(3)输出结点总数,检查结果是否正确。
(4)从树中删除一个整数,遍历该树并输出,检查结果是否正确。
重点:关于二叉树的各种实现
1.二叉树/二叉排序树结构体:
struct TreeNode{
int Data;
struct TreeNode*Left;
struct TreeNode*Right;
};
2.创建一颗空树:
Struct TreeNode*T;
T=NULL;
3.关于数插入二叉树:
(1)沿着树进行查找,如果X已存在树T中,则不做任何操作
(2)否则,将X插入到查找路径的最后一站(这一站是空树)
(3)最后,生成叶结点替换最后一站
struct TreeNode * Insert(struct TreeNode *T, ElementType X) {
if (T == NULL) {//如果树为空
T = malloc(sizeof(struct TreeNode));//创建一个新结点
T->Data = X;//将插入的数存入新结点中
T->Left = NULL;
T->Right = NULL;//左右子树皆为空,则代表插入的是叶节点
} else if (X < T->Data)//如果插入的数小于根节点数,则继续向根节点的左子树中查找, T->Left = Insert(T->Left, X);//直到在左子树的最后调用本函数然后创建新节点进行叶节点的插入形式
else if (X > T->Data)
T->Right = Insert(T->Right, X);
/*else X == T->Data */
return T;//插入成功后就返回插入成功后该数的根节点,因为根节点可能会发生改变
}
4.在树中删除:
(1)如果树中没有X,不做任何操作
(2)由于删除后根结点可能发生变化,因此该函数必须返回新的根结点指针
被删除结点有三种情形:
(3.1)叶结点//直接进行删除后没有其他任何操作
(3.2)有一个儿子//删除该节点后,将与该结点相连的后面的结点的位置改变
(3.3)有两个儿子//以删除点为根节点,在右子树中找到最小结点替换该结点,并删除最小结点,或者在左子树中找到最大结点替换该结点,并删除最大结点
struct TreeNode * Delete(struct TreeNode *T, ElementType X) {
struct TreeNode *q;
if (T == NULL)
return T;
else if (X < T->Data)
T->Left = Delete(T->Left, X);
else if (X > T->Data)
T->Right = Delete(T->Right, X);//对x进行查找
else { /* X == T->Data */
if (T->Left != NULL && T->Right != NULL) { /* 左右子树不空 */9有两个儿子
q = FindMin(T->Right);//在左子树中找到最小结点,并用指针q指向该结点
T->Data = q->Data;
T->Right = Delete(T->Right, q->Data);
} else { /* 左右子树至少有一个为空 */有一个儿子
q = T;
if (T->Left == NULL)
T = T->Right;
else if (T->Right == NULL)
T = T->Left;
free(q);//释放删除点q
}
}
return T;返回该树的根节点,因为删除后根节点可能会发生改变
}
5.树的最小结点的查找:
struct TreeNode*Findmin(struct TreeNode*T){
if(T==NULL)
return NULL;
return (T->Left==NULL)?T:Findmin(T->Left);
}
6.计算树的高度:
int Height(struct TreeNode*T) {
if(T==NULL)
return 0;
else
return 1+Max(Height(T->Left),Height(T->Right));
}
int Max(int a,int b){
if(a>b)
return a;
else
return b;}
7.计算树的结点总数:
int Count(struct TreeNode*T){
if(T==NULL)
return 0;
return 1+Count(T->Left)+Count(T->Right);
}
8.关于树的输出:
//先序遍历的输出
void Preorder(struct TreeNode*T){//先序遍历的输出
if(T!=NULL){
printf("%d ",T->Data);先输出根
Preorder(T->Left);再输出左子树
Preorder(T->Right);最后输出右子树
}
}
//中序遍历的输出
void Inorder(struct TreeNode*T){//中序遍历的输出
if(T!=NULL){
Preorder(T->Left);先输出左子树
printf("%d ",T->Data);再输出根
Preorder(T->Right);最后输出右子树
}
}
//后序遍历的输出
void Nextorder(struct TreeNode*T){//后序遍历的输出
if(T!=NULL){
Preorder(T->Left);先输出左子树
Preorder(T->Right);再输出右子树
printf("%d ",T->Data);最后输出根
}
}
实验源代码:
#include<stdio.h>
#include<stdlib.h>
struct TreeNode{
int Data;
struct TreeNode*Left;
struct TreeNode*Right;
};
//插入
struct TreeNode*Insert(struct TreeNode*T,int x) {
if(T==NULL){
T=malloc(sizeof(struct TreeNode));
T->Data=x;
T->Left=NULL;
T->Right=NULL;
}else if(x<T->Data)
T->Left=Insert(T->Left,x);
else if(x>T->Data)
T->Right=Insert(T->Right,x);
return T;
}
//查找最小结点
struct TreeNode*Findmin(struct TreeNode*T){
if(T==NULL)
return NULL;
return (T->Left==NULL)?T:Findmin(T->Left);
}
//删除结点
struct TreeNode*Delete(struct TreeNode*T,int m){
struct TreeNode*q;
if(T==NULL)
return T;
else if(m<T->Data)
T->Left=Delete(T->Left,m);
else if(m>T->Data)
T->Right=Delete(T->Right,m);
else{
if(T->Left!=NULL&&T->Right!=NULL){//左右子树不为空
q=Findmin(T->Right);
T->Data=q->Data;
T->Right=Delete(T->Right,q->Data);
}else{
q=T;
if(T->Left==NULL)
T=T->Right;
else if(T->Right=NULL)
T=T->Left;
free(q);
}
}
return T;
}
//计算高度
int Height(struct TreeNode*T) {
if(T==NULL)
return 0;
else
return 1+Max(Height(T->Left),Height(T->Right));
}
//两个数求最大值
int Max(int a,int b){
if(a>b)
return a;
else
return b;
}
//计算结点总数
int Count(struct TreeNode*T){
if(T==NULL)
return 0;
return 1+Count(T->Left)+Count(T->Right);
}
//先序遍历
void Preorder(struct TreeNode*T){
if(T!=NULL){
printf("%d ",T->Data);
Preorder(T->Left);
Preorder(T->Right);
}
}
//中序遍历
void Inorder(struct TreeNode*T){
if(T!=NULL){
Inorder(T->Left);
printf("%d ",T->Data);
Inorder(T->Right);
}
}
//后序遍历
void Postorder(struct TreeNode*T){
if(T!=NULL){
Postorder(T->Left);
Postorder(T->Right);
printf("%d ",T->Data);
}
}
void Print(struct TreeNode*T){
printf("先序遍历为:");
Preorder(T);
printf("\n");
printf("中序遍历为:");
Inorder(T);
printf("\n");
printf("后序遍历为:");
Postorder(T);
printf("\n");
}
void main(){
struct TreeNode*T;
T=NULL;//创建空树
printf("请输入十个结点数:");
int i=0,n;
for(;i<10;){
scanf("%d",&n);
T=Insert(T,n);
i=i+1;
}
int k;
printf("要删除的结点为:");
scanf("%d",&k);
Print(T);
printf("高度为: %d \n",Height(T));
printf("结点数为:%d \n",Count(T));
T=Delete(T,k);
printf("删除后的输出为:\n");
Print(T);
}