程序员面试之算法备忘录(四) | 二叉树

前言


本文是题主准备面试时记录下的笔记整理而来,稍显粗陋,还请各位撸友勿喷哈!

Topic


  • 目录

    • 数组
    • 字符串
    • 链表
    • 二叉树
    • 排序
  • 目标

    • 熟练使用常用数据结构的基本操作
    • 加深对常用算法与技巧的理解
    • 面试
  • 参考

    • 《程序员面试金典》
    • 《剑指offer》
    • Leetcode
    • 《结构之法 --July》

二叉树篇


BTree ADT

  • 构建二叉树

    • TreeNode* createBTree(const string &s, int &i, int method);
    • 递归构建
      • 判断传入字符串参数是否为空
      • 遇“#”返回NULL
      • 遇其他字符,new一个二叉树结点
        a. data域是该字符
        b. 左孩子递归调用该函数,所传标志变量i加1
        c. 右孩子同b
    • 根据先序遍历序列构建二叉树(非递归)
      • 判空
      • 向左深搜构造,并将结点入栈
      • 重复执行B直至最左叶子节点的左指针
      • 逐一访问栈顶结点,向右深搜构造
      • 执行D时,检测是否有左结点,有则执行C
    • 根据后序遍历序列构建二叉树(非递归)
      • 同先序类似,顺序颠倒一下就可以了
  • 销毁二叉树

    • void delBTree(TreeNode* &p);
  • 先序遍历

    • void PreOrder(TreeNode* p, int method);
    • 迭代策略一:
      • 向左深搜直至BTree的最左叶子节点的l_child指针
      • 搜的同时,访问每一结点,并将结点入栈
      • 逐一获取栈中结点的右孩子,重复A,B
      • 每获取一个栈中结点,就将该结点弹出,直至栈空
    • 迭代策略二:
      • 将根节点入栈
      • 访问栈顶结点,并弹出栈顶结点
      • 将该栈顶结点的右孩子入栈,如果有的话
      • 将该栈顶结点的左孩子入栈,如果有的话
      • 重复BCD,直至栈空
  • 中序遍历

    • void InOrder(TreeNode* p, int method);
    • 迭代策略:
      • 向左深搜直至BTree的最左叶子节点的l_child指针
      • 搜的同时,将结点入栈
      • 逐一访问栈顶结点,并将栈顶结点的右孩子入栈
      • 重复ABC,直至栈空
  • 后序遍历

    • void PostOrder(TreeNode* p, int method);

    • 策略一:

      • 向左深搜直至BTree的最左叶子节点的l_child指针
      • 搜的同时,将结点入栈
      • 向右深搜栈顶元素的右孩子,直至最右叶子节点,
        • 每搜一个节点时,先重复AB
      • 将栈中元素逐个弹出,并访问之
      • 执行D时,需注意将p指针置空
    • 策略二:双栈法

      • 构建两个栈s1,s2
      • 将根节点入栈s1
      • 弹出s1的栈顶元素,并将该元素入栈s2
      • 将该元素的左孩子入栈,如果有的话
      • 将该元素的右孩子入栈,如果有的话
      • 重复CDE,直至栈s1空
      • 通过栈顶指针逐一遍历栈s2的元素
  • 层次遍历

    • void LayerOrder(TreeNode *p);
  • 查找值为et_value的二叉树结点

    • TreeNode* findNode(TreeNode *p, T et_value);
  • 获得二叉树的深度

    • int getBTDepth(TreeNode *p);

BST ADT

  • 构建二叉排序树
    • TreeNode* createBST(int v[], int start, int end);
  • 插入新结点
    • void insertNode(T &et_value, TreeNode* &p);
  • 删除指定结点
    • void removeNode(T et_value, TreeNode* &p);
  • 查找最大值
    • TreeNode* findMax(TreeNode *p);
  • 查找最小值
    • TreeNode* findMin(TreeNode *p);
  • 查找二叉树是否包含指定值的结点
    • bool contains(T et_value, TreeNode *p);

代码示例:

