二叉树宽度
定义:以二叉链形式存储的二叉树,其结点之间路径的最大值称为树的宽度。
从这张图上可以得到,最远路径是
4
→
7
4\rightarrow7
4→7
容易想到,左子树深度的最大值加上右子树深度最大值不就是最远路径了吗?
调用求树深度的函数不就轻而易举?
int getDepth(BinTree T)
{
int LH,RH,MAXH;
if(T){
LH=getDepth(T->Lchild);
RH=getDetph(T->Rchild);
MAH=LH>RH?LH:RH;
return MAXH+1;
}
return 0;
}
int getWidth(BinTree T)
{
int LH,RH;
if(T){
LH=getDepth(T->Lchild);
RH=getDepth(T->Rchild);
return LH+RH+1;
}
return 0;
}
但问题到这里就结束了吗?-----没那么简单
如果树是这种结构,上述代码的结果是3而该树的直径应为4。
思路:在遍历的过程中加入“全局”变量,记录全局最大距离,而不是经过根节点的最大深度
修改如下
int getDepth(BinTree T,int *MaxHeight)
{
int LH,RH;
if(T){
LH=getDepth(T->Lchild,MaxHeight);
RH=getDetph(T->Rchild,MaxHeight);
*MaxHeight=max(LH+RH,*MaxHeight);
return max(LH,RH)+1;
}
return 0;
}
int getWidth(BinTree T)
{
int MaxHeight=0;
getDepth(T,&MaxHeight);
return MaxHeight;
}
去除二叉树叶子节点
BTNode* RemoveLeave(BTNode *BT)
{
if(!BT)
return NULL;
else if(!BT->Left&&!BT->Right)
return NULL;
else{
BTNode newBT=new BTNode;
newBT=BT;
newBT->Left= RemoveLeave(BTNode BT->Left);
newBT->Right= RemoveLeave(BTNode BT->Right);
return newBT;
}
}
根据二叉树的后序和中序得出二叉树的前序
假如给定后序和中序如下
2 | 3 | 1 | 5 | 7 | 6 | 4 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
思路:
建立pre,in,post数组,preL,inL,postL分别对应当前子段数组的最左边的位置
将post当前子段的最后一个元素赋值给pre当前子段的第一个元素。
将区间划分成两部分后继续递归,则得到答案
void getans(int preL,int inL,int postL,int n) //根据后序得到前序
{
if(n==0) return; //当n=0时直接return
if(n==1) {pre[preL]=post[postL];return;} //只有一个元素时
int root=post[postL+n-1],i;
pre[preL]=root; //最后一个元素赋值给第一个
for(i=0;i<n;i++) if(in[inL+i]==root) break; //根据中序划分
int L=i,R=n-L-1;
getans(preL+1,inL,postL,L); //递归左半部分
getans(preL+L+1,inL+L+1,postL+L,R); //递归右半部分
}
void getans(int preL,int inL,int postL,int n)//根据前序和中序得到后序
{
if(n==0) return;
if(n==1) {post[postL]=pre[preL];return;} //这里反序
int root=pre[preL],i; //只改这两步
post[postL+n-1]=root; //只改这两步
for(i=0;i<n;i++) if(in[inL+i]==root) break;
int L=i,R=n-L-1;
getans(preL+1,inL,postL,L);
getans(preL+L+1,inL+L+1,postL+L,R);
}
将二叉树的叶子结点从左到右形成链表
思路:中序遍历的应用,当遍历到BT结点时,连接左右孩子,递归。
LinkList head,pre=NULL;
LinkList InOrder(BinTree BT)
{
if(BT){
InOrder(BT->Left);
if(!BT->Left&&!BT->Right){//叶子
if(pre==NULL){
head=BT;
pre=BT;
}else{
pre->Right=BT;
pre=BT;
}
}
InOrder(BT->Right);
pre->Right=NULL;
}
return head;
}
二叉搜索树的应用
递归表示
typedef struct BinTree Position;
//查找
Position Find(ElemType X,BinTree BST)
{
if(!BST) return NULL;
if(BST->Data==X) return BST;
else if(BST->Data>X) Find(X,BST->Left);
else Find(X,BST->Right);
}
//插入值为X的结点
BinTree Insert(ElemType X,BinTree BST)
{
if(!BST) {
BST=(BinTree)malloc(sizeof(BinTree));
BST->Data=X;
BST->Left=BST->Right;
}else if(X<BST->Data) BST->Left=Insert(X,BST->Left);
else if(X>BST->Data) BST->Right=Insert(X,BST->Right);
return BST;
}
//删除值为X的结点
BinTree Delete(ElemType X,BinTree BST)
{
Position Tmp;
if(!BST) printf("Error");
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){
Tmp=FindMin(X,BST->Right);
BST->Data=Tmp->Data;
BST->Right=Delete(BST->Data,BST->Right);
}else{/*只有1个孩子或无子结点*/
Tmp=BST;
if(!BST->Left) //左边空,右儿子替代
BST=BST->Right;
else if(!BST->Right)
BST=BST->Left;
free(Tmp);
}
return BST;
}