二叉树的相关操作

1.定义二叉树的结构体

#pragma once 

#include 

typedef char TreeNodeType; 

typedef struct TreeNode { 
 TreeNodeType data; 
 struct TreeNode* lchild; //左孩子指针
 struct TreeNode* rchild; //右孩子指针
} TreeNode; 

2.初始化二叉树

void TreeInit(TreeNode** root){
    if(root==NULL){
        return;
    }   
    *root=NULL;
}

3.创建二叉树的节点

开辟动态内存空间来保存节点信息。

TreeNode* CreateTreeNode(TreeNodeType value){
    TreeNode* new_node=(TreeNode*)malloc(sizeof(TreeNode));
    new_node->data=value;
}

4.通过递归的方法来前序遍历访问二叉树

前序遍历:先访问根结点,再访问左子树,最后访问右子树

void PreOrder(TreeNode* root){
    if(root==NULL){
        printf("#");
        return;
    }
    printf("%c",root->data);
    PreOrder(root->lchild);
    PreOrder(root->rchild);
}

5,通过递归的方法来中序遍历访问二叉树

中序遍历:先访问左子树,再访问根结点,最后访问右子树

void InOrder(TreeNode* root){
    if(root==NULL){
        return; 
    }
    InOrder(root->lchild);
    printf("%c ",root->data);
    InOrder(root->rchild);
} 

6,通过递归的方法来后续遍历二叉树

后序遍历:先访问左子树,再访问右子树,最后访问根节点

void PostOrder(TreeNode* root){
    if(root==NULL){
        return;
    }
    PostOrder(root->lchild);                                                    
    PostOrder(root->rchild);
    printf("%c ",root->data);

}

7.层序遍历二叉树

层序遍历思想:利用队列


void LevelOrder(TreeNode* root){
    seqqueue q;
    seqqueuePush(&q,root);                                                      
    //2.循环的取队首元素
    TreeNode* cur=NULL;
    while(seqqueueTop(&q,&cur)){
    //3.访问队首元素并出队列
        printf("%c ",cur);
        seqqueuePop(&q);
        if(cur->lchild!=NULL){
            seqqueuePush(&q,cur->lchild);
        }
        if(cur->rchild!=NULL){
            seqqueuePush(&q,cur->rchild);
        }
    //4.将队首元素的左子树节点和右子树节点都依次入队列
    //5.进入下一次循环,直到队列为空,说明遍历完了
    }
}

8.通过给定的前序遍历的字符串数组来创建二叉树

前提:前序遍历的节点里若左右子树不存在则用‘#’代替

TreeNode* _TreeCreate(TreeNodeType array[],size_t size,size_t* index,TreeNodeType null_node){
    if(index==NULL){
        return NULL;
    }                                                                                
    if(*index>=size){
        return NULL;
    }
    if(array[*index]==null_node){
        return NULL;
    }
    TreeNode* new_node=CreateTreeNode(array[*index]);
    ++(*index);
    new_node->lchild=_TreeCreate(array,size,index,null_node);
    ++(*index);
    new_node->rchild=_TreeCreate(array,size,index,null_node);
    return new_node;
}
TreeNode* TreeCreate(TreeNodeType array[],size_t size,TreeNodeType null_node){
      size_t index=0;
      return _TreeCreate(array,size,&index,null_node);
    
}

测试代码

void TestCreateTree(){
    TestHeader;
    TreeNode* root;
    TreeNodeType array[]="abd##e##c#f##";//前序遍历的结果
    root=TreeCreate(array,strlen(array),'#');
    printf("前序遍历为:");
    PreOrder(root);
    printf("\n");
    printf("中序遍历为:");
    InOrder(root);
    printf("\n");

    printf("后序遍历为:");
    PostOrder(root);                                                                 
    printf("\n");

}

9.销毁二叉树

void TreeDestroy(TreeNode** root){
    if(root==NULL){
        return ;
    }
    if(*root==NULL){
        return;
    }
    TreeNode* to_delete=*root;
    TreeDestroy(&to_delete->lchild);
    TreeDestroy(&to_delete->rchild);                                                 
    Destroy(to_delete);
}

10.克隆二叉树

TreeNode* TreeClone(TreeNode* root){                                                 
    if(root==NULL){
        return NULL;
    }
    TreeNode* new_node=CreateTreeNode(root->data);//创建新的二叉树根结点
    new_node->lchild=TreeClone(root->lchild);
    new_node->rchild=TreeClone(root->rchild);
    return new_node;
}

11.求一棵树中节点的个数

思想:节点的个数=根结点+根结点所有的左子树节点个数+根结点所有的右子树节点个数

size_t TreeSize(TreeNode* root){
    if(root==NULL){
        return 0;
    }
    return 1+TreeSize(root->lchild)+TreeSize(root->rchild);
}

12.求第K层节点的个数

思想:向下递归,每递归一次K-1,当K=1时即为当前要找的K层

size_t TreeKLevelSize(TreeNode* root, int k){
    if(root==NULL||k<1){
        return 0;
    }
    if(k==1){
        return 1;
    }
    return TreeKLevelSize(root->lchild,k-1)+TreeKLevelSize(root->rchild,k-1);        
}

13.求二叉树的高度

size_t TreeHeight(TreeNode* root){
    if(root==NULL){
        return 0;
    }
   size_t m=TreeHeight(root->lchild) ;
   size_t n=TreeHeight(root->rchild);
   return 1+(m>n?m:n);
}  