/*******************************************************************************
    @ Title:            实现二叉树基本操作   

    @ Description:      
                        1.C++实现二叉树模板类(递归)
                        2.C++实现二叉树模板类(非递归)
                        3.C++实现二叉排序树模板类(递归)
                        4.C++实现二叉排序树模板类(非递归)
    @ Conclusion:           
            1.构建二叉树(递归):
                A.判断传入字符串参数是否为空
                B.遇“#”返回NULL
                C.遇其他字符,new一个二叉树结点
                    a.data域是该字符
                    b.左孩子递归调用该函数,所传标志变量i加1
                    c.右孩子同b
            
            2.先序遍历(非递归):
                策略一:
                    A.向左深搜直至BTree的最左叶子节点的l_child指针
                    B.搜的同时,访问每一结点,并将结点入栈
                    C.逐一获取栈中结点的右孩子,重复A,B
                    D.每获取一个栈中结点,就将该结点弹出,直至栈空
                
                策略二:
                    A.将根节点入栈
                    B.访问栈顶结点,并弹出栈顶结点
                    C.将该栈顶结点的右孩子入栈,如果有的话
                    D.将该栈顶结点的左孩子入栈,如果有的话
                    E.重复BCD,直至栈空

            3.中序遍历(非递归)
                策略一:
                    A.向左深搜直至BTree的最左叶子节点的l_child指针
                    B.搜的同时,将结点入栈
                    C.逐一访问栈顶结点,并将栈顶结点的右孩子入栈
                    D.重复ABC,直至栈空

            4.后序遍历(非递归)
                策略一:
                    A.向左深搜直至BTree的最左叶子节点的l_child指针
                    B.搜的同时,将结点入栈
                    C.向右深搜栈顶元素的右孩子,直至最右叶子节点,
                        *、每搜一个节点时,先重复AB
                    D.将栈中元素逐个弹出,并访问之
                        E.执行D时,需注意将p指针置空
                
                策略二:双栈法
                    A.构建两个栈s1,s2
                    B.将根节点入栈s1
                    C.弹出s1的栈顶元素,并将该元素入栈s2
                    D.将该元素的左孩子入栈,如果有的话
                    E.将该元素的右孩子入栈,如果有的话
                    F.重复CDE,直至栈s1空
                    G.通过栈顶指针逐一遍历栈s2的元素

                        5.根据先序遍历序列构建二叉树(非递归):
                            策略:
                                A.判空
                                B.向左深搜构造,并将结点入栈
                                C.重复执行B直至最左叶子节点的左指针
                                D.逐一访问栈顶结点,向右深搜构造
                                E.执行D时,检测是否有左结点,有则执行C

                        6.根据后序遍历序列构建二叉树(非递归):
                            策略:
                                A.同5类似,顺序颠倒一下就可以了
                        
                        7.求二叉树深度(非递归实现)
                        8.前中后Morris遍历测试
                        9.测试BST相关操作 + 创建二叉排序树(递归 & 非递归)
                        10.二叉树findnode(非递归实现)
            11.BST insertNode非递归 & removeNode非递归


    @ Author:       rh_Jameson

    @ Date:         2014/12/22
**********************************************************************************/

#ifndef BINARYTREE_H
#define BINARYTREE_H

#include 
#include 
//#include 
#include
#include
#include
#include

using namespace std;

//二叉树类声明
templateclass BinaryTree;

//二叉树结点类
template
class TreeNode{
private:
    TreeNode *l_child,*r_child;
    T data;

public:
    TreeNode(){l_child = NULL;r_child = NULL;}
    TreeNode(T value,TreeNode *left = NULL,TreeNode *right = NULL){
        data = value;
        l_child = left;
        r_child = right;
    }
    friend class BinaryTree;     // 将二叉树类声明为友元类,方便访问该类私有变量
};

//二叉树类
template
class BinaryTree{
public:
    
    /* 二叉树常用操作 */

    // 构造函数
    BinaryTree(const string &s, int method);                
    // 拷贝构造函数
    //BinaryTree(BinaryTree &tree);
    // 析构函数
    ~BinaryTree();
    // 外部删除二叉树函数
    bool pubForDelBTree();      
    // 外部访问先序遍历
    void pubForPreOrder(int method);
    // 外部访问中序遍历
    void pubForInOrder(int method);
    // 外部访问后序遍历
    void pubForPostOrder(int method);
    // 外部访问层次遍历
    void pubForLayerOrder();
    // 外部查找值为et_value的二叉树结点
    void pubForFindNode(T et_value);
    // 获得二叉树的根
    TreeNode* getRoot();
    // 外部获得二叉树的深度
    int pubForGetBTDepth();

    /* 二叉排序树常用操作 */
    
    // 二叉排序树构造函数
    //BinaryTree(vector v);              
    BinaryTree(int v[]);                
    // 外部插入新结点
    void pubForInsertNode(T &et_value);
    // 外部删除指定结点
    void pubForRemoveNode(T et_value);
    // 外部查找最大值
    void pubForFindMax();
    // 外部查找最小值
    void pubForFindMin();
    // 外部查找二叉树是否包含指定值的结点
    bool pubForContains(T et_value);

private:
    TreeNode *root;                  //二叉树的根指针
    
