以下为本人自己总结整理的常考的二叉树的相关伪代码(C语言),部分题目未整理有待补充,且可能存在错误,欢迎批评指正!
目录
●求二叉树叶子结点个数、度为1的结点个数、度为2的结点个数(二叉链表存储)
●基于二叉链表存储,求二叉树高度/深度(采用层次遍历、非递归实现)
●基于二叉链表存储,求二叉树中根为x的子树的深度(层次遍历+队列)
●二叉树的自上而下自左至右的一般层次遍历(用队列的函数编写的非递归算法)
●已知二叉树的先序和中序序列,编写算法建立二叉树的二叉链链表(待补充)
●借助队列,二叉树以二叉链表存储,非递归判断一棵二叉树是否为完全二叉树(层次遍历的变形)
●二叉树以二叉链表形式存储,判断二叉树是否为二叉排序树(有点问题,仅供参考)
●二叉树以二叉链表形式存储,判断两棵二叉树是否同构(有待补充)
●二叉树采用二叉链表存储结构,求先序遍历序列中第k个结点的值(有待补充)
●二叉链式存储的二叉树,交换每个结点的左右孩子/左右子树-即二叉树的镜像
(一)二叉树
1、基础类题目
●二叉树的二叉链式存储定义
typedef struct BTNode{
ElemType data;
Struct BTNode *lchild,*rchild;
}BTNode,*BiTree;
●初始化二叉链表
bool InitBiTree(BiTree &T){
ElemType ch;
cin>>ch;//输入元素ch
if(ch==“#”)T=NULL;
else{
T=(BTNode*)malloc(sizeof(BTNode));
T→data=ch;
InitBiTree(T→lchild);
InitBiTree(T→rchild);
}
}
●二叉树的顺序存储定义(有待补充)
●求二叉树结点个数
int c=0;//c记录结点的个数
int CountNode(BiTree T){
if(T!=NULL){
CountNode(T→lchild);
CountNode(T→rchild);
c++;
}
return c;
}
int CountNode(BiTree T){
if(T==NULL)return 0;
int lc=CountNode(T→lchild);//lc记录左子树结点个数,
int rc=CountNode(T→rchild);//rc记录右子树结点个数
return lc+rc+1;//结点个数=左子树个数+右子树个数+根结点
}
●求二叉树叶子结点个数
int LeafNum1(BiTree T){//法一
int lc=0,rc=0;//lc记录左子树结点个数,rc记录右子树结点个数
if(T==NULL)return 0;
lc=LeafNum1(T→lchild);
rc=LeafNum1(T→rchild);
if(lc==0&&rc==0)return 1;
return lc+rc;
}
int n0=0;//记录叶子结点数
int LeafNum2(BiTree T){//法二
if(T!=NULL){
LeafNum2(T→lchild);
LeafNum2(T→rchild);
if(T→lchild==NULL&&T→rchild==NULL)n0++;
}
return n0;
}
●求二叉树叶子结点个数、度为1的结点个数、度为2的结点个数(二叉链表存储)
int n0=0,n1=0,n2=0;//定义变量记录度为0/1/2的结点个数
int NumCount(BiTree T){
if(T!=NULL){
NumCount(T→lchild);
NumCount(T→rchild);
if(T→lchild==NULL&&T→rchild==NULL)n0++;
if((T→lchild==NULL&&T→rchild!=NULL)||(T→lchild!=NULL&&T→rchild==NULL))n1++;
if(T→lchild!=NULL&&T→rchild!=NULL)n2++;
}
return 0;//结束
}
●求二叉树高度/深度(递归实现)
int TMaxDepth(BiTree T){//或BTNode root
if(T==NULL)return 0;
int ld=TDepth(T→lchild);//定义变量记录左子树高度
int rd=TDepth(T→rchild);//定义变量记录右子树高度
return ld>rd?ld+1:rd+1;
}
●基于二叉链表存储,求二叉树高度/深度(采用层次遍历、非递归实现)
int TMaxDepth(BiTree T){
if(T==NULL)return 0;
int level=0,last=0;//level记录当前所在的层数,last指向当前层的最右结点
int front=-1,rear=-1;
BiTree Q[QueueMaxSize];
BiTree t;
Q[++rear]=T;//根结点入队
while(front<rear){
t=Q[++front];
if(t→lchild!=NULL)Q[++rear]=t→lchild;
if(t→rchild!=NULL)Q[++rear]=t→rchild;
if(front==last){
level++;
last=rear;//last指向下一次
}
}
return level;
}
●基于二叉链表存储,求二叉树中根为x的子树的深度(层次遍历+队列)
int TMaxDepth(BiTree T){
if(T==NULL)return 0;
int ld=TDepth(T→lchild);//定义变量记录左子树高度
int rd=TDepth(T→rchild);//定义变量记录右子树高度
return ld>rd?ld+1:rd+1;
}
int Depth_x(BiTree T,int x){//借助层次遍历+队列+非递归
Queue Q;
InitQueue(Q);
EnQueue(Q,T);//根结点入队
BiTree t;
while(!isEmpty(Q)){
DeQueue(Q,t);//出队,队头元素赋值给t
if(t.data==x)return TMaxDepth(t);
if(t→lchild!=NULL)EnQueue(Q,t→lchild);
if(t→rchild!=NULL)EnQueue(Q,t→lchild);
}
return 0;
}
int Depth_x(BiTree T,int x,int depth){//递归
if(T=NULL)return 0;
if(T→data==x)return depth+1;
int ld=Depth_x(T→lchild,x,depth+1);
if(ld>0)return ld;
return Depth_x(T→rchild,x,depth+1);
}
●求二叉数第k层结点个数
int NlevelTree(BiTree T,int k){
int lc=0,rc=0;//记录左右子树结点个
if(T==NULL||k==0)return 0;
if(k==1)return 1;
lc=NlevelTree(T→lchild,k-1);
rc=NlevelTree(T→rchild,k-1);
return lc+rc;
}
●递归实现二叉树的先、中、后序遍历
void PreOrder(BiTree T){//先序
if(T==NULL)return;
visit(T);
PreOrder(T→lchild);
PreOrder(T→rchild);
}
void InOrder(BiTree T){//中序
if(T==NULL)return;
InOrder(T→lchild);
visit(T);
InOrder(T→rchild);
}
void PostOrder(BiTree T){//后序
if(T==NULL)return;
PostOrder(T→lchild);
PostOrder(T→rchild);
visit(T);
}
●借助栈非递归实现二叉树的先、中、后序遍历
void PreOrder(BiTree T){//先序
Stack S;
InitStack(S);
BiTree p=T;//遍历指针
while(p!=NULL||!isEmpty(S)){
if(p){
visit(p);
Push(p)
p=p→lchild;
}else{
Pop(S,p);
p=p→rchild;
}
}
}
void InOrder(BiTree T){//中序
Stack S;
InitStack(S);
BiTree p=T;//遍历指针
while(p!=NULL||!isEmpty(S)){
if(p){
Push(p)
p=p→lchild;
}else{
Pop(S,p);
visit(p);
p=p→rchild;
}
}
}
void PostOrder(BiTree T){//后序
Stack S;
InitStack(S);
BiTree p;//遍历指针
BTNode*r=NULL;//辅助指针,指向最近访问过的结点
while(p!=NULL||!isEmpty(S)){
if(p){
Push(S,p);
p=p→lchild;
}else{
GetTop(S,p);//读栈顶元素
if(p→rchild!=NULL && p→rchild!=r){//右孩子不为空,且未被访问过
p=p→rchild;
Push(S,p);
p=p→lchild;
}else{
Pop(S,p);
visit(p);
r=p;//记录最近访问过的结点
p=NULL;//结点访问完后重置p指针
}
}
}
}
●二叉树的自上而下自左至右的一般层次遍历(用队列的函数编写的非递归算法)
//递归实现
void LevelOrder(BiTree T){//非递归借助链队列实现
if(T==NULL)return;
LinkQueue Q;
InitQueue(Q);
BiTree p;
EnQueue(Q,T);//根结点入队列
while(!isEmpty(Q)){//队列不为空
Dequeue(Q,p);//出队
if(p→lchild!=NULL)EnQueue(Q,lchild);//左孩子入队
if(p→rchild!=NULL)EnQueue(Q,rchild);//右孩子入队
}
}
●二叉树的自下而上自右至左的层次遍历【栈的应用】
2、构建类题目
●已知二叉树的先序和中序序列,编写算法建立二叉树的二叉链链表(待补充)
3、判断类题目
●借助队列,二叉树以二叉链表存储,非递归判断一棵二叉树是否为完全二叉树(层次遍历的变形)
bool IsCompleteBiTree(BiTree T){
if(T==NULL)return ture;
bool flag=ture,ans=ture;
LinkQueue Q;
InitQueue(Q);
BiTree p;
EnQueue(Q,T);//根结点入队
while(!isEmpty(Q)){
DeQueue(Q,p);//出队
if(p→lchild==NULL){//左孩子为空,右孩子不为空
flag=false;
if(p→rchild!=NULL){
ans=flase;
}
}
else {//左孩子不为空
if(flag){//flag==Ture
EnQueue(Q,p→lchild);//左孩子入栈
if(p→rchild!=NULL)EnQueue(Q,p→rchild);
else flag=false;
}else ans=false;//左孩子的左孩子不为空但前面有叔叔为空
}
}
return ans;
}
●二叉树以二叉链表形式存储,判断二叉树是否为二叉排序树(有点问题,仅供参考)
bool IsBST(BiTree *root,BTNode*left,BTNode*right){//一次遍历法
if(root==NULL)return ture;
if(left!=NULL&&root→data<=left→data)return false;
if(right!=NULL&&root→data>right→data)return false;
return IsBST(root→left,left,root)&&IsBST(root→right,root,right);
}
●二叉树以二叉链表形式存储,判断两棵二叉树是否同构(有待补充)
4、查找类题目
●递归实现二叉树中按值查找(有待补充)
●二叉树采用二叉链表存储结构,求先序遍历序列中第k个结点的值(有待补充)
●求一般二叉树中两个结点的最近公共祖先(结点值均唯一)
/** * 二叉树最低公共祖先结点-自底向上解法 O(N) */
BTNode *btLCADown2Top(BTNode *root, BTNode *p, BTNode *q){
if(!root)return NULL;
if(root==p||root==q)return root;
BTNode *left=btLCADown2Top(root->left,p,q);
BTNode *right=btLCADown2Top(root->right,p,q);
if(left!=NULL&&right!=NULL)
return root;//如果p和q位于不同的子树
return left!=NULL?left:right;//p和q在相同的子树,或者p和q不在子树中
}
●求一棵给定节点至根节点的路径【栈的应用】
int flag=0;
void CherkNode(BiTree T,int target,Stack &S){
if(T==NULL)return;
if(flag==0)Push(S,T.data);
if(T.data==target){
flag=1;
return;
}
CherkNode(T->lchild,target,Stack &S);
CherkNode(T->rchild,target,Stack &S);
if(flag==0)Pop(S);//清除非要寻找路径上的栈中元素
}
void findPath(BiTree T,int target){
Stack S1,S2;
InitStack(S1);
InitStack(S2);
CherkNode(T,target);
BTNode*p;
while(!isEmpty(S1)){
Pop(S1,p);
Push(S2,p);
}
while(!isEmpty(S2)){
Pop(S2,p);
visit(p);
}
}
5、距离类题目
●求一棵树的最大宽度(有待补充)
(1)层序遍历法
(2)先序遍历法
●求二叉树的叶结点的带权路径长度WPL(有待补充)
6、其他
●二叉链式存储的二叉树,交换每个结点的左右孩子/左右子树-即二叉树的镜像
void swapbitree(bitree &bt){//从下到上,递归实现
if(bt==NULL)return;
bitree *p;
swapbitree(bt→lchild);//判不判断孩子是否存在均可
swapbitree(bt→rchild);
p=bt→lchild;
bt→lchild=bt→rchild;
bt→rchild=p;
}
void MirrorTree(BiTree &T){//从上到下,递归实现
if(T==NULL)return;
LNode *p=T→lchild;
T→lchild=T→rchild;
T→rchild=p;
if(T→lchild!=NULL)MirrorTree(T→lchild);
if(T→rchild!=NULL)MirrorTree(T→rchild)
}
(二)森林
●求孩子-兄弟表示法存储的森林的叶子结点数
typedef struct CSNode(){
int data;
struct CSNode*fch,*nsib;//孩子、兄弟
}CSNode,*CSTree;
int Leaves(CSTree T){
if(T==NULL)return 0;
if(T→fch==NULL)return 1+Leaves(T→nsib);//无左孩子为叶子结点,返回他和他兄弟的叶子结点总数
else return Leaves(T→fch)+Leaves(T→nsib);
}