二叉树
1.建立
第一种情况(给定先序遍历的字符序列,其中空结点用,给出)
char pre[55];
int l;
struct node
{
char data;
struct node*left;
struct node*right;
};
struct node* cre()
{
struct node*root;
char p;
p=pre[l++];
if(p==',') return NULL;
else
{
root=(struct node*)malloc(sizeof(struct node));
root->data=p;
root->left=cre();
root->right=cre();
}
return root;
}
int main()
{
while(~scanf("%s",pre))
{
l=0;//每一次开始都要清零
struct node*root;
root=cre();
}
return 0;
}
第二种情况:(已知先序遍历和中序遍历(或者后序和中序),其中空结点不给出)
char s1[55],s2[55];
int len;
struct node
{
char data;
struct node*left,*right;
};
struct node* cre(int m,char*a,char*b)//m是字符序列的长
{
int i;
struct node*root;
if(m==0) return NULL;
else
{
root=(struct node*)malloc(sizeof(struct node));
root->data=a[0];
for(i=0; i<m; i++)
{
if(b[i]==a[0]) break;//在中序遍历里找根
}
root->left=cre(i,a+1,b);
root->right=cre(m-1-i,a+1+i,b+1+i);
}
return root;
}
int main()
{
struct node*root;
int n;
scanf("%d",&n);
while(n--)
{
len=0;
scanf("%s",s1);
scanf("%s",s2);
int l=strlen(s1);
root=cre(l,s1,s2);
}
return 0;
}
2.遍历(二叉树和二叉排序树和平衡二叉树的遍历方式相同)
void xian(struxt node*root)//先序遍历
{
if(root)
{
printf("%c",root->data);
xian(root->left);
xian(root->right);
}
}
void zhong(struxt node*root)//中序遍历
{
if(root)
{
printf("%c",root->data);
zhong(root->left);
zhong(root->right);
}
}
void hou(struct node*root)//后序遍历
{
if(root)
{
hou(root->left);
hou(root->right);
printf("%c",root->data);
}
}
还有一个层序遍历单独拿出来讲
3.叶子问题
①求叶子个数;
int sum=0;//多组输出一定sum定义在外面,因为后续函数里面会多次递归调用
void yezi(struct node*root)
{
if(root)
{
if(root->left==NULL&&root->right==NULL)
sum++;
yezi(root->left);
yezi(root->right);
}
}
② 按从上到下从左到右的顺序输出二叉树的叶子结点;(层序)
void yezi(struct node*root)
{
int front=0,rare=0;
int flag;
struct node*q[55];
q[rare++]=root;
while(rare>front)
{
if(q[front])
{
flag=0;
q[rare++]=q[front]->left;
if(q[front]->left==NULL) flag++;
q[rare++]=q[front]->right;
if(q[front]->right==NULL) flag++;
if(flag==2) printf("%c",q[front]->data);
}
front++;
}
}
4.二叉树的高度和深度
单独讲
二叉排序树BST
二叉查找树,也称二叉搜索树,或二叉排序树。
1.建立
struct node
{
int data;
struct node*l,*r;
};
struct node*cre(struct node*root,int x)//每次建立一个结点
{
if(root==NULL)
{
root=(struct node*)malloc(sizeof(struct node));
root->data=x;
root->l=NULL;
root->r=NULL;
}
else
{
if(x>root->data)
root->r=cre(root->r,x);
else if(x<=root->data)//若所给数据有相同值,这里要考虑=;
root->l=cre(root->l,x);
}
return root;
};
2.判断两序列是否为同一棵二叉排序树
int flag=0;
void judge(struct node*root1,struct node*root2)
{
//flag=0表示是同一棵二叉排序树,flag=1不是;
if(root1&&root2)
{
if(root1->data!=root2->data)
{
flag=1;return;}//一旦不同立马返回;
judge(root1->l,root2->l);
judge(root1->r,root2->r);
}
}
3.查找
二叉排序树的查找最差的情况与顺序查找相同,ASL=(n+1)/2;最好的情况与折半查找相同,ASL=logn。
int find(struct node*root,int x)
{
if(root==NULL) return 0;
else if(x==root->data) return 1;
else if(x<root->data) return find(root->l,x);
else return find(root->r,x);
}
4.插入
struct node*insert(struct node*root,int x)
{
if(root==NULL)
{
root=(struct node*)malloc(sizeof(struct node));
root->data=x;
root->l=root->r=NULL;
}
else
{
if(x<=root) root->l=insert(root->l,x);
else root->r=insert(root->r,x);
}
return root;
}
5.删除
方法一:
若所要删除的结点不存在,则不作操作;
否则,分三种情况进行讨论:
(1)若所删结点是叶子结点,直接删除即可;
(2)所删结点只有左子树或只有右子树,则将其相应的左孩子或右孩子代替其位置即可;
(3)所删结点既有左子树也有右子树,因为二叉排序树的中序遍历结果为有序序列,替换所要删除结点的位置其实就是该结点的直接前驱或直接后继结点,而替换结点要么是叶子结点,要么就是只有左子树或右子树的情况。
(其左子树的最右下角的结点即为该结点的直接前驱结点;其右子树的最左下角的结点即为待删结点的直接后继结点)
链接:https://blog.csdn.net/weixin_39651041/article/details/80022177
方法二:
链接:https://www.cnblogs.com/multhree/p/10510383.html
一般来说,需要根据下面几种情况分别进行处理: 需要删除的节点没有左儿子,那么就把右儿子提上去。
需要删除的节点的左儿子没有右儿子,那么就把左儿子提上去。 以上两种情况都不满足的话,就把左儿子的子孙中最大的节点提到需要删除的节点上。