    /* 二叉树常用操作 */

    //构建二叉树
    TreeNode* createBTree(const string &s, int &i, int method);
    //销毁二叉树
    void delBTree(TreeNode* &p);
    //内部先序遍历
    void PreOrder(TreeNode* p, int method);
    //内部中序遍历
    void InOrder(TreeNode* p, int method);
    //内部后序遍历
    void PostOrder(TreeNode* p, int method);
    //内部层次遍历
        void LayerOrder(TreeNode *p);  
    //内部查找值为et_value的二叉树结点
    TreeNode* findNode(TreeNode *p, T et_value);    
    //内部获得二叉树的深度
    int getBTDepth(TreeNode *p);

    /* 二叉排序树常用操作 */

        // 构建二叉排序树
    TreeNode* createBST(int v[], int start, int end);
    //TreeNode* createBST(int v[], int start, int end);
    // 插入新结点
    void insertNode(T &et_value, TreeNode* &p);
    // 删除指定结点
    void removeNode(T et_value, TreeNode* &p);
    // 查找最大值
    TreeNode* findMax(TreeNode *p);
    // 查找最小值
    TreeNode* findMin(TreeNode *p);
    // 查找二叉树是否包含指定值的结点
    bool contains(T et_value, TreeNode *p);
};

// 构造函数
template 
BinaryTree::BinaryTree(const string &s, int method){
    root = NULL;
    int i = 0;
    root = createBTree(s, i, method);
} 
//构建二叉树 
template 
TreeNode* BinaryTree::createBTree(const string &s, int &i,int method){
    switch(method){
        case 1:     //递归构建
        {
            TreeNode* BTree; 
            if(s.empty() ){
                return NULL;
            }

            if(s[i] == '#'){
                return NULL;
            }
            else{
                BTree = new TreeNode();
                BTree->data = s[i];
                BTree->l_child = createBTree(s,++i, method);
                BTree->r_child = createBTree(s,++i, method);
                return BTree;
            }
        }
        case 2:     //根据先序遍历序列构建(非递归)
        {
            if(s.empty()){
                return NULL;
            }
            TreeNode *BTNode = new TreeNode, *head = BTNode;
            BTNode->data = s[i++];
            stack* > SForBTree;
            while(BTNode || !SForBTree.empty() ){
                if(s[i] == '\0'){
                    break;
                }
                if(BTNode){             //向左深搜
                    SForBTree.push(BTNode);
                    if(s[i] == '#'){    //遇#置NULL
                        BTNode->l_child = NULL;
                    }
                    else{               //遇其他符号则新建结点
                        BTNode->l_child = new TreeNode();
                        BTNode->l_child->data = s[i];
                    }
                    BTNode = BTNode->l_child;
                }
                else{                   //反过来,向右深搜
                    BTNode = SForBTree.top();
                    SForBTree.pop();
                    if(s[i] == '#'){
                        BTNode->r_child = NULL;
                    }
                    else{
                        BTNode->r_child = new TreeNode();
                        BTNode->r_child->data = s[i];
                    }
                    BTNode = BTNode->r_child;
                }
                i++;
            }
            return head;
        }
        case 3:     //根据后序遍历序列构建二叉树
        {
            if(s.empty()){
                return NULL;
            }
            int cur = s.size() - 1;
            stack* > SForBTree;
            TreeNode *node = new TreeNode(), *head = node;
            node->data = s[cur--];
            while(node || !SForBTree.empty()){
                if(cur < 0){
                    break;
                }
                if(node){                   //向右深搜
                    SForBTree.push(node);
                    if(s[cur] == '#'){      //遇#置NULL
                        node->r_child = NULL;
                    }
                    else{                   //其他符号新建一个结点
                        node->r_child = new TreeNode();
                        node->r_child->data = s[cur];
                    }
                    node = node->r_child;
                }
                else{                       //反过来,向左深搜
                    node = SForBTree.top();
                    SForBTree.pop();
                    if(s[cur] == '#'){
                        node->l_child = NULL;
                    }
                    else{
                        node->l_child = new TreeNode();
                        node->l_child->data = s[cur];
                    }
                    node = node->l_child;
                }
                --cur;
            }
            return head;
        }
    }
}