14.查找节点

TreeNode* TreeFind(TreeNode* root, TreeNodeType to_find){
    if(root==NULL){
        return NULL;
    }
    if(root->data==to_find){
        return root;
    }
    TreeFind(root->lchild,to_find);
    TreeFind(root->rchild,to_find);
}

15.查找所给节点的左子树,右子树,父节点

TreeNode* LChild(TreeNode* node){
    if(node==NULL){
        return NULL;
    }
    return node->lchild;
}                                                                                    
TreeNode* RChild(TreeNode* node){
    if(node==NULL){
        return NULL;
    }
    return node->rchild;
}

TreeNode* Parent(TreeNode* root, TreeNode* node){
    if(node==NULL||root==NULL){
        return NULL;
    }
    if(root->lchild==node||root->rchild==node){
        return root;
    }
    TreeNode* lret=Parent(root->lchild,node);
    TreeNode* rret=Parent(root->rchild,node);
    return lret!=NULL?lret:rret;
}

16.非递归前序遍历二叉树



void PreOrderByLoop(TreeNode* root){
    if(root==NULL){
        return;
    }
   seqStack stack;
   seqStackInit(&stack);
   seqStackPush(&stack,root);
   TreeNode* cur=NULL;
   while(seqStackFront(&stack,&cur)){
        printf("%c ",cur);
        seqStackPop(&stack);
        if(cur->lchild!=NULL){
           seqStackPush(&stack,cur->lchild) ;
        }
        if(cur->rchild){                                                             
            seqStackPush(&stack,cur->rchild);
        }
   }
}

17.非递归中序遍历二叉树


void InOrderByLoop(TreeNode* root){
    if(root==NULL){
        return;
    }
    seqStack stack;
    seqStackInit(&stack);
    TreeNode* cur=root;
    while(1){
        while(cur!=NULL){
            cur=cur->lchild;
            seqStackPush(&stack,&cur);
        }
        TreeNode* top=NULL;
        int ret=seqStackFront(&stack,&top);
        if(ret==0){
            return;
        }
        seqStackPop(&stack);
        cur=top->rchild;                                                             
    }
    return;
}

18.非递归后序遍历二叉树


void PostOrderByLoop(TreeNode* root){
    if(root==NULL){
        return;
    }
    seqStack stack;
    seqStackInit(&stack);
    TreeNode* cur=root;//cur保存当前节点
    TreeNode* pre=NULL;//pre保存前一个访问过的节点
    while(cur!=NULL){
        seqStackPush(&stack,&cur);
        cur=cur->lchild;
    }
    TreeNode* top=NULL;
    seqStackFront(&stack,&top);
    if(top->rchild==NULL||top->rchild==pre){
        printf("%c ",top);
        seqStackPop(&stack);
        pre=top;                                                                     
    }else{
        cur=top->rchild;
    }
}

19.镜像二叉树


//递归版本
void swap(TreeNode** lnode,TreeNode** rnode){
    TreeNode* tmp=*lnode;
    *lnode=*rnode;
    *rnode=tmp;
    return;
}
void TreeMirror(TreeNode* root){
    if(root==NULL){
        return;
    }
    //访问动作就是交换左右子树
    swap(&root->lchild,&root->rchild);
    TreeMirror(root->lchild);
    TreeMirror(root->rchild);
}
//非递归版本
void TreeMirrorByLoop(TreeNode* root){
    if(root==NULL){
        return;
    }                                                                                
    seqqueue q;
    seqqueueInit(&q);
    seqqueuePush(&q,root);
    TreeNode* cur=NULL;
    while(seqqueueTop(&q,&cur)){
        swap(&cur->lchild,&cur->lchild);
        seqqueuePop(&q);
        if(cur->lchild!=NULL){
            seqqueuePush(&q,cur->lchild);
        }
        if(cur->rchild!=NULL){
            seqqueuePush(&q,cur->rchild);
        }
    }
    return;
}

20.判断二叉树是否为完全二叉树

思想:
阶段一:任何一个节点同时具备左右子树,一旦发现某个节点不是同时具备
a>当前节点只有右子树,一定不是完全二叉树
b>如果当前节点只有左子树,进入阶段二
c>如果当前节点没有子树,也进入阶段二


阶段二:任何一个节点都必须没有子树

当遍历结束之后,所有的条件都满足,说明这个树是二叉树,否则,不是。

int IsCompleteTree(TreeNode* root){
    if(root==NULL){
        return 0;
    }
    int if_start_step_two_flag=0;
    seqqueue q;
    seqqueueInit(&q);
    seqqueuePush(&q,root);
    TreeNode* cur=NULL;
    while(seqqueueFront(&q,&cur)){
        seqqueuePop(&q);
        if(if_start_step_two_flag==0){
            if(cur->lchild!=NULL&&cur->rchild!=NULL){
                seqqueuePush(&q,cur->lchild);
                seqqueuePush(&q,cur->rchild);
            }else if(cur->lchild==NULL&&cur->rchild!=NULL){
                return 0;
            }else if(cur->lchild!=NULL&&cur->rchild==NULL){
                if_start_step_two_flag=1;                                            
                seqqueuePush(&q,cur->lchild);
            }else{
                if_start_step_two_flag=1;
            }
        }else{
            if(cur->lchild==NULL&&cur->rchild==NULL) {
                ;
            }else{
                return 0;
            }
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值