代码改变世界

二叉树操作总结

2013-02-21 17:32  littlelion  阅读(515)  评论(0编辑  收藏  举报

关于树及二叉树的基本定义就不多说,下面以BST为例,介绍一下二叉树的创建、遍历以及一些简单的算法。

  • 首先是结点定义及初始化:
struct node{                     
    int data;                       
    node* lchild;                   
    node* rchild;                   
};                               
                                 
node* init_node(int value){      
    node* new_node = new node();    
    new_node->data = value;         
    new_node->lchild = NULL;        
    new_node->rchild = NULL;        
    return new_node;                
}

还是那句话,初始化别放在main函数中,关于这个问题,程序员们肯定说这还用说吗,但对于没写过程序的人(例如我)来说,可能根本就不会想到这是个问题。

  • 关于BST,咱都知道,即root->data > root->lchild->data && root->data < root->rchild->data; 那么在加入新结点时只需要根据这个条件找到它的父节点即可。

所以,找到要插入结点的父节点并插入的方法如下:

 

node* search_parent(node* root,int value){
    node* parent = root;
    node* current_node = root;
    while(current_node!=NULL){
        parent = current_node;
        if(current_node->data >= value){
            current_node = current_node->lchild;
        }else{
            current_node = current_node->rchild;
        }
    }
    return parent;
}
void add_node(node* root,int value){
    node* new_node = init_node(value);
    node* parent = search_parent(root,value);
    if(value >= parent->data){
        parent->rchild = new_node;
    }else{
        parent->lchild = new_node;
    }
}

 

  • 好,下面初始化一个BST并且遍历它,关于二叉树的遍历方式,前序中序后序
node* init_BST(int* arr,int len){
    node* root = init_node(9);
    for(int i=0;i<len;i++){
        add_node(root,arr[i]);
    }
    return root;
}
void inorder(node* root){
    if(root){
        inorder(root->lchild);
        cout<<root->data<<" ";
        inorder(root->rchild);
    }
}
void preorder(node* root){
    if(root){
        cout<<root->data<<" ";
        preorder(root->lchild);
        preorder(root->rchild);
    }
}
void postorder(node* root){
    if(root){
        postorder(root->lchild);
        postorder(root->rchild);
        cout<<root->data<<" ";
    }
}
  • 下面来考虑几个有关二叉树的算法

1.求叶子结点数

叶子结点既没有左子树也没有右子树,因此只要满足current->lchild==NULL && current->rchild==NULL;count+=1; 

总的叶子结点数 = l_叶子结点数 + r_叶子结点数,代码如下:

int leaf_node(node* root){
    node* current_node = root;
    if(current_node==NULL)
        return 0;
    else if(current_node->lchild==NULL && current_node->rchild==NULL){
        cout<<endl<<"leaf node is "<<current_node->data<<" ";
        return 1;
    }
    else
        return leaf_node(current_node->lchild)+leaf_node(current_node->rchild);
}

2.求树的高度

数据结构书中给出的算法是

if(root == NULL)

  height = 0;

else

  height = max(height(root->lchild),height(root->rchild))+1

由于是求子树的高度,要知道height(root),只需知道height(root->lchild)和height(root->rchild),同理,要知道height(root->lchild)和height(root->rchild),只需知道它们各自子树的高度,依次类推。这样的想法,用递归来实现,递归退出的条件为urrent_node->lchild==NULL && current_node->rchild==NULL

 

int height(node* root){                                               
    int lheight,rheight;                                                 
    node* current_node = root;                                           
    if(current_node==NULL)                                               
        return 0;                                                           
    else if(current_node->lchild==NULL && current_node->rchild==NULL)    
        return 1;                                                           
    else{                                                                
        lheight = height(current_node->lchild);                             
        rheight = height(current_node->rchild);                             
    }                                                                    
    int height = lheight>=rheight?lheight+1:rheight+1;                   
    cout<<endl<<"height of child tree "<<height<<" ";                    
    return height;                                                       
}                                                                     

 

3.查找一个结点

这个也不难想,current_node->data = value,

bool search_node(node* root,int value){                
    node* current_node = root;                            
    bool has = false;                                     
    if(root==NULL){                                       
        return false;                                        
    }else if(root->data==value){                          
        return true;                                         
    }else{                                                
        if(root->lchild!=NULL){                              
            has = search_node(root->lchild,value);              
        }                                                    
        if(!has && root->rchild!=NULL){                      
            has = search_node(root->rchild,value);              
        }                                                    
    }                                                     
    return has;                                           
}                                                      

4.求结点之间的最大路径

这道题目需要考虑三种情况:

(1)root->lchild!=NULL && root->rchild!=NULL

那么距离最远的两个结点一定分别位于左右子树

(2)当没有左子树或者没有右子树时,最大距离可能为某一结点到root根结点之间的距离

(3)                                                     也可能为子树内部的两个结点之间的距离

我第一次写这个题目时,没有考虑那么多,只写出了第一种情况下的代码,如下:

int distance_differentChild(node* root){                         
    int distance;                                                   
    if((root==NULL)||(root->lchild==NULL&&root->rchild==NULL))      
        return 0;                                                      
    else{                                                           
        distance = height(root->lchild)+height(root->rchild);          
    }                                                               
    return distance;                                                
} 

当然了,还需要考虑缺了一个子树时的情况,代码如下:

int distance_compare(node* root){                                                           
    int distance_passroot = height(root);                                                      
    int distance_notpassroot = distance_differentChild(root);                                  
    return distance_passroot>=distance_notpassroot?distance_passroot:distance_notpassroot;     
}                                                                                           

最后,汇总一下求最远距离的代码:

int distanceBetweenTwoNodes(node* root){                       
    int distance;                                                 
    if((root==NULL)||(root->lchild==NULL&&root->rchild==NULL))    
        return 0;                                                    
    else if(root->lchild==NULL || root->rchild==NULL){            
        if(root->lchild!=NULL){                                      
            distance = distance_compare(root->lchild);                  
        }                                                            
        if(root->rchild!=NULL){                                      
            distance = distance_compare(root->rchild);                     
        }                                                            
    }                                                             
    else{                                                         
        distance = distance_differentChild(root);                    
    }                                                             
    return distance;                                              
}