//根据前序遍历序列和中序遍历序列构建二叉树
//失败,模板类惹的祸,只允许TreeNode,待另写一个cpp实现
/*template
TreeNode* createBTreeByPreAndInOrder(string &PreOrder, string &InOrder){
    if(PreOrder.empty() || InOrder.empty()) return NULL;
    TreeNode *tmp; 
    if(PreOrder.size()){
        tmp = new TreeNode();
        tmp->data = PreOrder[0];
        int idx = InOrder.find(PreOrder[0]);
        
        string PreLeft = PreOrder.substr(1, idx);
        string PreRight = PreOrder.substr(idx + 1);
        string InLeft = InOrder.substr(0, idx);
        string InRight = InOrder.substr(idx + 1);

        tmp->l_child = createBTreeByPreAndInOrder(PreLeft, InLeft);
        tmp->r_child = createBTreeByPreAndInOrder(PreRight,InRight);
    }
    return tmp;
}*/

//// 拷贝构造函数
//template 
//BinaryTree::BinaryTree(BinaryTree &tree){
//  
//} 

//析构函数
template 
BinaryTree::~BinaryTree(){
    delBTree(root);
}
//外部销毁二叉树
template 
bool BinaryTree::pubForDelBTree(){
    delBTree(root);
    if(root){
        return false;
    }
    return true;
            
}
//内部销毁二叉树
template
void BinaryTree::delBTree(TreeNode* &p){
    
    /* 递归销毁
     if(p != NULL){
        delBTree(p->l_child);
        delBTree(p->r_child);
        delete(p);
        p = NULL;
    }*/
    //待实现:自上而下层次遍历销毁
    //
    //非递归实现(自下而上后续遍历销毁)
    stack* > SForBTree;
    TreeNode *pre;
    while(p || !SForBTree.empty() ){
        if(p){
            SForBTree.push(p);
            p = p->l_child;
        }
        else{
            p = SForBTree.top();
            if(p->r_child && p->r_child != pre ){   //有右子树且右子树未被访问过
                p = p->r_child;
            }
            else{
                pre = p;
                SForBTree.pop();
                delete p;
                p = NULL;           //!!!须置空,否则陷入死循环
                                    //反复出栈 / 入栈
            }
        }
    }
}

//外部访问先序遍历
template
void BinaryTree::pubForPreOrder(int method){
    if(!root){
        cout << "空二叉树!" << endl;
    }
    PreOrder(root, method);
}
//内部访问先序遍历
template
void BinaryTree::PreOrder(TreeNode* p, int method){
    switch(method){
        case 1:     //递归形式
            if(p != NULL){
                cout << p->data << "\t";
                PreOrder(p->l_child, method);
                PreOrder(p->r_child, method);
            }
            break;
        case 2:     //栈的实现形式
            {   
                stack* > SForBTree;
                while(p != NULL || !SForBTree.empty() ){
                    if(p != NULL){
                        cout << p->data << "\t";
                        SForBTree.push(p);
                        p = p->l_child;
                    }
                    else{
                        p = SForBTree.top();
                        SForBTree.pop();
                        p = p->r_child;
                    }
                }
                break;
            }
        case 3:     //栈实现形式二
            {   
                stack* > SForBTree;
                if(p != NULL)
                    SForBTree.push(p);
                while( !SForBTree.empty() ){
                    p = SForBTree.top();
                    cout << p->data << "\t";
                    SForBTree.pop();

                    if(p->r_child){
                        SForBTree.push(p->r_child);
                    }
                    if(p->l_child){
                        SForBTree.push(p->l_child);
                    }
                }
                break;
            }
            case 4:     //Morris遍历
            {
            TreeNode *cur = p, *pre;
            while(cur){
                if(!cur->l_child){      //左孩子为空时,输出当前结点,cur指向其右孩子
                    cout << cur->data << "\t";
                    cur = cur->r_child;
                }
                else{                   //左孩子不为空时
                    pre = cur->l_child;
                    //找该结点的中序遍历序列的前驱结点
                    while(pre->r_child != NULL && pre->r_child != cur){     
                        pre = pre->r_child;
                    }
                    //前驱结点的右孩子指向当前结点,并输出当前节点,cur指向其左孩子
                    if(pre->r_child == NULL){   
                        pre->r_child = cur;
                        cout << cur->data << "\t";  //与中序遍历唯一的不同!
                        cur = cur->l_child;
                    }
                    //将前驱结点右孩子指向当前结点的连接断开,cur指向其右孩子
                    else{
                        pre->r_child = NULL;
                        cur = cur->r_child;
                    }
                }
            }
            break;
        }
    }
}

