二叉树创建(层序)
与层序有关的要用到队列,因此创建一个队列
Bintree creat()//二叉树层序创建(想用C++STL库的,到时候改成new)
{
int data;
BinTree BT,T;
scanf("%d",&data);
if(data!=0)
{
BT=(BinTree)malloc(sizeof(struct TNode));
BT->data=data;
BT->left=NULL;
BT->right=NULL;
q.push(data);
}
else return NULL;
while(!q.empty())
{
T=q.front();
scanf("%d",&data);
if(data==0) T->left=NULL;
else{
T->left=(BinTree)malloc(sizeof(struct TNode));
T->left->data=data;
q.push(T->left)
}
scanf("%d",&data);
if(data==0) T->right=NULL;
else{
T->right=(BinTree)malloc(sizeof(struct TNode));
T->right->data=data;
q.push(T->right)
}
}
return BT;
}
输出二叉树中所有叶结点
分析:用到的知识是二叉树的遍历,在遍历的时候加条件(左子树和右子树都为空即可)
void Preorderprintleaves(BinTree BT)
{
if(BT)
{
if(!BT->left&&!BT->right)
{
printf("%d",BT->data);
}
Preorderprintleaves(BT->left);
Preorderprintleaves(BT->right);
}
}
递归求二叉树高度
分析:求二叉树高度=求左子树高度和求右子树高度中最大的那个=…=…(递推下去吧)
int getHeight(BinTree BT)
{
int HL,HR,MAXH;
if(BT)
{
HL=getHeight(BT->left);
HR=getHeight(BT->right);
MAXH=HL>HR?HL:HR;
return(MAXH+1);
}
else return 0;/*空树高度为0*/
}
二叉搜索树(BST)的查找
注意返回的还是指针,指向二叉树的结点
如果发现BST为空了(查完了还没找到) 返回查找失败
typedef struct node *Bintree;
struct node{
int data;
Bintree left,right;
};
Bintree find(Bintree BST,int x)
{
if(!BST) return NULL;
else
{
if(BST->data==x) return BST;//返回当前结点的地址
else if(BST->data>x) return find(BST->left,x);
else if(BST->data<x) return find(BST->right,x);
}
}
查找BST的最大最小值
方法一:递归
方法二:迭代
利用BST的性质,最小元素一定在树的最左分支的端结点上
Bintree FindMax(Bintree BST)
{
if(!BST) return NULL;
else if(BST->right==NULL) return BST;
else return FindMax(BST->right);
}
Bintree findmin(Bintree BST)
{
if(BST)
{
while(BST->left)
{
BST=BST->left;
}
return BST;
}
}
BST的插入
操作类似于查找,必须记得分情况
原树为空,那么建一个只有一个结点的树
原树不为空,递归寻找插入的位置
最后返回的也是指针,指向插入元素的位置
(递归真是个好东西啊)
Bintree insert(Bintree BST,int x)
{
if(!BST)
{
BST=(Bintree)malloc(sizeof(struct node));
BST->data=x;
BST->left=BST->right=NULL;
}
else
{
if(BST->data>x)
{
insert(BST->left,x);
}
else if (BST->data<x)
{
insert(BST->right,x);
}
}
return BST;
}
二叉搜索树的插入其实还是很方便的,因为数据的插入后一定接在树下方,不影响其他结点,但是删除就相对复杂了,一个结点的删除会影响其他结点的位置
二叉搜索树的删除
三种情况
1.删除的是叶结点
2.删除的结点只有一个孩子结点
3.删除的结点有左右两颗子树,那么要转换为第二种情况:选取左子树中的最大元素或者右子树的最小元素(利用上面讲的findmax和findmin函数鸭)
Bintree delete(Bintree BST,int x)
{
//先找到要被删除的元素
Bintree tmp;
if(!BST) return printf("未找到");
else
{
if(x<BST->data) delete(BST->left,x);
else if(x>BST->data) delete(BST->right,x);
else if(x==BST->data)
{
if(BST->left&&BST->right)
/*有两个子节点*/
{
tmp=findmin(BST->right);
BST->data=tmp->data;
/*重要过程?递归(why?如何理解?)*/
BST->right=delete(BST->right,BST->data);
}
else
{
tmp=BST;
if(!BST->left)//只有右孩子
BST=BST->right;
else
{
BST=BST->left;
}
free(tmp);//原来数据被删除,指针改变方向
}
}
return BST;
}
}
//最后返回值还是指针,指向的是删除后的结点,原来的数据不复存在