//外部访问中序遍历
template
void BinaryTree::pubForInOrder(int method){
    if(!root){
        cout << "空二叉树" << endl;
    }
    InOrder(root, method);
}
//内部访问中序遍历
template
void BinaryTree::InOrder(TreeNode* p, int method){
    switch(method){
        case 1:     //递归形式
        {   if(p != NULL){
                InOrder(p->l_child, method);
                cout << p->data << "\t";                
                InOrder(p->r_child, method);
            }
            break;
        }
        case 2:     //栈的实现形式
        {
            stack* > SForBTree;
            while(p != NULL || !SForBTree.empty() ){
                if(p != NULL){
                    SForBTree.push(p);
                    p = p->l_child;
                }
                else{
                    p = SForBTree.top();
                    cout << p->data << "\t";
                    SForBTree.pop();
                    p = p->r_child;
                }
            }
            break;
        }
        case 3:     //morris遍历
        {
            TreeNode *cur = p, *pre;
            while(cur){
                if(cur->l_child == NULL){
                    cout << cur->data << "\t";
                    cur = cur->r_child;
                }
                else{
                    pre = cur->l_child;
                    while(pre->r_child != NULL && pre->r_child != cur){
                        pre = pre->r_child;
                    }
                    if(pre->r_child == NULL){
                        pre->r_child = cur;
                        cur = cur->l_child;
                    }
                    else{
                        pre->r_child = NULL;
                        cout << cur->data << "\t";      //与前序遍历代码的不同!
                        cur = cur->r_child;
                    }
                }
            }
            break;
        }
    }
    
}

//外部访问后序遍历
template
void BinaryTree::pubForPostOrder(int method){
    if(!root){
        cout << "空二叉树!" << endl;
    }
    PostOrder(root, method);
}
//内部访问后序遍历
template
void BinaryTree::PostOrder(TreeNode *p, int method){
    switch(method){
        case 1:     //递归形式实现
            if(p != NULL){
                PostOrder(p->l_child, method);
                PostOrder(p->r_child, method);
                cout << p->data << "\t";
            }
            break;

        case 2:     //栈形式实现,该代码应该可以转作非递归销毁二叉树
        {
            stack* > SForBTree;
            TreeNode *pre;
            while(p || !SForBTree.empty() ){
                if(p){
                    SForBTree.push(p);
                    p = p->l_child;
                }
                else{
                    p = SForBTree.top();
                    if(p->r_child && p->r_child != pre ){   //有右子树且右子树未被访问过
                        p = p->r_child;
                    }
                    else{
                        cout << p->data << "\t";    
                        pre = p;
                        SForBTree.pop();
                        p = NULL;           //!!!须置空,否则陷入死循环
                                            //反复出栈 / 入栈
                    }
                }
            }
            break;
        }
        case 3:     //双栈形式实现
        {
            stack* > s1, s2;
            if(p != NULL)   s1.push(p);
            while(!s1.empty()){
                p = s1.top();
                s1.pop();
                s2.push(p);

                if(p->l_child){
                    s1.push(p->l_child);
                }
                if(p->r_child){
                    s1.push(p->r_child);
                }
            }
            while(!s2.empty()){
                p = s2.top();
                cout << p->data << "\t";
                s2.pop();
            }
            break;
        }
        case 4:     //morris遍历
        {
            TreeNode *cur = p, *pre;
            while(cur != NULL){
                if(cur->l_child == NULL){
                    cur = cur->r_child;
                }
                else{
                    pre = cur->l_child;
                    while(pre->r_child != NULL && pre->r_child != cur){
                        pre = pre->r_child;
                    }
                    if(pre->r_child == NULL){
                        pre->r_child = cur;
                        cur = cur->l_child;
                    }
                    else{
                        //printReverse(cur->l_child, pre);
                        pre->r_child = NULL;
                        cur = cur->r_child;
                    }
                }
            }
            break;
        }
    }
}
/*Morris 后续遍历相关函数
 * template
void reverse(TreeNode *from, TreeNode *to){
    if(from = to){
        return;
    }
    TreeNode  =
}
template
void printReverse(TreeNode *from, TreeNode *to){
    TreeNode *p = to;
    reverse(from, to);
    while(true){
        cout << p->data << "\t";
        if(p == from){
            break;
        }
        p = p->r_child;
    }
    reverse(to, from); 
}*/

//外部查找值为et_value的二叉树结点
template
void BinaryTree::pubForFindNode(T et_value){
    TreeNode *res = findNode(root, et_value);
    if(res == NULL){
        cout << "找不到相应结点" << endl;
    }
    else{
        cout << "找到该结点,该结点值为:" << res->data << endl;
    }
    
}
//查找值为et_value的二叉树结点
template
TreeNode* BinaryTree::findNode(TreeNode *p, T et_value){
    //递归实现
/*  if(p == NULL){
        return NULL;
    }
    if(p->data == et_value){
        return p;
    }   
    TreeNode *tmp = findNode(p->l_child, et_value);
    if(tmp != NULL){
        return tmp;
    }
    else{
        return findNode(p->r_child, et_value);
    }
*/
    //非递归实现
    stack*> s;
    while(p != NULL || !s.empty()){
        if(p != NULL){
            s.push(p);
            p = p->l_child;
        }
        else{
            p = s.top();
            s.pop();
            if(p->data == et_value) break;
            p = p->r_child;
        }
    }
    return p;
}

//外部获得二叉树的深度
template
int BinaryTree::pubForGetBTDepth(){
    return getBTDepth(root);
}
//获得二叉树的深度
template
int BinaryTree::getBTDepth(TreeNode *p){
    /* 递归实现1 
    int depth = 0;
    if(p != NULL){
        int l_child_depth = getBTDepth(p->l_child);
        int r_child_depth = getBTDepth(p->r_child);
        depth =  (l_child_depth >= r_child_depth) ? (l_child_depth + 1) : (r_child_depth + 1);
        //depth = 1 + (l_child_depth >= r_child_depth ? l_child_depth : r_child_depth);
    }
    return depth;   
    */
    /* 递归实现2 
    if(p == NULL) return 0;
    return 1 + max(getBTDepth(p->l_child), getBTDepth(p->r_child));
    */
    //非递归实现
/*    int depth = 0, maxDepth = 0;
    stack*> *s = new stack*>();
    while(p != NULL || !s->empty()){
        if(p != NULL){
            s->push(p);
            ++depth;
            p = p->l_child;
        }
        else{
            p = s->top();
            s->pop();
            p = p->r_child;
            if(p == NULL){
                if(depth > maxDepth){
                    maxDepth = depth;
                }   
                depth--;
            }
        }
    }
    return maxDepth - 1;
*/
    /* 双栈形式 
    if (p == NULL) return 0;
    stack *> gray;
    stack depth;
    int maxDepth = 0;

    gray.push(p);
    depth.push(1);
    while (!gray.empty()) {
        TreeNode *tmp = gray.top();
        int num = depth.top();
        gray.pop();
        depth.pop();
        if (tmp->l_child == NULL && tmp->r_child == NULL) {
            maxDepth = num > maxDepth ? num : maxDepth;
        }
        else {
            if (tmp->l_child != NULL) {
                gray.push(tmp->l_child);
                depth.push(num + 1);
            }
            if (tmp->r_child != NULL) {
                gray.push(tmp->r_child);
                depth.push(num + 1);
            }
        }
    }
    return maxDepth;
    */

    /* 队列层次遍历实现 
    int height = 0,rowCount = 1;
    if(root == NULL){
        return 0;
    }
    queue*> queue;
    queue.push(p);
    while(!queue.empty()){
        TreeNode *node = queue.front();
        queue.pop();
        //一层的元素个数减1,一层遍历完高度加1
        rowCount --;
        if(node->l_child){
            queue.push(node->l_child);
        }
        if(node->r_child){
            queue.push(node->r_child);
        }
        //一层遍历完
        if(rowCount == 0){
            //高度加1
            height++;
            //下一层元素个数
            rowCount = queue.size();
        }
    }
    return height;
    */
    /* 层次遍历树的层数,NULL为每一层节点的分割标志 */
    if(p == NULL)return 0;
    int res = 0;
    queue*> Q;
    Q.push(p);
    Q.push(NULL);
    while(Q.empty() == false)
    {
        TreeNode *p = Q.front();
        Q.pop();
        if(p != NULL)
        {
            if(p->l_child)Q.push(p->l_child);
            if(p->r_child)Q.push(p->r_child);
        }
        else
        {
            res++;
            if(Q.empty() == false)Q.push(NULL);
        }
    }
    return res;
}

//外部访问层次遍历
template
void  BinaryTree::pubForLayerOrder(){
    LayerOrder(root);
}
//内部层次遍历
template
void  BinaryTree::LayerOrder(TreeNode *p){
    if(p == NULL){
        cout << "空树!" << endl;
        return;
    }
    queue *> queueTreeNode;
    queueTreeNode.push(p);
    while(queueTreeNode.size() ){
        TreeNode *tmp = queueTreeNode.front();
        queueTreeNode.pop();
        cout << tmp->data << "\t";

        if(tmp->l_child != NULL){
            queueTreeNode.push(tmp->l_child);
        }
        if(tmp->r_child != NULL){
            queueTreeNode.push(tmp->r_child);
        }
    }
    /*deque双向队列版
    deque *> dequeTreeNode;
    dequeTreeNode.push_back(p);
    while(dequeTreeNode.size() ){
        TreeNode *tmp = dequeTreeNode.front();
        dequeTreeNode.pop_front();
        cout << tmp->data << "\t";

        if(tmp->l_child != NULL){
            dequeTreeNode.push_back(tmp->l_child);
        }
        if(tmp->r_child != NULL){
            dequeTreeNode.push_back(tmp->r_child);
        }
    }*/
}

//获得二叉树的根
template
TreeNode* BinaryTree::getRoot(){
    return root;
}


/* 二叉排序树常用操作 */

// 二叉排序树构造函数
template
BinaryTree::BinaryTree(int v[]){
    //vector vv(v, v + sizeof(v)/sizeof(v[0]));
    /*vector vv(v, v + 10);
    if(!vv.size()){
        cout << "生成失败,原因:空数组" << "\t";
        return;
    }
    sort(vv.begin(), vv.end());
    */
    sort(v, v + 9);
    /*if(sizeof(v) / sizeof(int)){
        cout << "生成失败,原因:空数组" << "\t";
        return;
    }*/

    root = createBST(v, 0, 9 - 1);
}
 // 构建二叉排序树
template
TreeNode* BinaryTree::createBST(int sorted_Vec[],int start,int end){    
    //递归实现
    if(end < start){
        return NULL;
    }
    int mid = (start + end) / 2;
    TreeNode *node = new TreeNode();
    node->data = sorted_Vec[mid];
    node->l_child = createBST(sorted_Vec, start, mid - 1);
    node->r_child = createBST(sorted_Vec, mid + 1, end);
    return node;
    
    //非递归实现
/*失败,每个结点的start和end都需记住,该模板无相应属性
 * 为避免大量修改代码,放弃实现~~
 *  mid = (start + end) / 2;
    stack* > s = new stack* >();
    stack mid_s = new stack();
    TreeNode *node = new TreeNode();
    mid_s.push(end);
    while(mid >= 0 || !s.empty()){
        if(mid >= 0){
            node = new TreeNode();
            node->data = sorted_Vec[mid];
            mid_s.push(mid);
            s.push(node);
            node = node->l_child;
            mid = (0 + mid - 1) / 2;
        }
        else{
            mid = mid_s.top();
            node = s.top();
            mid_s.pop();
            s.pop();
            
        }
    }
*/
}


// 外部插入新结点
template
void BinaryTree::pubForInsertNode(T &et_value){
    insertNode(et_value, root);
}
// 插入新结点
template
void BinaryTree::insertNode(T &et_value, TreeNode* &p){
    //递归实现
/*  if(p == NULL){
        p = new TreeNode();
        p->data = et_value;
    }
    else if(et_value < p->data){
        insertNode(et_value, p->l_child);
    }
    else if(et_value > p->data){
        insertNode(et_value, p->r_child);
    }
    else    //相等(重复)则不做任何操作
        ;
    */
    //非递归实现
    TreeNode *cur = p, *parent = NULL, *newNode = new TreeNode();
    newNode->data = et_value;
    if(p == NULL){              //二叉树为空的情况
        p = newNode;
        return;
    }           
    while(true){
        if(cur == NULL){
            if(et_value < parent->data)         //插入到叶子节点的左孩子
                parent->l_child = newNode;
            else
                parent->r_child = newNode;
            return;
        }
        parent = cur;
        if(et_value < cur->data)
            cur = cur->l_child;
        else if(et_value > cur->data)
            cur = cur->r_child;
        else
            return;     //重复,不插入,直接退出
    }
}

// 外部删除指定结点
template
void BinaryTree::pubForRemoveNode(T et_value){
    removeNode(et_value, root);
}
// 删除指定结点
template
void BinaryTree::removeNode(T et_value, TreeNode * &p){
    //递归实现
/*  if(p == NULL){
        return;     //该值未找到,停止
    }
    if(et_value < p->data){
        removeNode(et_value, p->l_child);
    }
    else if(et_value > p->data){
        removeNode(et_value, p->r_child);
    }
    else if(p->l_child != NULL && p->r_child != NULL){      //待删结点有两个孩子的情况
        p->data = findMin(p->r_child)->data;        //需琢磨另一种写法
        removeNode(p->data, p->r_child);
    }
    else{       //无孩子或有一个孩子情况
        TreeNode *tmp = p;
        p = (p->l_child != NULL) ? p->l_child : p->r_child;
        delete tmp;
    }
*/

    //非递归实现 
/*  TreeNode *cur = p, *pre, *tmp, *child;
    if(p->data == et_value && !p->l_child && !p->r_child){  //只有一个节点的情况
        p = NULL;
        return;
    }
    while(true){        
        if(cur == NULL) break;
        if(et_value < cur->data){
            pre = cur;
            cur = cur->l_child;
        }else if(et_value > cur->data){ 
            pre = cur;
            cur = cur->r_child;
        }else if(cur->l_child != NULL && cur->r_child != NULL){     //待删结点有两个孩子的情况
            tmp = findMin(cur->r_child); 
            cur->data = tmp->data;
            child = tmp->r_child;           //暂存其右孩子
            pre = cur->r_child;
            while(pre->l_child != tmp)      //找倒数第二小的结点
                pre = pre->l_child;
            pre->l_child = child;
            delete tmp;
            break;
        }
        else{       //无孩子或有一个孩子情况
            tmp = cur;
            cur = (cur->l_child != NULL) ? cur->l_child : cur->r_child;
            (pre->l_child == tmp) ? pre->l_child = cur : pre->r_child = cur;
            delete tmp;
            break;
        }
    }
*/
    //非递归实现 
    TreeNode *cur = p, *pre, *tmp, *child;
    if(p->data == et_value && !p->l_child && !p->r_child){  //只有一个节点的情况
        p = NULL;
        return;
    }
    while(true){        
        if(cur == NULL) break;      //找不到或BST为空
        if(et_value < cur->data){
            pre = cur;
            cur = cur->l_child;
        }
        else if(et_value > cur->data){  
            pre = cur;
            cur = cur->r_child;
        }
        else{       
            if(cur->l_child != NULL && cur->r_child != NULL){   //待删结点有两个孩子的情况
                tmp = findMin(cur->r_child); 
                cur->data = tmp->data;
                child = tmp->r_child;           //暂存其右孩子
                pre = cur->r_child;
                while(pre->l_child != tmp)  pre = pre->l_child; //找倒数第二小的结点 
                pre->l_child = child;
            }
            else{       //无孩子或有一个孩子情况
                tmp = cur;
                cur = (cur->l_child != NULL) ? cur->l_child : cur->r_child;
                (pre->l_child == tmp) ? pre->l_child = cur : pre->r_child = cur;

            }
            delete tmp;
            break;
        }
    }
}

// 外部查找最大值
template
void BinaryTree::pubForFindMax(){
    cout << "该二叉树的最大值为:" << findMax(root)->data << endl;
}
// 查找最大值
template
TreeNode* BinaryTree::findMax(TreeNode *p){
    /* 递归实现 */
/*  if(p == NULL){
        return NULL;
    }
    if(p->r_child == NULL){
        return p;
    }
    return findMax(p->r_child);
*/  
    /* 非递归实现 */
/*  while(p != NULL){
        if(p->r_child == NULL){
            return p;
        }
        p = p->r_child;
    }
    return NULL; 
*/
    /* 非递归实现2 */
    if(p != NULL){
        while(p->r_child != NULL){
            p = p->r_child;
        }
    }
    return p;
    
}

// 外部查找最小值
template
void BinaryTree::pubForFindMin(){
    cout << "该二叉树的最小值为:" << findMin(root)->data << endl;
}
// 查找最小值
template
TreeNode* BinaryTree::findMin(TreeNode *p){
    /* 递归实现 */
/*  if(p == NULL){
        return NULL;
    }
    //if(p->l_child == NULL || *((unsigned int *)p->l_child) == 0xFEEEFEEE ){
    if(p->l_child == NULL){
        p->l_child = NULL;
        return p;
    }
    return findMin(p->l_child);
*/
    /* 非递归实现 
    while(p != NULL){
        if(p->l_child == NULL){
            return p;
        }
        p = p->l_child;
    }
    return NULL; 
*/
    /* 非递归实现2 */
    if(p != NULL){
        while(p->l_child != NULL){
            p = p->l_child;
        }
    }
    return p;
}

// 外部查找二叉树是否包含指定值的结点
template
bool BinaryTree::pubForContains(T et_value){
    return contains(et_value, root);
}
// 查找二叉树是否包含指定值的结点
template
bool BinaryTree::contains(T et_value, TreeNode *p){
    //递归实现
/*  if(p == NULL){
        return false;
    }
    if(et_value < p->data){
        contains(et_value, p->l_child);
    }
    else if(et_value > p->data){
        contains(et_value, p->r_child);
    }
    else{
        return true;
    }
*/
    //非递归实现
    while(p != NULL){
        if(et_value < p->data)
            p = p->l_child;
        else if(et_value > p->data)
            p = p->r_child;
        else
            return true;
    }
    return false;

}

#endif


你可能感兴趣的:(程序员面试之算法备忘录(四) | 二叉树)