• 二叉树-------二叉链表实现


    2019-04-30 17:11:12

    重新拿c++实现了一下

    #include <iostream>
    #include <stack>
    #include <queue>
    
    using namespace std;
    
    class tree_node
    {
    public:
        int data;
        tree_node *lchild;
        tree_node *rchild;
        ~tree_node(){
            lchild = nullptr;
            rchild = nullptr;
        }
    };
    
    class binary_tree
    {
    public:
        tree_node *build_tree(int level, string pos);
        void pre_order(tree_node *root);
        void in_order(tree_node *root);
        void post_order(tree_node *root);
        int sum_node(tree_node *root);
        int sum_leaf(tree_node *root);
        bool tree_equals(tree_node *root1, tree_node *root2);
        void destory_tree(tree_node *root);
        tree_node *copy_tree(tree_node *root);
        void non_rec_pre_order(tree_node *root);
        void non_rec_in_order(tree_node *root);
        void non_rec_post_order(tree_node *root);
        void level_order(tree_node *root);
        void invert_level_order(tree_node *root);
        int tree_depth(tree_node *root);
        int tree_depth2(tree_node *root);
        void find_x_level(tree_node *root, int x);
        tree_node *pre_in_create_tree2(int A[], int B[], int s1, int e1, int s2, int e2);
        tree_node *pre_in_create_tree(int A[],int B[], int s1, int e1, int s2, int e2);
        bool is_complete(tree_node *root);
        int double_son_node(tree_node *root);
        void swap_lrchild(tree_node *root);
        void swap_lrchild2(tree_node *root);
        int search_k_node(tree_node *root, int k);
        void destory_x_node(tree_node *root, int k);
        void print_ancestor_node(tree_node *root, int x);
        tree_node *nearest_comm_ancestor(tree_node *root, int p, int q);
        int tree_width(tree_node *root);
        void pre_to_post(int pre[], int s1, int e1,
                         int post[], int s2, int e2);
        tree_node *inorder_list(tree_node *root);
        void link(tree_node *root, tree_node *head, tree_node *tail);
        bool is_similar(tree_node *root1, tree_node *root2);
        int WPL(tree_node *node);
    
        ~binary_tree(){
            root = nullptr;
        }
    
        tree_node *root;
    };
    
    tree_node *binary_tree::build_tree(int level, string pos) {
        int tmp;
        cin >> tmp;
        if(tmp == 0)
            return nullptr;
    
        tree_node *p_new = new tree_node();
        p_new->data = tmp;
        p_new->lchild = build_tree(level+1, "left");
        p_new->rchild = build_tree(level+1, "right");
        return p_new;
    }
    
    void binary_tree::pre_order(tree_node *root) {
        if(root)
        {
            cout << root->data << endl;
            pre_order(root->lchild);
            pre_order(root->rchild);
        }
    }
    
    void binary_tree::in_order(tree_node *root) {
        if(root)
        {
            in_order(root->lchild);
            cout << root->data << endl;
            in_order(root->rchild);
        }
    }
    
    void binary_tree::post_order(tree_node *root) {
        if(root)
        {
            post_order(root->lchild);
            post_order(root->rchild);
            cout << root->data << endl;
        }
    }
    
    int binary_tree::sum_node(tree_node *root) {
        if(root == nullptr)
            return 0;
        else{
            return sum_node(root->lchild) + sum_node(root->rchild) + 1;
        }
    
        return 0;
    }
    
    // 统计叶子节点的个数
    int binary_tree::sum_leaf(tree_node *root) {
        int sum=0;
    
        if(root)
        {
            if(root->lchild==nullptr && root->rchild==nullptr)
                sum++;
            if(root->lchild)
                sum += sum_leaf(root->lchild);
            if(root->rchild)
                sum += sum_leaf(root->rchild);
        }
    
        return sum;
    }
    
    bool binary_tree::tree_equals(tree_node *root1, tree_node *root2) {
    
        if(root1 == nullptr && root2 == nullptr)
            return true;
    
        if(root1 && root2 && root1->data == root2->data)
            if(tree_equals(root1->lchild,root2->lchild))
                if(tree_equals(root1->rchild, root2->rchild))
                    return true;
    
        return false;
    }
    
    /// delete 会调用析够函数,对对象进行释放
    /// 这个代码不能有效删除树根节点 root
    void binary_tree::destory_tree(tree_node *root) {
        if(root == nullptr)
            return;
        destory_tree(root->lchild);
        destory_tree(root->rchild);
    
        delete root;
        root = nullptr;
        return;
    }
    
    
    tree_node *get_tree_node(int data, tree_node *lchild, tree_node *rchild)
    {
        tree_node *p_tmp = new tree_node();
        p_tmp->data = data;
        p_tmp->lchild = lchild;
        p_tmp->rchild = rchild;
        return p_tmp;
    }
    
    tree_node *binary_tree::copy_tree(tree_node *root) {
        tree_node *new_l, *new_r, *new_root;
        if(root == nullptr)
            return nullptr;
    
        if(root->lchild)
            new_l = copy_tree(root->lchild);
        else
            new_l = nullptr;
    
        if(root->rchild)
            new_r = copy_tree(root->rchild);
        else
            new_r = nullptr;
    
        new_root = get_tree_node(root->data, new_l, new_r);
    
    
        return new_root;
    }
    
    void binary_tree::non_rec_pre_order(tree_node *root) {
    
        /**
    类名后面加*,表示该类型为对应类的指针类型。
    指针类型为C/C++语言的特色概念,其值为对象的地址。
    类名加*,有两种作用情况:
    1 用于定义时,或用于函数参数,返回值时,表示对应变量值为类指针类型;
    2 用于变量前,以(CLASS_NAME *)var_name,形式出现时,表示将变量或常量var_name强制转换为类指针类型。
         * */
    
        stack<tree_node *> tree_stack;
        if(root == nullptr)
            return;
        else{
            while(root || !tree_stack.empty())
            {
                if(root)
                {
                    cout << root->data << endl;
                    tree_stack.push(root);
                    root = root->lchild;
                }else{
                    root = tree_stack.top();
                    tree_stack.pop();
                    root = root->rchild;
                }
            }
        }
    
    }
    
    void binary_tree::non_rec_in_order(tree_node *root) {
        stack<tree_node *> tree_stack;
        if(root==nullptr)
            return;
        else{
            while(root || !tree_stack.empty())
            {
                if(root){
                    tree_stack.push(root);
                    root=root->lchild;
                }else{
                    root=tree_stack.top();
                    tree_stack.pop();
                    cout << root->data << endl;
                    root=root->rchild;
                }
            }
        }
    }
    
    void binary_tree::non_rec_post_order(tree_node *root) {
        stack<tree_node *> tree_stack;
        tree_node *vis = nullptr;
    
        if(root == nullptr)
            return;
    
        while(root || !tree_stack.empty())
        {
            if(root)
            {
                tree_stack.push(root);
                root = root->lchild;
            }else{
                root = tree_stack.top();
                if(root->rchild && root->rchild != vis)
                {
                    root=root->rchild;
                    tree_stack.push(root);
                    root=root->lchild;
                }else{
                    root=tree_stack.top();
                    tree_stack.pop();
                    cout << root->data << endl;
                    vis=root;
                    root=nullptr;
                }
            }
        }
    }
    
    /**
     * 学会使用stl后,代码超级简单,还不用记忆各个容器的具体操作
     * */
    void binary_tree::level_order(tree_node *root) {
        queue<tree_node *> tree_que;
    
        if(root == nullptr)
            return;
    
        tree_que.push(root);
        while(!tree_que.empty())
        {
            root = tree_que.front();
            tree_que.pop();
    
            cout << root->data<< endl;
    
            if(root->lchild)
                tree_que.push(root->lchild);
    
            if (root->rchild)
                tree_que.push(root->rchild);
        }
    }
    
    /**
     * 逆层次遍历
     *
     * */
    void binary_tree::invert_level_order(tree_node *root) {
        queue<tree_node *> tree_que;
        stack<tree_node *> tree_stack;
    
        if(root == nullptr)
            return;
    
        tree_que.push(root);
        while(!tree_que.empty())
        {
            root = tree_que.front();
            tree_que.pop();
            tree_stack.push(root);
    
            if(root->lchild)
                tree_que.push(root->lchild);
            if(root->rchild)
                tree_que.push(root->rchild);
        }
    
        while(!tree_stack.empty())
        {
            root = tree_stack.top();
            tree_stack.pop();
            cout << root->data << endl;
        }
    }
    
    /**
     *
     1.每遍历一层,depth++;
    
     2.每一层,需使用一个变量len记录该层的结点个数,也就是队列的当前长度,
     然后依次在队列中访问该层的len个结点(将队列中len个元素出队列),
     并将下一层如队列
     * */
    
    int binary_tree::tree_depth(tree_node *root) {
    
        queue<tree_node *> tree_que;
        if(root == nullptr)
            return 0;
    
        int level=0;
        tree_que.push(root);
    
        while(!tree_que.empty())
        {
            unsigned long tree_size=tree_que.size();
            level++;
            while(tree_size--)
            {
                tree_node *tmp = tree_que.front();
                tree_que.pop();
                if(tmp->lchild)
                    tree_que.push(tmp->lchild);
                if(tmp->rchild)
                    tree_que.push(tmp->rchild);
            }
        }
    
        return level;
    }
    
    int binary_tree::tree_depth2(tree_node *root) {
    
        int level=0;
        if(!root)
            return 0;
        else
        {
            level = 1 + max(tree_depth2(root->lchild), tree_depth2(root->rchild));
        }
    
        return level;
    }
    
    void binary_tree::find_x_level(tree_node *root, int x) {
        static int level=1;
        if(root)
        {
            if(root->data == x)
            {
                cout << level << endl;
                return;
            }
    
            level++;
            find_x_level(root->lchild, x);
            find_x_level(root->rchild, x);
        }
    }
    
    tree_node *binary_tree::pre_in_create_tree2(int *A, int *B, int s1, int e1, int s2, int e2) {
        if(s1>e1 || s2>e2)
            return nullptr;
        tree_node *root = new tree_node();
        root->data=A[s1];
        for(int i=s2; i<=e2; ++i)
        {
            if(A[s1] == B[i])
            {
                root->lchild=pre_in_create_tree2(A,B,s1+1,s1+i-s2, s2, i-1);
                root->rchild=pre_in_create_tree2(A,B,i-s2+s1+1,e1,i+1,e2);
            }
        }
    
        return root;
    }
    
    tree_node *binary_tree::pre_in_create_tree(int *A, int *B, int s1, int e1, int s2, int e2) {
    
        return nullptr;
    }
    
    
    /**
     * 对应于博客上的代码是有问题的,617行
     *
     * */
    bool binary_tree::is_complete(tree_node *root) {
        queue<tree_node *> tree_que;
    
        if(!root)
            return true;
    
        tree_que.push(root);
    
        tree_node *tmp = tree_que.front();
        while(tmp)
        {
            tree_que.pop();
            tree_que.push(tmp->lchild);
            tree_que.push(tmp->rchild);
            tmp = tree_que.front();
        }
    
        tree_que.pop();// 把空pop出来
        // 因为以经有一个空了,所以只要头不为空就不是完全二叉树
        while(!tree_que.empty())
        {
            if(tree_que.front())
                return false;
            tree_que.pop();
        }
        return true;
    }
    
    int binary_tree::double_son_node(tree_node *root) {
    
        if(root == nullptr)
            return 0;
    
        if(root->lchild && root->rchild)
            return double_son_node(root->lchild)+double_son_node(root->rchild)+1;
        else
            return double_son_node(root->lchild)+double_son_node(root->rchild);
    }
    
    
    /*
     * 交互二叉树的左右子树(后序遍历的应用)
     * 1.首先交换root的左孩子的左右子树,
     * 2.然后交换root的右孩子的左右子树
     * 3.最后交换root的左右孩子,当结点为空时递归结束
    */
    void binary_tree::swap_lrchild(tree_node *root) {
        tree_node *tmp;
        if(root)
        {
            swap_lrchild(root->lchild);
            swap_lrchild(root->rchild);
            tmp=root->lchild;
            root->lchild=root->rchild;
            root->rchild=tmp;
        }
    }
    
    void binary_tree::swap_lrchild2(tree_node *root) {
        tree_node *p, *tmp;
        queue<tree_node *> tree_que;
    
        if(root)
        {
            tree_que.push(root);
        }
        while(!tree_que.empty())
        {
            p = tree_que.front();
            tree_que.pop();
    
            if(p->lchild)
                tree_que.push(p->lchild);
            if(p->rchild)
                tree_que.push(p->rchild);
    
            tmp = p->lchild;
            p->lchild = p->rchild;
            p->rchild = tmp;
        }
    }
    
    // 对应的博客中的代码有问题
    // 715 行
    int binary_tree::search_k_node(tree_node *root, int k) {
        static int flg = 0;
        static int ans = -1;
    
        if(root)
        {
            flg++;
            if(flg == k)
            {
                ans = root->data;
                return ans;
            }
            search_k_node(root->lchild, k);
            search_k_node(root->rchild, k);
        }
        return ans;
    }
    
    /**
     * 思想很简单,但是destory_tree
     * 写的删除不了根节点,这个代码就不测了
     *
     * */
    void binary_tree::destory_x_node(tree_node *root, int k) {
        if(root)
        {
            if(root->data == k)
            {
                destory_tree(root);
                return;
            }
    
            queue<tree_node *> tree_que;
    
            tree_que.push(root);
    
            while(!tree_que.empty())
            {
                tree_node *tmp=tree_que.front();
                tree_que.pop();
    
                if(tmp->lchild)
                {
                    if(tmp->lchild->data == k)
                    {
                        destory_tree(root->lchild);
                        root->lchild= nullptr;
                    }else
                    {
                        tree_que.push(tmp->lchild);
                    }
                }
                if(tmp->rchild)
                {
                    if(tmp->rchild->data == k)
                    {
                        destory_tree(root->rchild);
                        root->rchild= nullptr;
                    }else
                    {
                        tree_que.push(tmp->rchild);
                    }
                }
            }
        }
        return;
    }
    
     /*
     780  * 打印X结点的所有祖先,用到了非递归后序遍历的栈中信息
     781  * 1.非递归后序遍历找到X
     782  * 2.此时栈中的所有元素均为该结点的祖先结点
     783  * Note:树上的代码是后序遍历的不同写法,感觉没必要记那种(应该看一下深入理解后序遍历),
     784  * 会一种就够了了,所以我的代码,就是把上边的后序遍历中的输出语句该为了判断是否是当前结点。
     785  * 王道 P.133 第十二题
    
     博客中写的太恶心了,不要用那种
     786  * */
    
    void binary_tree::print_ancestor_node(tree_node *root, int x) {
        stack<tree_node *> tree_stack;
        tree_node *vis = nullptr;
         if(!root)
         {
             cout << "tree is empyt" << endl;
             return;
         }
    
         while(root || !tree_stack.empty())
         {
             if(root)
             {
                 tree_stack.push(root);
                 root = root->lchild;
             }else{
                 root = tree_stack.top();
                 if(root->rchild && root->rchild != vis)
                 {
                     root=root->rchild;
                     tree_stack.push(root);
                     root=root->lchild;
                 }else{
                     root=tree_stack.top();
                     tree_stack.pop();
                     /// 将后序遍历的输出改为判断是否为x节点
                     // 是x节点,跳出循环,栈中元素极为祖先
                     if(root->data == x)
                         break;
    
                     vis=root;
                     root=nullptr;
                 }
             }
         }
    
         while(!tree_stack.empty())
         {
             cout << tree_stack.top()->data << endl;
             tree_stack.pop();
         }
        return;
    }
    
    /*
     829  * 求 p q两个结点的最近公共祖先,非递归后序遍历的应用,就是利用栈信息
     830  * 假设p 在 q的左边
     831  * 1.后序遍历必然先遍历到 p,这时把栈中的信息借用辅助栈保存起来
     832  * 2.继续遍历,遍历到 q 结点的时候,将栈中的结点逐个和辅助栈的结点匹配,
     833  *      第一个相等的元素就是p & q的最近公共祖先
     834  * 王道 P.134 第13题
     835  * */
    tree_node *binary_tree::nearest_comm_ancestor(tree_node *root, int p, int q) {
        stack<tree_node *> tree_stack;
        stack<tree_node *> ass_tree_stack;
        tree_node *vis = nullptr;
        if(!root)
        {
            cout << "tree is empyt" << endl;
            return nullptr;
        }
    
        while(root || !tree_stack.empty())
        {
            if(root)
            {
                tree_stack.push(root);
                root = root->lchild;
            }else{
                root = tree_stack.top();
                if(root->rchild && root->rchild != vis)
                {
                    root=root->rchild;
                    tree_stack.push(root);
                    root=root->lchild;
                }else{
                    root=tree_stack.top();
                    tree_stack.pop();
                    /// 将后序遍历的输出改为判断是否为x节点
                    // 是x节点,跳出循环,栈中元素极为祖先
                    if(root->data == p)
                    {
                        ass_tree_stack = tree_stack;
                    }
                    if(root->data == q)
                    {
                        vector<tree_node *> s1_info;
                        vector<tree_node *> s2_info;
    
                        while(!tree_stack.empty())
                        {
                            s1_info.push_back(tree_stack.top());
                            tree_stack.pop();
                        }
    
                        while(!ass_tree_stack.empty())
                        {
                            s2_info.push_back(ass_tree_stack.top());
                            ass_tree_stack.pop();
                        }
    
                        for (auto i=s1_info.begin(); i!=s1_info.end(); ++i) {
                            for (auto j = s2_info.begin(); j != s2_info.end() ; j++) {
                                if((*i) == (*j))
                                {
                                    cout << *i << endl;
                                    return *i;
                                }
    
                            }
    
                        }
                    }
    
                    vis=root;
                    root=nullptr;
                }
            }
        }
    
    
        return nullptr;
    }
    
    int binary_tree::tree_width(tree_node *root) {
    
        queue<tree_node *> tree_queue;
    
        if(!root)
            return 0;
    
        int tree_width=1;
        tree_queue.push(root);
        while(true)
        {
            int len = (int)tree_queue.size(); // 当前层具有的节点个数
            if(len == 0)
                break;
            while(len > 0) // 如果当前层还有节点
            {
                tree_node *tmp = tree_queue.front();
                tree_queue.pop(); // 出队,
                len --;//长度减1
                if(tmp->lchild)
                    tree_queue.push(tmp->lchild); // 下一层入队
                if(tmp->rchild)
                    tree_queue.push(tmp->rchild); // 下一层入队
            }
            tree_width = max(tree_width,(int)tree_queue.size()); // 得到最大宽度
        }
        return tree_width;
    }
    
    /**
     * 直接抄下来,没有细看
     *
     * */
    void binary_tree::pre_to_post(int *pre, int s1, int e1, int *post, int s2, int e2) {
        int mid;
        if(e1>=s1)
        {
            post[e2]=pre[e1];
            mid = (e1-s1)/2;
            pre_to_post(pre, s1+1,s1+mid,post,s2,s2+mid-1);
            pre_to_post(pre, s1+mid+1, e1, post, s1+mid, e2-1);
        }
    }
    
    /**
     *
     * 没有细看
     * */
    tree_node *head, *pre= nullptr;
    tree_node *binary_tree::inorder_list(tree_node *root) {
    
        if(root)
        {
            inorder_list(root->lchild);
    
            if(!root->lchild && !root->rchild)
            {
                if(!pre)
                {
                    head = root;
                    pre = root;
                }else{
                    pre->rchild = root;
                    pre = root;
                }
                inorder_list(root->rchild);
                pre->rchild= nullptr;
            }
        }
    
        return head;
    }
    
    /**
     *
     * 没有细看
     * */
    void binary_tree::link(tree_node *root, tree_node *head, tree_node *tail) {
        if(root)
        {
            if(!root->lchild && !root->rchild)
            {
                if(!head)
                {
                    head = root;
                    tail = root;
                }else
                {
                    tail->rchild = root;
                    tail = root;
                }
            }
    
            link(root->lchild, head, tail);
            link(root->rchild, head, tail);
        }
    }
    
    
    
    bool binary_tree::is_similar(tree_node *root1, tree_node *root2) {
    
        int l_data, r_data;
        if(!root1 && !root2)
            return true;
        else if(!root1 && !root2)
            return false;
        else
        {
            l_data = is_similar(root1->lchild, root2->lchild);
            r_data = is_similar(root1->lchild, root2->rchild);
            return (l_data&&r_data);
        }
    }
    
    
    int binary_tree::WPL(tree_node *node) {
        return 0;
    }
    
    
    int main() {
        // 1 2 0 0 3 0 4 5 0 0 0
        // 1 0 2 0 0
        std::cout << "Hello, World!" << std::endl;
    
        binary_tree bt;
        binary_tree bt1;
        bt.root = bt.build_tree(1, "root");
        bt1.root = bt1.build_tree(1, "root");
        bt.pre_order(bt.root);
        bt.in_order(bt.root);
        bt.post_order(bt.root);
        cout<< "node sum is : " << bt.sum_node(bt.root) << endl;
        cout<< "leaf node sum is : " << bt.sum_leaf(bt.root) << endl;
        cout<< "tree equals is : " << bt.tree_equals(bt.root, bt1.root) << endl;
    //    bt.destory_tree(bt.root);
    //    cout<< "node sum is : " << bt.sum_node(bt.root) << endl;
    //    cout << bt.root->data << endl;
    
        binary_tree bt2;
        bt2.root = bt.copy_tree(bt.root);
        cout<< "node sum is : " << bt2.sum_node(bt2.root) << endl;
        cout << bt2.tree_depth2(bt2.root)<< endl;
    
        bt2.find_x_level(bt2.root, 2);
    
        int A[] = {1,2,4,7,3,5,6,8};
        int B[] = {4,7,2,1,5,3,8,6};
        binary_tree bt3;
        bt3.root = bt3.pre_in_create_tree2(A,B,0,7,0,7);
        bt3.non_rec_pre_order(bt3.root);
    
        cout << bt1.search_k_node(bt1.root, 15) << endl;
        cout << bt1.nearest_comm_ancestor(bt1.root, 2,5)->data << endl;
        bt1.pre_order(bt1.root);
        cout << bt1.tree_width(bt1.root) << endl;
    
        return 0;
    }
    

      

    一下两个版本部分代码存在问题,请忽略

    ///练练练
    #include <stdio.h>
    #include <stdlib.h>
    typedef char Telemtype;
    typedef struct BinTree{
        Telemtype data;
        struct BinTree *LChild;
        struct BinTree *RChild;
    }BinaryTree;
    
    /*
     * 建树是通过先序遍历的方法进行,先输如一个字符,如果不是‘0’,则进行
     * 树的创建,否则不建树
     * 树的创建需要有一下几个步骤
     * 1.给树根结点申请空间
     * 2.给根节点的数据域赋值
     * 3.递归的分别创建左右子树
     * */
    BinaryTree* create_tree(BinaryTree *Tree)
    {
        Telemtype tmp;
        scanf("%c", &tmp);
        if(tmp == '0')
            return 0;
        Tree = (BinaryTree*)malloc(sizeof(BinaryTree));
        Tree->data = tmp;
        Tree->LChild = create_tree(Tree->LChild);
        Tree->RChild = create_tree(Tree->RChild);
        return Tree;
    }
    
    /*
     * 递归写法的几种树的遍历(先序,中序,后序),都一样
     * 但是这样的写法其实在其他操作中也类似,
     * 1.比如说统计节点个数
     * 2.树的销毁等等
     * 对于时间复杂度,因为每个节点均遍历一次,所以复杂度为O(n)
     * */
    void preorder_traverse(BinaryTree *tree)
    {
        if(tree)
        {
            printf("%c ", tree->data);
            preorder_traverse(tree->LChild);
            preorder_traverse(tree->RChild);
        }
    }
    
    void inorder_traverse(BinaryTree *tree)
    {
        if(tree)
        {
            inorder_traverse(tree->LChild);
            printf("%c ", tree->data);
            inorder_traverse(tree->RChild);
        }
    }
    
    void postorder_traverse(BinaryTree *tree)
    {
        if(tree)
        {
            postorder_traverse(tree->LChild);
            postorder_traverse(tree->RChild);
            printf("%c ", tree->data);
        }
    }
    
    /*
     * 统计叶子节点的个数
     * 1.先看当前节点是否是叶子节点,如果是叶子节点,sum值加一
     * 2.然后递归的分别统计左右子树中拥有的叶子节点的个数
     * */
    int sum_left(BinaryTree *tree)
    {
        int sum = 0;
        if(tree)
        {
            if(!tree->LChild && !tree->RChild)
                sum ++;
            if(tree->LChild)
                sum += sum_left(tree->LChild);
            if(tree->RChild)
                sum += sum_left(tree->RChild);
        }
        return sum;
    }
    /*
     * 1.如果两颗树是空树,则两颗树相等
     * 2.否则,判断当前树的根节点是否相等
     * 3.然后再递归的判断左右子树
     * 4.如果都相同,返回1.否则返回0
     * */
    int is_equal(BinaryTree *T1, BinaryTree *T2)
    {
        if(!T1 && !T2)
        {
            return 1;
        }
        if(T1 && T2 && T1->data == T2->data)
            if(is_equal(T1->LChild, T2->LChild))
                if(is_equal(T1->RChild, T2->RChild))
                    return 1;
        return 0;
    }
    /*
     * 思路同后序遍历
     * 1.先销毁左右子树
     * 2.然后释放当前根节点的空间
     * 3.将指针的指向   指到NULL
     * Note:free(tree)仅仅收回内存,不会改变T的指向。
     * */
    void destory_tree(BinaryTree *tree)
    {
        if(tree == NULL)
            return;
        destory_tree(tree->LChild);
        destory_tree(tree->RChild);
        free(tree);
        tree = NULL;
        return;
    }
    
    /*
     * 树的复制包含两部分,第一部分是,为根节点设置值和要指向的左右子树
     * 第二部分就是递归的复制左右子树
     * 左右子树的复制,还是同后序遍历
     * */
    BinaryTree *get_tree_node(Telemtype item, BinaryTree *LChild, BinaryTree *RChild)
    {
        BinaryTree *tree;
        tree = (BinaryTree*)malloc(sizeof(BinaryTree));
        tree->data = item;
        tree->LChild = LChild;
        tree->RChild = RChild;
        return tree;
    }
    
    BinaryTree* copy_tree(BinaryTree *tree)
    {
        BinaryTree *newLChild, *newRChild, *newtree;
        if(!tree)
            return NULL;
        if(tree->LChild)
            newLChild = copy_tree(tree->LChild);
        else
            newLChild = NULL;
    
        if(tree->RChild)
            newRChild = copy_tree(tree->RChild);
        else
            newRChild = NULL;
    
        newtree = get_tree_node(tree->data, newLChild, newRChild);
        return newtree;
    }
    
    /*
     * 非递归的遍历就要用到 Stack & Queue
     * 1.Stack的初始化  stack.top = -1;
     * 2.Queue的初始化  queue.front = queue.rear = 0;
     * */
    typedef struct TreeStack{
        BinaryTree *stroe[1000];
        int tag[1000];          //后序遍历要用到的标志域
        int top;
    }Tstack;
    /*
     *1.压栈操作,top+1 然后在当前位置存放节点信息
     *2.出栈操作,返回当前栈顶元素,然后top-1
     * */
    void push_stack(Tstack *stack, BinaryTree *tree)
    {
        if(stack->top == 1000)
            printf("the stack is full!
    ");
        else{
            stack->top++;
            stack->stroe[stack->top] = tree;
        }
    }
    
    BinaryTree* pop_stack(Tstack *stack)
    {
        if(stack->top == -1)
            return NULL;
        else{
            stack->top--;
            return stack->stroe[stack->top+1];
        }
    }
    
    typedef  struct TreeQueue{
        BinaryTree *stroe[1000];
        int front;
        int rear;
    }Tqueue;
    /*
     * 入队,出队比较简单
     * */
    void enqueue(Tqueue *queue, BinaryTree *tree)
    {
        if(queue->rear == 1000)
            printf("the queue is full!
    ");
        else{
            queue->stroe[queue->rear] = tree;
            queue->rear++;
        }
    }
    
    BinaryTree* dequeue(Tqueue *queue)
    {
        if(queue->front == queue->rear)
            return NULL;
        else{
            queue->front++;
            return queue->stroe[queue->front-1];
        }
    
    }
    /*
     * Note: 请先参照中序遍历,中序遍历是教科书说法,比较准确
     * 先序遍历的非递归算法和中序遍历的非递归算法类似
     * 1.先访问当前根结点,并将根结点入栈,往左走
     * 2.当当前节点没有左孩子时,将当前结点出栈,并访问他的右孩子
     * 3.一直循环,直到栈空
     * */
    void non_recursion_preorder(BinaryTree *tree)
    {
        Tstack stack;
        stack.top = -1;
        if(!tree)
            printf("the tree is empty!
    ");
        else{
            while(tree || stack.top != -1)
            {
                if(tree)
                {
                    printf("%c ", tree->data);
                    push_stack(&stack, tree);
                    tree = tree->LChild;
                }else{
                    tree = pop_stack(&stack);
                    tree = tree->RChild;
                }
                /*
                 while(tree)                        //类似于中序遍历
                 {
                    printf("%c ", tree->LChild);
                    push_stack(&stack, tree);
                    tree = tree->LChild;
                 }
                    tree = pop_stack(&stack);
                    tree = tree->RChild;
                 * */
            }
        }
    }
    
    /*
     * 1.先扫描(并非访问)根结点的所有左结点并将他们一一进栈
     * 2.当当前结点没有左子树(或者左孩子结点已经访问过),将其出栈,访问他
     * 3.然后扫描该结点的右孩子结点,将其进栈,再扫描右孩子结点的所有左结点并一一进栈,如此继续,直到栈空
     * */
    void non_recursion_inorder(BinaryTree *tree)
    {
        Tstack stack;
        stack.top = -1;
        if(!tree)
        {
            printf("the tree is empty!
    ");
        }else {
            while(tree || stack.top != -1)      //树根节点不空,或者栈不空时
            {
                if(tree){
                    push_stack(&stack, tree);   //根结点进栈,遍历左子树
                    tree = tree->LChild;        //每次遇到非空的左子树,就往左走
                }else{
                    tree = pop_stack(&stack);   //根指针退栈,访问根节点,遍历右子树
                    printf("%c ", tree->data);
                    tree = tree->RChild;
                }
    
                /*
                 while(tree)                     //另外一种好的写法,只要有左子树,就往左走
                 {
                     push_stack(&stack, tree);   //根结点进栈,遍历左子树
                     tree = tree->LChild;        //每次遇到非空的左子树,就往左走
                 }
                 tree = pop_stack(&stack);       //根指针退栈,访问根节点,遍历右子树
                 printf("%c ", tree->data);
                 tree = tree->RChild;
                 * */
            }
        }
    }
    
    /*
     * 后序遍历是先访问左右子树,最后访问根结点。
     * 当用栈来存储结点时,必须分清返回根结点时,是从左结点返回的,还是从右结点返回的
     * 用辅助指针可以写(也可以在结点中增加一个标志域)
     * 1.从根结点一直向左走,直到没有左子树
     * 2.转向向右走,先取栈顶指针
     * 3.判断是否有右子树
     *    4.若存在右子树且右子树是否被访问过,转向右子树,将右子树根结点压栈,继续走到最左边
     *    5.不满足4,弹出当前根结点,进行访问,并做标记,将tmp置空,必须将tmp置空,跳过向左走,直接向右走
     *
     * Note:当访问一个结点 *tmp时,栈中的结点恰好是*tmp结点的所有祖先。
     *      从栈底到栈顶结点再加上*tmp结点,刚好构成从根结点到*tmp的一条路径
     *      在很多算法设计中都用到了这一特行,比如:
     *                *求根结点到某结点的路径
     *                *求两个结点的最近公共祖先
     * */
    
    void non_recursion_postorder(BinaryTree *tree)
    {
        Tstack stack;
        stack.top = -1;
        BinaryTree *tmp = tree;
        BinaryTree *tag = NULL;
        while(tmp || stack.top != -1)
        {
            if(tmp)                                    //走到最左边
            {
                push_stack(&stack, tmp);
                tmp = tmp->LChild;
            }else{                                      //向右走
                tmp = pop_stack(&stack);                //取栈顶元素  这里应该是获取栈顶元素,但是不能出栈  王道 P.128
                push_stack(&stack, tmp);
                if(tmp->RChild && tmp->RChild != tag)   //如果右子树存在,且未被访问过
                {
                    tmp = tmp->RChild;                  //转向右子树
                    push_stack(&stack, tmp);            //压栈
                    tmp = tmp->LChild;                  //继续走到最左边
                }else{                                  //如果右子树不存在,或者已经访问过
                    tmp = pop_stack(&stack);            //弹出当前的根结点
                    printf("%c ", tmp->data);           //进行访问
                    tag = tmp;                          //标记访问过
                    tmp = NULL;                         //访问过后,重置tmp指针,必须将tmp置空,跳过向左走,直接向右走
                }
            }
        }
    }
    
    //后序遍历的标记数据域标记写法
    void non_recursion_postorder2(BinaryTree *tree)
    {
        Tstack stack;
        stack.top = -1;
        if(!tree)
            printf("the tree is empty!
    ");
        else{
            while(tree || stack.top != -1) {
                while (tree) {
                    push_stack(&stack, tree);
                    stack.tag[stack.top] = 0;       //设置访问标记,0为第一次访问,1为第二次访问
                    tree = tree->LChild;
                }
                if (stack.tag[stack.top] == 0)       //第一次访问时,转向同层右结点
                {
                    tree = stack.stroe[stack.top];  //左走到底时,tree是空,必须有这句话
                    stack.tag[stack.top] = 1;
                    tree = tree->RChild;
                } else {
                    while (stack.tag[stack.top] == 1)//在栈中找到下一个第一次范格纹你的结点,退出循环时并没有pop,所以为其左子结点
                    {
                        tree = pop_stack(&stack);
                        printf("%c ", tree->data);
                    }
                    tree = NULL;
                }
            }
        }
    }
    
    /*
     * 层次遍历,其实就是BFS  (广度优先搜索)
     * */
    void levelorder(BinaryTree *tree)
    {
        Tqueue queue;
        queue.front = queue.rear = 0;
        enqueue(&queue, tree);              //根结点入队
        while(queue.front != queue.rear) {  //队列不为空时,循环
            tree = dequeue(&queue);         //队头元素出队
            printf("%c ", tree->data);      //访问当前结点
            if (tree->LChild != NULL)
                enqueue(&queue, tree->LChild);
            if (tree->RChild != NULL)
                enqueue(&queue, tree->RChild);
        }
    }
    /*
     * 层次遍历的应用,将树自下而上,自右向左遍历,
     * 就是把层次遍历访问的结点入栈,然后从栈弹出的顺序
     * 王道 P.128
     * */
    void invert_levelorder(BinaryTree *tree)
    {
        Tqueue queue;
        Tstack stack;
        if(tree != NULL)
        {
            stack.top = -1;
            queue.front = queue.rear = 0;
            enqueue(&queue, tree);              //根结点入队
            while(queue.front != queue.rear) {
                tree = dequeue(&queue);
                push_stack(&stack, tree);      //当前结点 入栈
                if (tree->LChild != NULL)
                    enqueue(&queue, tree->LChild);
                if (tree->RChild != NULL)
                    enqueue(&queue, tree->RChild);
            }
    
            while(stack.top != -1)
            {
                tree = pop_stack(&stack);
                printf("%c ", tree->data);
            }
        }
    }
    /*
     * 王道 第五题 P.129 通过层次遍历获得树的深度
     * */
    int tree_depth(BinaryTree *tree)
    {
        if(!tree)
            return 0;
        Tqueue queue;
        queue.front = queue.rear = 0;
        int last = 1, level = 0;        //last指向下一层的第一个结点
        enqueue(&queue, tree);          //根结点入队
        while(queue.front != queue.rear)
        {
            tree = dequeue(&queue);
            if(tree->LChild)
                enqueue(&queue, tree->LChild);
            if(tree->RChild)
                enqueue(&queue, tree->RChild);
            //好好理解这里
            if(queue.front == last)     //处理该层的最右结点
            {
                level++;                //层数加一
                last = queue.rear;      //last指向下层
            }
        }
        return level;
    }
    
    int max(int a, int b)
    {
        return (a > b) ? a : b;
    }
    /*
     * 统计树的深度,同后序遍历
     * 1.如果树空,深度为零
     * 2.否则分别递归求解左右子树的深度
     * 3.树的深度为 1+左右子树中更大的深度
     * */
    int tree_depth2(BinaryTree *tree)
    {
        int d = 0, dl, dr;
        if(!tree)
            d = 0;
        else
        {
            dl = tree_depth2(tree->LChild);
            dr = tree_depth2(tree->RChild);
            d = 1 + max(dl, dr);
        }
        return d;
    }
    
    /*
     * NOTE: 关键的地方还是区间划分
     * */
    BinaryTree* pre_in_create_tree2(Telemtype A[], Telemtype B[], int start1, int end1, int start2, int end2)
    {
        if(start1 > end1 || start2 > end2)
            return NULL;
        BinaryTree *tree;
        tree = (BinaryTree*)malloc(sizeof(BinaryTree));
        tree->data = A[start1];                                         //根结点
        for(int i = start2; i <=end2; i++)                       //根结点在中序中的划分
        {
            if(A[start1] == B[i]) {
                tree->LChild = pre_in_create_tree2(A, B, start1 + 1, start1 + i - start2, start2, i - 1);
                tree->RChild = pre_in_create_tree2(A, B, i - start2 + start1 + 1, end1, i + 1, end2);
            }
        }
        return tree;
    }
    
    /*
     * 由先序和中序遍历,来唯一确定一棵二叉树
     * 1.根据先序序列确定树的根结点
     * 2.根据根结点在中序遍历中划分左右子树,然后根据左右子树结点在先序序列中的次序,可以确定子树的根结点,(即回到第一步)
     * 王道书上 P.130 第六题
     * */
    BinaryTree* pre_in_create_tree(Telemtype A[], Telemtype B[], int startPre, int endPre, int startIn, int endIn)
    {
        int i;
        BinaryTree *tree;
        tree = (BinaryTree*)malloc(sizeof(BinaryTree));
        tree->data = A[startPre];
        for(i = startIn; B[i]!=tree->data; ++i);
        int LChild_len = i - startIn;                                    //左子树的长度
        int RChild_len = endIn - i;                                      //右子树的长度
    
        if(LChild_len)                                                  //递归建立左子树
            tree->LChild = pre_in_create_tree(A, B, startPre+1, startPre+LChild_len, startIn, startIn+LChild_len-1);   //划分的区间,是值得注意的地方
        else
            tree->LChild = NULL;
    
        if(RChild_len)                                                  //递归建立右子树
            tree->RChild = pre_in_create_tree(A, B, endPre-RChild_len+1, endPre, endIn-RChild_len+1, endIn);
        else
            tree->RChild = NULL;
        return tree;
    }
    /*
     * 层次遍历的应用
     * 1.将所有结点入队列(包括空结点)。
     * 2.当遇到空结点时,判断其后是否存在非空结点,如果存在,则不是完全二叉树
     * 王道 P.131 第七题
     * */
    bool is_complete(BinaryTree *tree)
    {
        Tqueue queue;
        queue.front = queue.rear = 0;
        if(!tree)
            return 1;                           //空树为满二叉树
        enqueue(&queue, tree);
        while(queue.front != queue.rear)
        {
            if(!tree)                           //结点非空,将其左右子树入队
            {
                enqueue(&queue, tree->LChild);
                enqueue(&queue, tree->RChild);
            } else {                            //结点非空,检查其后是否有非空结点
                while(queue.front != queue.rear)
                {
                    tree = dequeue(&queue);
                    if(tree)                    //结点非空,为非完全二叉树
                        return 0;
                }
            }
        }
        return 1;
    }
    /*
     * 统计双分支结点的个数
     * 递归思路
     * f(root) = 0;                                      若root == NULL
     * f(root) = f(root->LChild) + f(root->RChild) + 1;  当前root结点为双分支结点
     * f(root) = f(root->LChild) + f(root->RChild);      其他情况(当前root为单分支结点,或者root为叶子结点)
     * 王道P.131 第八题
     * */
    int double_son_node(BinaryTree *tree)
    {
        if(tree == NULL)
            return 0;
        if(tree->LChild != NULL && tree->RChild != NULL)
        {
            return  double_son_node(tree->LChild) + double_son_node(tree->RChild) + 1;
        }else {
            double_son_node(tree->LChild) + double_son_node(tree->RChild);
        }
    }
    
    /*
     * 交互二叉树的左右子树(后序遍历的应用)
     * 1.首先交换root的左孩子的左右子树,
     * 2.然后交换root的右孩子的左右子树
     * 3.最后交换root的左右孩子,当结点为空时递归结束
     * 王道  P.131  第九题
     * */
    void swap_lrchild(BinaryTree *tree)
    {
        BinaryTree *tmp;
        if(tree)
        {
            swap_lrchild(tree->LChild);
            swap_lrchild(tree->RChild);
            tmp = tree->LChild;
            tree->LChild = tree->RChild;
            tree->RChild = tmp;
        }
    }
    /*
     * 求先序遍历中的第k个结点的值(确保k值在有效范围内)
     * 1.设置一个全局变量itag记录访问过的结点的序号,其初值是根结点在先序序列中的序号,即为1
     * 2.当二叉树tree为空时,返回特殊结点“#”,当itag == k时,表示找到了满足条件的结点,返回 tree->data
     * 3.当itag != k 是,则递归的在左右子树中继续查找
     * 王道   P.131    第十题
     * */
    int itag = 1;
    Telemtype search_k_node(BinaryTree *tree, int k)
    {
        if(tree == NULL)
            return '#';
        if(itag == k)
            return tree->data;
        itag++;
        Telemtype ch = search_k_node(tree->LChild, k);
        if(tree->LChild != NULL)
            return ch;
        ch = search_k_node(tree->RChild, k);
        if(tree->RChild != NULL)                        //确保一定有返回值
            return ch;
        else
            return '#';
    }
    /*
     * 层次遍历的基本思想,就是找到 X 结点,然后删除它这棵树
     * 1.如果当前树根为X结点,直接删掉
     * 2.否则,进行层次遍历,去找 X,找到了就删掉,
     * Note:应为之前封装的好,明显要比书上的代码形式统一,也好看的多
     * 王道 P.132 第十一题
     * */
    void destroy_x_tree(BinaryTree *tree, Telemtype x)
    {
        if(tree)
        {
            if(tree->data == x)
            {
                destory_tree(tree);
                return;
            }
            Tqueue queue;
            queue.front = queue.rear = 0;
            enqueue(&queue, tree);
            while(queue.front != queue.rear)
            {
                tree = dequeue(&queue);
                if(tree->LChild)
                {
                    if(tree->LChild->data == x)
                    {
                        destory_tree(tree->LChild);
                        tree->LChild = NULL;
                    } else {
                        enqueue(&queue, tree->LChild);
                    }
                }
                if(tree->RChild)
                {
                    if(tree->RChild->data == x)
                    {
                        destory_tree(tree->RChild);
                        tree->RChild = NULL;
                    }else{
                        enqueue(&queue, tree->RChild);
                    }
                }
            }
        }
        return;
    }
    
    /*
     * 打印X结点的所有祖先,用到了非递归后序遍历的栈中信息
     * 1.非递归后序遍历找到X
     * 2.此时栈中的所有元素均为该结点的祖先结点
     * Note:树上的代码是后序遍历的不同写法,感觉没必要记那种(应该看一下深入理解后序遍历),
     * 会一种就够了了,所以我的代码,就是把上边的后序遍历中的输出语句该为了判断是否是当前结点。
     * 王道 P.133 第十二题
     * */
    
    void print_ancestor_node(BinaryTree *tree, Telemtype x)
    {
        Tstack stack;
        stack.top = -1;
        if(!tree)
            printf("the tree is empty!
    ");
        else{
            while(tree || stack.top != -1) {
                while (tree) {
                    push_stack(&stack, tree);
                    stack.tag[stack.top] = 0;       //设置访问标记,0为第一次访问,1为第二次访问
                    tree = tree->LChild;
                }
                if (stack.tag[stack.top] == 0)       //第一次访问时,转向同层右结点
                {
                    tree = stack.stroe[stack.top];  //左走到底时,tree是空,必须有这句话
                    stack.tag[stack.top] = 1;
                    tree = tree->RChild;
                } else {
                    while (stack.tag[stack.top] == 1)//在栈中找到下一个第一次范格纹你的结点,退出循环时并没有pop,所以为其左子结点
                    {
                        tree = pop_stack(&stack);
                        if(tree->data == x)
                        {
    
                            printf("
    %c ancestor is : 
    ",tree->data);;
                            for(int i = 0; i <= stack.top; ++i)
                            {
                                printf("%c ", stack.stroe[i]->data);
                            }
                            return;
                        }
                    }
                    tree = NULL;
                }
            }
        }
    }
    
    /*
     * 2016/9/1  今天就写到这里,感觉自己对后序遍历的非递归算法,理解不够。
     * 先不写了回头总结总结
     * */
    
    int main()
    {
        BinaryTree *tree;
        tree = create_tree(tree);
        printf("preorder
    ");
        //preorder_traverse(tree);
        non_recursion_preorder(tree);
        printf("
    inorder
    ");
        //inorder_traverse(tree);
        non_recursion_inorder(tree);
        printf("
    postorder
    ");
        //postorder_traverse(tree);
        non_recursion_postorder(tree);
        printf("
    levelorder
    ");
        levelorder(tree);
        printf("
    invert_levelorder
    ");
        invert_levelorder(tree);
        printf("
    left_node`s number is %d
    ", sum_left(tree));
        printf("
    depth is %d
    ", tree_depth2(tree));
        printf("
    depth is %d
    ", tree_depth(tree));
        //Telemtype A[] = {'A','B','C','D','E','F','G','H','K'};
        //Telemtype B[] = {'B','D','C','A','E','H','G','K','F'};
        Telemtype A[] = {' ','1','2','4','7','3','5','6','8'};
        Telemtype B[] = {' ','4','7','2','1','5','3','8','6'};
        BinaryTree *root, *root2;
        root = pre_in_create_tree(A, B, 1, 8, 1, 8);
        puts("
    *********************root traverse
    ");
        preorder_traverse(root);
        root2 = pre_in_create_tree2(A, B, 1, 8, 1, 8);
        puts("
    *********************root2 traverse
    ");
        preorder_traverse(root2);
        printf("is complete %d
    ", is_complete(root));
        printf("double son node is %d
    ", double_son_node(root));
    
        swap_lrchild(root2);
        preorder_traverse(root2);
        printf("
    %c
    ", search_k_node(root2, 4));
        destroy_x_tree(root2, '2');
        preorder_traverse(root2);
        puts("
    print_ancestor_node");
        print_ancestor_node(root, '5');
        printf("
    
    end!!
    
    ");
        return 0;
    }
    

      

    更新一些代码

       1 ///练练练
       2 #include <stdio.h>
       3 #include <stdlib.h>
       4 typedef char Telemtype;
       5 typedef struct BinaryTree{
       6     Telemtype data;
       7     struct BinaryTree *LChild;
       8     struct BinaryTree *RChild;
       9 }BinaryTree;
      10 /* function content
      11  *
      12  * BinaryTree *create_tree(BinaryTree *root)
      13  * preorder_traverse(BinaryTree *root)
      14  * void inorder_traverse(BinaryTree *root)
      15  * void postorder_traverse(BinaryTree *root)
      16  * int sum_node(BinaryTree *root)
      17  * int tree_equal(BinaryTree *T1, BinaryTree *T2)
      18  * void destory_tree(BinaryTree *root)
      19  * BinaryTree *copy_tree(BinaryTree *root)
      20  * void non_recursion_preorder(BinaryTree *root)
      21  * void non_recursion_inorder(BinaryTree *root)
      22  * void non_recursion_postorder(BinaryTree *root)
      23  * void non_recursion_postorder2(BinaryTree *root)
      24  * void levelorder(BinaryTree *root)
      25  * void invert_levelorder(BinaryTree *root)
      26  * int tree_depth(BinaryTree *root)
      27  * int tree_depth2(BinaryTree *root)
      28  * void search_x_level(BinaryTree *root, Telemtype x)
      29  * BinaryTree *pre_in_create_tree(Telemtype A[], Telemtype B[], int startPre, int endPre, int startIn, int endIn)
      30  * BinaryTree *pre_in_create_tree2(Telemtype A[], Telemtype B[], int s1, int e1, int s2, int e2)
      31  * int is_complete(BinaryTree *root)
      32  * int double_son_node(BinaryTree *tree)
      33  * void swap_lrchild(BinaryTree *tree)
      34  * void swap_lrchild2(BinaryTree *root)
      35  * Telemtype search_k_node(BinaryTree *tree, int k)
      36  * void destroy_x_tree(BinaryTree *tree, Telemtype x)
      37  * void print_ancestor_node(BinaryTree *tree, Telemtype x)
      38  * BinaryTree *nearest_comm_ancestor(BinaryTree *tree, Telemtype p, Telemtype q)
      39  * int tree_width(BinaryTree *root)
      40  * void pre_to_post(Telemtype pre[], int s1, int e1, Telemtype post[], int s2, int e2)
      41  * BinaryTree *inorder_List(BinaryTree *root)
      42  * void link(BinaryTree *root, BinaryTree *head, BinaryTree *tail)
      43  * int is_similar(BinaryTree *T1, BinaryTree *T2)
      44  * int WPL(BinaryTree *root)
      45  * */
      46 /*
      47  * 建树是通过先序遍历的方法进行,先输如一个字符,如果不是‘0’,则进行
      48  * 树的创建,否则不建树
      49  * 树的创建需要有一下几个步骤
      50  * 1.给树根结点申请空间
      51  * 2.给根节点的数据域赋值
      52  * 3.递归的分别创建左右子树
      53  * */
      54 BinaryTree *create_tree(BinaryTree *root)
      55 {
      56     Telemtype tmp;
      57     scanf("%c", &tmp);
      58     if(tmp == '0')
      59         return NULL;
      60     root = (BinaryTree*)malloc(sizeof(BinaryTree));
      61     root->data = tmp;
      62     root->LChild = create_tree(root->LChild);
      63     root->RChild = create_tree(root->RChild);
      64     return root;
      65 }
      66 
      67 /*
      68  * 递归写法的几种树的遍历(先序,中序,后序),都一样
      69  * 但是这样的写法其实在其他操作中也类似,
      70  * 1.比如说进行统计节点个数
      71  * 2.树的销毁等等
      72  * 对于时间复杂度,因为每个节点均遍历一次,所以复杂度为O(n)
      73  * */
      74 void preorder_traverse(BinaryTree *root)
      75 {
      76     if(root)
      77     {
      78         printf("%c ", root->data);
      79         preorder_traverse(root->LChild);
      80         preorder_traverse(root->RChild);
      81     }
      82 }
      83 
      84 void inorder_traverse(BinaryTree *root)
      85 {
      86     if(root)
      87     {
      88         inorder_traverse(root->LChild);
      89         printf("%c ", root->data);
      90         inorder_traverse(root->RChild);
      91     }
      92 }
      93 
      94 void postorder_traverse(BinaryTree *root)
      95 {
      96     if(root)
      97     {
      98         postorder_traverse(root->LChild);
      99         postorder_traverse(root->RChild);
     100         printf("%c ", root->data);
     101     }
     102 }
     103 /*
     104  * 统计二叉树中结点的个数
     105  * */
     106 int sum_node(BinaryTree *root)
     107 {
     108     if(!root)               //root == NULL
     109         return 0;
     110     else{
     111         return sum_node(root->LChild)
     112                + sum_node(root->RChild) + 1;
     113     }
     114 }
     115 
     116 /*
     117  * 统计叶子节点的个数
     118  * 1.先看当前节点是否是叶子节点,如果是叶子节点,sum值加一
     119  * 2.然后递归的分别统计左右子树中拥有的叶子节点的个数
     120  * */
     121 int sum_leaf(BinaryTree *root)
     122 {
     123     int sum = 0;
     124     if(root)
     125     {
     126         if(!root->LChild && !root->RChild)
     127             sum ++;
     128         if(root->LChild)
     129             sum += sum_leaf(root->LChild);
     130         if(root->RChild)
     131             sum += sum_leaf(root->RChild);
     132     }
     133     return sum;
     134 }
     135 /*
     136  * 1.如果两颗树是空树,则两颗树相等
     137  * 2.否则,判断当前树的根节点是否相等
     138  * 3.然后再递归的判断左右子树
     139  * 4.如果都相同,发回1.否则返回0
     140  * */
     141 int tree_equal(BinaryTree *T1, BinaryTree *T2)
     142 {
     143     if(!T1 && !T2)
     144         return 1;
     145 
     146     if(T1 && T2 && T1->data == T2->data)
     147     if(tree_equal(T1->LChild, T2->LChild))
     148     if(tree_equal(T1->RChild, T2->RChild))
     149         return 1;
     150     return 0;
     151 }
     152 /*
     153  * 思路同后序遍历
     154  * 1.先销毁左右子树
     155  * 2.然后释放当前根节点的空间
     156  * 3.将指针的指向   指到NULL
     157  * Note:free(tree)仅仅收回内存,不会改变T的指向。
     158  * */
     159 void destory_tree(BinaryTree *root)
     160 {
     161     if(!root)
     162         return;
     163 
     164     destory_tree(root->LChild);
     165     destory_tree(root->RChild);
     166     free(root);
     167     root = NULL;
     168     return;
     169 }
     170 
     171 /*
     172  * 树的复制包含两部分,一部分是,为要根节点设置值和要指向的左右子树
     173  * 第二部分就是递归的复制左右子树
     174  * 左右子树的复制,还是同后序遍历
     175  * */
     176 BinaryTree *get_tree_node(Telemtype data, BinaryTree *LChild, BinaryTree *RChild)
     177 {
     178     BinaryTree *root;
     179     root = (BinaryTree*)malloc(sizeof(BinaryTree));
     180     root->data = data;
     181     root->LChild = LChild;
     182     root->RChild = RChild;
     183     return root;
     184 }
     185 
     186 BinaryTree *copy_tree(BinaryTree *root)
     187 {
     188     BinaryTree *newLChild, *newRChild, *newRoot;
     189     if(!root)
     190         return NULL;
     191 
     192     if(root->LChild)
     193         newLChild = copy_tree(root->LChild);
     194     else
     195         newLChild = NULL;
     196     if(root->RChild)
     197         newRChild = copy_tree(root->RChild);
     198     else
     199         newRChild = NULL;
     200 
     201     newRoot = get_tree_node(root->data, newLChild, newRChild);
     202 
     203     return newRoot;
     204 }
     205 
     206 /*
     207  * 非递归的遍历就要用到 Stack & Queue
     208  * 1.Stack的初始化  stack.top = -1;
     209  * 2.Queue的初始化  queue.front = queue.rear = 0;
     210  * */
     211 typedef struct TreeStack{
     212     BinaryTree *stroe[1000];
     213     int tag[1000];          //后序遍历要用到的标志域
     214     int top;
     215 }Tstack;
     216 /*
     217  *1.压栈操作,top+1 然后在当前位置存放节点信息
     218  *2.出栈操作,返回当前栈顶元素,然后top-1
     219  * */
     220 void push_stack(Tstack *stack, BinaryTree *root)
     221 {
     222     if(stack->top == 1000)
     223         printf("the stack is full!
    ");
     224     else{
     225         stack->top++;
     226         stack->stroe[stack->top] = root;
     227     }
     228 }
     229 
     230 BinaryTree* pop_stack(Tstack *stack)
     231 {
     232     if(stack->top == -1)
     233         return NULL;
     234     else{
     235         stack->top--;
     236         return stack->stroe[stack->top+1];
     237     }
     238 }
     239 
     240 typedef  struct TreeQueue{
     241     BinaryTree *stroe[1000];
     242     int level[1000];
     243     int front;
     244     int rear;
     245 }Tqueue;
     246 /*
     247  * 入队,出队比较简单
     248  * */
     249 void enqueue(Tqueue *queue, BinaryTree *root)
     250 {
     251     if(queue->rear == 1000)
     252         printf("the queue is full!
    ");
     253     else{
     254         queue->stroe[queue->rear] = root;
     255         queue->rear++;
     256     }
     257 }
     258 
     259 BinaryTree* dequeue(Tqueue *queue)
     260 {
     261     if(queue->front == queue->rear)
     262         return NULL;
     263     else{
     264         queue->front++;
     265         return queue->stroe[queue->front-1];
     266     }
     267 
     268 }
     269 /*
     270  * Note: 请先参照中序遍历,中序遍历是教科书说法,比较准确
     271  * 先序遍历的非递归算法和中序遍历的非递归算法类似
     272  * 1.先访问当前根结点,并将根结点入栈,往左走
     273  * 2.当当前节点没有左孩子时,将当前结点出栈,并访问他的右孩子
     274  * 3.一直循环,直到栈空
     275  * */
     276 void non_recursion_preorder(BinaryTree *root)
     277 {
     278     Tstack stack;
     279     stack.top = -1;
     280     if(!root)
     281         printf("the tree is empty!
    ");
     282     else{
     283         while(root || stack.top != -1)
     284         {
     285             if(root)
     286             {
     287                 printf("%c ", root->data);
     288                 push_stack(&stack, root);
     289                 root = root->LChild;
     290             }else{
     291                 root = pop_stack(&stack);
     292                 root = root->RChild;
     293             }
     294             /*
     295              while(root)                        //类似于中序遍历,详见下边
     296              {
     297                 printf("%c ", root->LChild);
     298                 push_stack(&stack, root);
     299                 root = root->LChild;
     300              }
     301                 root = pop_stack(&stack);
     302                 root = root->RChild;
     303              * */
     304         }
     305     }
     306 }
     307 
     308 /*
     309  * 1.先扫描(并非访问)根结点的所有左结点并将他们一一进栈
     310  * 2.当当前结点没有左子树(或者做孩子结点已经访问过),将其出栈,访问他
     311  * 3.然后扫描该结点的右孩子结点,将其进栈,再扫描右孩子结点的所有左结点并一一进栈,如此继续,直到栈空
     312  * */
     313 void non_recursion_inorder(BinaryTree *root)
     314 {
     315     Tstack stack;
     316     stack.top = -1;
     317     if(!root)
     318     {
     319         printf("the tree is empty!
    ");
     320     }else {
     321         while(root || stack.top != -1)  //树根节点不空,或者栈不空时
     322         {
     323             if(root){
     324                 push_stack(&stack, root);   //根结点进栈,遍历左子树
     325                 root = root->LChild;        //每次遇到非空的左子树,就往左走
     326             }else{
     327                 root = pop_stack(&stack);   //根指针退栈,访问根节点,遍历右子树
     328                 printf("%c ", root->data);
     329                 root = root->RChild;
     330             }
     331 
     332             /*
     333              while(root)                     //另外一种好的写法,只要有左子树,就往左走
     334              {
     335                  push_stack(&stack, root);   //根结点进栈,遍历左子树
     336                  root = root->LChild;        //每次遇到非空的左子树,就往左走
     337              }
     338              root = pop_stack(&stack);       //根指针退栈,访问根节点,遍历右子树
     339              printf("%c ", root->data);
     340              root = root->RChild;
     341              * */
     342         }
     343     }
     344 }
     345 
     346 /*
     347  * 后序遍历是先访问左右子树,最后访问根结点。
     348  * 当用栈来存储结点时,必须分清返回根结点时,是从左结点返回的,还是从右结点返回的
     349  * 用辅助指针可以写(也可以在结点中增加一个标志域)
     350  * 1.从根结点一直向左走,直到没有左子树
     351  * 2.转向向右走,先取栈顶指针
     352  * 3.判断是否有右子树
     353  *    4.若存在右子树且右子树是否被访问过,转向右子树,将右子树根结点压栈,继续走到最左边
     354  *    5.不满足4,弹出当前根结点,进行访问,并做标记,将root置空,必须将root置空,跳过向左走,直接向右走
     355  *
     356  * Note:当访问一个结点 *tmp (就是当前root)时,栈中的结点恰好是*tmp结点的所有祖先。
     357  *      从栈底到栈顶结点再加上*tmp结点,刚好构成从根结点到*tmp的一条路径
     358  *      在很多算法设计中都用到了这一特行,比如:
     359  *                *求根结点到某结点的路径
     360  *                *求两个结点的最近公共祖先
     361  * */
     362 
     363 void non_recursion_postorder(BinaryTree *root)
     364 {
     365     Tstack stack;
     366     stack.top = -1;
     367     BinaryTree *vis = NULL;
     368 
     369     if(!root)
     370         printf("the tree is empty!
    ");
     371 
     372     while(root || stack.top != -1)
     373     {
     374         if(root)                                    //走到最左边
     375         {
     376             push_stack(&stack, root);
     377             root = root->LChild;
     378         }else{                                      //向右走
     379             root = stack.stroe[stack.top];           //取栈顶元素    王道 P.128
     380             if(root->RChild && root->RChild != vis)   //如果右子树存在,且未被访问过
     381             {
     382                 root = root->RChild;                  //转向右子树
     383                 push_stack(&stack, root);            //压栈
     384                 root = root->LChild;                  //继续走到最左边
     385             }else{                                  //如果右子树不存在,或者已经访问过
     386                 root = pop_stack(&stack);            //弹出当前的根结点
     387                 printf("%c ", root->data);           //进行访问
     388                 vis = root;                          //标记访问过
     389                 root = NULL;                         //访问过后,重置root指针,必须将root置空,跳过向左走,直接向右走
     390             }
     391         }
     392     }
     393 }
     394 
     395 //后序遍历的标记数据域标记写法,这个不推荐
     396 void non_recursion_postorder2(BinaryTree *root)
     397 {
     398     Tstack stack;
     399     stack.top = -1;
     400     if(!root)
     401         printf("the tree is empty!
    ");
     402     else{
     403         while(root || stack.top != -1) {
     404             while (root) {
     405                 push_stack(&stack, root);
     406                 stack.tag[stack.top] = 0;       //设置访问标记,0为第一次访问,1为第二次访问
     407                 root = root->LChild;
     408             }
     409             if (stack.tag[stack.top] == 0)       //第一次访问时,转向同层右结点
     410             {
     411                 root = stack.stroe[stack.top];  //左走到底时,tree是空,必须有这句话
     412                 stack.tag[stack.top] = 1;
     413                 root = root->RChild;
     414             } else {
     415                 while (stack.tag[stack.top] == 1)//在栈中找到下一个第一次范格纹你的结点,退出循环时并没有pop,所以为其左子结点
     416                 {
     417                     root = pop_stack(&stack);
     418                     printf("%c ", root->data);
     419                 }
     420                 root = NULL;
     421             }
     422         }
     423     }
     424 }
     425 
     426 /*
     427  * 层次遍历,其实就是BFS  (广度优先搜索)
     428  * */
     429 void levelorder(BinaryTree *root)
     430 {
     431     Tqueue queue;
     432     queue.front = queue.rear = 0;
     433 
     434     if(!root)
     435         printf("the tree is empty!
    ");
     436 
     437     enqueue(&queue, root);              //根结点入队
     438 
     439     while(queue.front != queue.rear)
     440     {  //队列不为空时,循环
     441         root = dequeue(&queue);         //队头元素出队
     442         printf("%c ", root->data);      //访问当前结点
     443 
     444         if (root->LChild != NULL)
     445             enqueue(&queue, root->LChild);
     446 
     447         if (root->RChild != NULL)
     448             enqueue(&queue, root->RChild);
     449     }
     450 }
     451 /*
     452  * 层次遍历的应用,将树自下而上,自右向左遍历,
     453  * 就是把层次遍历访问的结点入栈,然后从栈弹出的顺序
     454  * 王道 P.128
     455  * */
     456 void invert_levelorder(BinaryTree *root)
     457 {
     458     Tqueue queue;
     459     Tstack stack;
     460 
     461     if(!root)
     462         printf("the tree is empty!
    ");
     463 
     464     stack.top = -1;
     465     queue.front = queue.rear = 0;
     466     enqueue(&queue, root);              //根结点入队
     467 
     468     while(queue.front != queue.rear)
     469     {
     470         root = dequeue(&queue);
     471         push_stack(&stack, root);      //当前结点 入栈
     472 
     473         if (root->LChild != NULL)
     474             enqueue(&queue, root->LChild);
     475 
     476         if (root->RChild != NULL)
     477             enqueue(&queue, root->RChild);
     478     }
     479 
     480     while(stack.top != -1)
     481     {
     482         root = pop_stack(&stack);
     483         printf("%c ", root->data);
     484     }
     485 }
     486 /*
     487  * 王道 第五题 P.129 通过层次遍历获得树的深度
     488  * */
     489 int tree_depth(BinaryTree *root)
     490 {
     491     Tqueue queue;
     492 
     493     if(!root)
     494         return 0;
     495 
     496     queue.front = queue.rear = 0;
     497     int last = 1, level = 0;        //last指向下一层的第一个结点
     498     enqueue(&queue, root);          //根结点入队
     499 
     500     while(queue.front != queue.rear)
     501     {
     502         root = dequeue(&queue);
     503 
     504         if(root->LChild)
     505             enqueue(&queue, root->LChild);
     506         if(root->RChild)
     507             enqueue(&queue, root->RChild);
     508 
     509         //好好理解这里
     510         if(queue.front == last)     //处理该层的最右结点
     511         {
     512             level++;                //层数加一
     513             last = queue.rear;      //last指向下层
     514         }
     515     }
     516     return level;
     517 }
     518 
     519 int max(int a, int b)
     520 {
     521     return (a > b) ? a : b;
     522 }
     523 /*
     524  * 统计树的深度,同后序遍历
     525  * 1.如果树空,深度为零
     526  * 2.否则分别递归求解左右子树的深度
     527  * 3.树的深度为 1+左右子树中更大的深度
     528  * */
     529 int tree_depth2(BinaryTree *root)
     530 {
     531     int d = 0, dl, dr;
     532     if(!root)
     533         d = 0;
     534     else
     535     {
     536         dl = tree_depth2(root->LChild);
     537         dr = tree_depth2(root->RChild);
     538         d = 1 + max(dl, dr);
     539     }
     540     return d;
     541 }
     542 
     543 /*
     544  *求二叉树中值为x的结点所在的层数
     545  * */
     546 void search_x_level(BinaryTree *root, Telemtype x)
     547 {
     548     static int level = 1;
     549     if(root)
     550     {
     551         if(root->data == x)
     552             printf("the x level is %d
    ", level) ;
     553         level++;
     554         search_x_level(root->LChild, x);
     555         search_x_level(root->RChild, x);
     556         level--;
     557     }
     558 }
     559 
     560 /*
     561  * 下面这种写法,牛逼666,学这个
     562  * NOTE: 关键的地方还是区间划分
     563  * s1 : start1, e1 : end1
     564  * s2 : start2, e2 : end2
     565  * */
     566 BinaryTree *pre_in_create_tree2(Telemtype A[], Telemtype B[], int s1, int e1, int s2, int e2)
     567 {
     568     if(s1 > e1 || s2 > e2)
     569         return NULL;
     570     BinaryTree *root;
     571     root = (BinaryTree*)malloc(sizeof(BinaryTree));
     572     root->data = A[s1];                                         //根结点
     573     for(int i = s2; i <=e2; i++)                       //根结点在中序中的划分
     574     {
     575         if(A[s1] == B[i]) {
     576             root->LChild = pre_in_create_tree2(A, B, s1 + 1, s1 + i - s2, s2, i - 1);
     577             root->RChild = pre_in_create_tree2(A, B, i - s2 + s1 + 1, e1, i + 1, e2);
     578         }
     579     }
     580     return root;
     581 }
     582 
     583 /*
     584  * 由先序和中序遍历,来唯一确定一棵二叉树
     585  * 1.根据先序序列确定树的根结点
     586  * 2.根据根结点在中序遍历中划分左右子树,然后根据左右子树结点在先序序列中的次序,可以确定子树的根结点,(即回到第一步)
     587  * 王道书上 P.130 第六题
     588  * */
     589 BinaryTree *pre_in_create_tree(Telemtype A[], Telemtype B[], int startPre, int endPre, int startIn, int endIn)
     590 {
     591     int i;
     592     BinaryTree *root;
     593     root = (BinaryTree*)malloc(sizeof(BinaryTree));
     594     root->data = A[startPre];
     595     for(i = startIn; B[i]!=root->data; ++i);
     596     int LChild_len = i - startIn;                                    //左子树的长度
     597     int RChild_len = endIn - i;                                      //右子树的长度
     598 
     599     if(LChild_len)                                                  //递归建立左子树
     600         root->LChild = pre_in_create_tree(A, B, startPre+1, startPre+LChild_len, startIn, startIn+LChild_len-1);   //划分的区间,是值得注意的地方
     601     else
     602         root->LChild = NULL;
     603 
     604     if(RChild_len)                                                  //递归建立右子树
     605         root->RChild = pre_in_create_tree(A, B, endPre-RChild_len+1, endPre, endIn-RChild_len+1, endIn);
     606     else
     607         root->RChild = NULL;
     608 
     609     return root;
     610 }
     611 /*
     612  * 层次遍历的应用
     613  * 1.将所有结点加入队列(包括空结点)。
     614  * 2.当遇到空结点时,判断其后是否存在非空结点,如果存在,则不是完全二叉树
     615  * 王道 P.131 第七题
     616  * */
     617 int is_complete(BinaryTree *root)
     618 {
     619     Tqueue queue;
     620 
     621     if(!root)
     622         return 1;                           //空树为满二叉树
     623 
     624     queue.front = queue.rear = 0;
     625     enqueue(&queue, root);
     626 
     627     while(queue.front != queue.rear)
     628     {
     629         if(!root)                           //结点非空,将其左右子树入队
     630         {
     631             enqueue(&queue, root->LChild);
     632             enqueue(&queue, root->RChild);
     633         } else {                            //结点非空,检查其后是否有非空结点
     634             while(queue.front != queue.rear)
     635             {
     636                 root = dequeue(&queue);
     637                 if(root)                    //结点非空,为非完全二叉树
     638                     return 0;
     639             }
     640         }
     641     }
     642     return 1;
     643 }
     644 /*
     645  * 统计双分支结点的个数
     646  * 递归思路
     647  * f(root) = 0;                                      若root == NULL
     648  * f(root) = f(root->LChild) + f(root->RChild) + 1;  当前root结点为双分支结点
     649  * f(root) = f(root->LChild) + f(root->RChild);      其他情况(当前root为单分支结点,或者root为叶子结点)
     650  * 王道P.131 第八题
     651  * */
     652 int double_son_node(BinaryTree *tree)
     653 {
     654     if(tree == NULL)
     655         return 0;
     656     if(tree->LChild != NULL && tree->RChild != NULL)
     657     {
     658         return  double_son_node(tree->LChild) + double_son_node(tree->RChild) + 1;
     659     }else
     660     {
     661         return double_son_node(tree->LChild) + double_son_node(tree->RChild);
     662     }
     663 }
     664 
     665 /*
     666  * 交互二叉树的左右子树(后序遍历的应用)
     667  * 1.首先交换root的左孩子的左右子树,
     668  * 2.然后交换root的右孩子的左右子树
     669  * 3.最后交换root的左右孩子,当结点为空时递归结束
     670  * 王道  P.131  第九题
     671  * */
     672 void swap_lrchild(BinaryTree *tree)
     673 {
     674     BinaryTree *tmp;
     675     if(tree)
     676     {
     677         swap_lrchild(tree->LChild);
     678         swap_lrchild(tree->RChild);
     679         tmp = tree->LChild;
     680         tree->LChild = tree->RChild;
     681         tree->RChild = tmp;
     682     }
     683 }
     684 /*
     685  * 借用队列实现左右子树交换
     686  * */
     687 void swap_lrchild2(BinaryTree *root)
     688 {
     689     BinaryTree *p, *tmp;
     690     Tqueue queue;
     691     queue.front = queue.rear = 0;
     692     if(root)
     693         enqueue(&queue, root);
     694     while(queue.rear != queue.front)
     695     {
     696         p = dequeue(&queue);
     697         if(p->LChild)
     698             enqueue(&queue, p->LChild);
     699         if(p->RChild)
     700             enqueue(&queue, p->RChild);
     701 
     702         tmp = p->LChild;
     703         p->LChild = p->RChild;
     704         p->RChild = tmp;
     705     }
     706 
     707 }
     708 /*
     709  * 求先序遍历中的第k个结点的值(确保k值在有效范围内)
     710  * 1.设置一个全局变量itag记录访问过的结点的序号,其初值是根结点在先序序列中的序号,即为1
     711  * 2.当二叉树tree为空时,返回特殊结点“#”,当itag == k时,表示找到了满足条件的结点,返回 tree->data
     712  * 3.当itag != k 是,则递归的在左右子树中继续查找
     713  * 王道   P.131    第十题
     714  * */
     715 int itag = 1;
     716 Telemtype search_k_node(BinaryTree *tree, int k)
     717 {
     718     if(tree == NULL)
     719         return '#';
     720     if(itag == k)
     721         return tree->data;
     722     itag++;
     723     Telemtype ch = search_k_node(tree->LChild, k);
     724     if(tree->LChild != NULL)
     725         return ch;
     726     ch = search_k_node(tree->RChild, k);
     727     if(tree->RChild != NULL)                        //确保一定有返回值
     728         return ch;
     729     else
     730         return '#';
     731 }
     732 /*
     733  * 层次遍历的基本思想,就是找到 X 结点,然后删除它这棵树
     734  * 1.如果当前树根为X结点,直接删掉
     735  * 2.否则,进行层次遍历,去找 X,找到了就删掉,
     736  * Note:应为之前封装的好,明显要比书上的代码形式统一,也好看的多
     737  * 王道 P.132 第十一题
     738  * */
     739 void destroy_x_tree(BinaryTree *tree, Telemtype x)
     740 {
     741     if(tree)
     742     {
     743         if(tree->data == x)
     744         {
     745             destory_tree(tree);
     746             return;
     747         }
     748         Tqueue queue;
     749         queue.front = queue.rear = 0;
     750         enqueue(&queue, tree);
     751         while(queue.front != queue.rear)
     752         {
     753             tree = dequeue(&queue);
     754             if(tree->LChild)
     755             {
     756                 if(tree->LChild->data == x)
     757                 {
     758                     destory_tree(tree->LChild);
     759                     tree->LChild = NULL;
     760                 } else {
     761                     enqueue(&queue, tree->LChild);
     762                 }
     763             }
     764             if(tree->RChild)
     765             {
     766                 if(tree->RChild->data == x)
     767                 {
     768                     destory_tree(tree->RChild);
     769                     tree->RChild = NULL;
     770                 }else{
     771                     enqueue(&queue, tree->RChild);
     772                 }
     773             }
     774         }
     775     }
     776     return;
     777 }
     778 
     779 /*
     780  * 打印X结点的所有祖先,用到了非递归后序遍历的栈中信息
     781  * 1.非递归后序遍历找到X
     782  * 2.此时栈中的所有元素均为该结点的祖先结点
     783  * Note:树上的代码是后序遍历的不同写法,感觉没必要记那种(应该看一下深入理解后序遍历),
     784  * 会一种就够了了,所以我的代码,就是把上边的后序遍历中的输出语句该为了判断是否是当前结点。
     785  * 王道 P.133 第十二题
     786  * */
     787 
     788 void print_ancestor_node(BinaryTree *tree, Telemtype x)
     789 {
     790     Tstack stack;
     791     stack.top = -1;
     792     if(!tree)
     793         printf("the tree is empty!
    ");
     794     else{
     795         while(tree || stack.top != -1) {
     796             while (tree) {
     797                 push_stack(&stack, tree);
     798                 stack.tag[stack.top] = 0;       //设置访问标记,0为第一次访问,1为第二次访问
     799                 tree = tree->LChild;
     800             }
     801             if (stack.tag[stack.top] == 0)       //第一次访问时,转向同层右结点
     802             {
     803                 tree = stack.stroe[stack.top];  //左走到底时,tree是空,必须有这句话
     804                 stack.tag[stack.top] = 1;
     805                 tree = tree->RChild;
     806             } else {
     807                 while (stack.tag[stack.top] == 1)//在栈中找到下一个第一次范格纹你的结点,退出循环时并没有pop,所以为其左子结点
     808                 {
     809                     tree = pop_stack(&stack);
     810                     //每次根改动都是下边
     811                     if(tree->data == x)
     812                     {
     813 
     814                         printf("
    %c ancestor is : 
    ",tree->data);;
     815                         for(int i = 0; i <= stack.top; ++i)
     816                         {
     817                             printf("%c ", stack.stroe[i]->data);
     818                         }
     819                         return;
     820                     }
     821                     //*********************
     822                 }
     823                 tree = NULL;
     824             }
     825         }
     826     }
     827 }
     828 /*
     829  * 求 p q两个结点的最近公共祖先,非递归后序遍历的应用,就是利用栈信息
     830  * 假设p 在 q的左边
     831  * 1.后序遍历必然先遍历到 p,这时把栈中的信息借用辅助栈保存起来
     832  * 2.继续遍历,遍历到 q 结点的时候,将栈中的结点逐个和辅助栈的结点匹配,
     833  *      第一个相等的元素就是p & q的最近公共祖先
     834  * 王道 P.134 第13题
     835  * */
     836 BinaryTree *nearest_comm_ancestor(BinaryTree *tree, Telemtype p, Telemtype q)
     837 {
     838     Tstack stack;
     839     Tstack ass_stack;
     840     stack.top = -1;
     841     ass_stack.top = -1;
     842     while(tree || stack.top != -1)
     843     {
     844         while(tree)
     845         {
     846             push_stack(&stack, tree);
     847             stack.tag[stack.top] = 0;
     848             tree = tree->LChild;
     849         }
     850         if(stack.tag[stack.top] == 0)
     851         {
     852             tree = stack.stroe[stack.top];
     853             stack.tag[stack.top] = 1;
     854             tree = tree->RChild;
     855         } else {
     856             while(stack.tag[stack.top] == 1)
     857             {
     858                 tree = pop_stack(&stack);
     859                 //每次根改动都是下边
     860                 if(tree->data == p)
     861                 {
     862                     for(int i = 0; i <= stack.top; ++i)
     863                     {
     864                         ass_stack.stroe[i] = stack.stroe[i];
     865                         ass_stack.top = stack.top;
     866                     }
     867                 }
     868                 if(tree->data == q)
     869                 {
     870                     for(int i = stack.top; i >= 0; --i)
     871                     {
     872                         for(int j = ass_stack.top; j >= 0; --j)
     873                         {
     874                             if(stack.stroe[i]->data == ass_stack.stroe[j]->data)
     875                             {
     876                                 return stack.stroe[i];
     877                             }
     878                         }
     879                     }
     880                 }
     881                 //*********************
     882             }
     883             tree = NULL;
     884         }
     885     }
     886     return NULL;
     887 }
     888 
     889 /*
     890  * 求树的宽度,二叉树的宽度即 某一层拥有最多的结点树(层次遍历的应用)
     891  * 将所有节点对应的层次放在一个队列里,然后通过扫描队列求出各层的总结点的个数,最大的层结点即为二叉树的宽度
     892  * 王道  P.135  第十四题
     893  * */
     894 
     895 int tree_width(BinaryTree *root)
     896 {
     897     Tqueue queue;
     898     int k, max, i, n;
     899 
     900     if(!root)
     901         return 0;
     902 
     903     queue.front = queue.rear = 0;
     904     enqueue(&queue, root);
     905     queue.level[queue.rear] = 1;
     906 
     907     while(queue.front != queue.rear)
     908     {
     909         root = dequeue(&queue);
     910         k = queue.level[queue.front];
     911         if(root->LChild)
     912         {
     913             enqueue(&queue, root->LChild);
     914             queue.level[queue.rear] = k + 1;
     915         }
     916         if(root->RChild)
     917         {
     918             enqueue(&queue, root->RChild);
     919             queue.level[queue.rear] = k + 1;
     920         }
     921     }
     922 
     923     max = 0; i = 0;                                            ///max保存同一层最多的结点个数
     924     k = 1;                                                     ///k表示从第一层开始查找
     925     while(i <= queue.rear)                                     ///i扫描队中所有的元素
     926     {
     927         n = 0;                                                  ///n统计第k层的结点个数
     928         while(i <= queue.rear && queue.level[i] == k)
     929         {
     930             n++;
     931             i++;
     932         }
     933         k = queue.level[i];
     934         if(n > max)
     935             max = n;
     936     }
     937     return  max;
     938 }
     939 
     940 /*
     941  * 15、设有一棵满二叉树(所有结点的值均不相同),已知先序序列,求其后序序列
     942  *王道P1
     943  * */
     944 
     945 void pre_to_post(Telemtype pre[], int s1, int e1, Telemtype post[], int s2, int e2)
     946 {
     947     int half;
     948     if(e1 >= s1)
     949     {
     950         post[e2] = pre[s1];
     951         half = (e1 - s1) / 2;
     952         pre_to_post(pre, s1+1, s1+half, post, s2, s2+half-1);
     953         pre_to_post(pre, s1+half+1, e1, post, s1+half, e2-1);
     954     }
     955 }
     956 
     957 /*
     958  *16、将二叉树的叶节点按从左到右的顺序连城一个单链表,表头指针为head。
     959  * 二叉树按二叉链表的方式存储,链接时用叶结点的右指针域来存放指针单链表
     960  * */
     961 
     962 BinaryTree *head, *pre = NULL;
     963 BinaryTree *inorder_List(BinaryTree *root)
     964 {
     965     if(root)
     966     {
     967         inorder_List(root->LChild);
     968         if (!root->LChild && !root->RChild) {
     969             if (!pre) {
     970                 head = root;
     971                 pre = root;
     972             } else {
     973                 pre->RChild = root;
     974                 pre = root;
     975             }
     976             inorder_List(root->RChild);
     977             pre->RChild = NULL;
     978         }
     979     }
     980     return head;
     981 }
     982 /*
     983  * 利用结点的右孩子rchild将一颗二叉树的叶子结点按照从左往右的顺序串成一个单链表
     984  * */
     985 void link(BinaryTree *root, BinaryTree *head, BinaryTree *tail)
     986 {
     987     if(root)
     988     {
     989         if(!root->LChild && !root->RChild)
     990         {
     991             if(!head)
     992             {
     993                 head = root;
     994                 tail = root;
     995             }else
     996             {
     997                 tail->RChild = root;
     998                 tail = root;
     999             }
    1000         }
    1001         link(root->LChild, head, tail);
    1002         link(root->RChild, head, tail);
    1003     }
    1004 }
    1005 
    1006 
    1007 /*
    1008  *17、判断两颗二叉树是否相似
    1009  * 相似:T1,T2都是空二叉树或都只有一个根结点,或T1的左子树和T2的左子树相似,T1的右子树和T2的右子树相似
    1010  * */
    1011 int is_similar(BinaryTree *T1, BinaryTree *T2)
    1012 {
    1013     int lvalue, rvalue;
    1014     if(!T1 && !T2)
    1015         return 1;
    1016     else if(!T1 || !T2)
    1017         return 0;
    1018     else
    1019     {
    1020         lvalue = is_similar(T1->LChild, T2->LChild);
    1021         rvalue = is_similar(T1->RChild, T2->RChild);
    1022         return (lvalue&&rvalue);
    1023     }
    1024 }
    1025 
    1026 /*
    1027  *18、写出中序线索二叉树里查找指定结点后序的前驱结点的算法
    1028  * */
    1029 
    1030 /*
    1031  *19、求二叉树的带却路径长度(WPL)。
    1032  * WPL指二叉树中所有叶结点的带权路径长度之和。
    1033  * */
    1034 int wpl_preorder(BinaryTree *root, int deep)
    1035 {
    1036     static int wpl = 0;
    1037     if(!root->LChild && !root->RChild)
    1038         wpl += deep*(root->data - '0');     ///此时data中存放的是权值,但我们data是char型。
    1039     if(root->LChild)
    1040         wpl_preorder(root->LChild, deep+1);
    1041     if(root->RChild)
    1042         wpl_preorder(root->RChild, deep+1);
    1043     return wpl;
    1044 }
    1045 
    1046 int WPL(BinaryTree *root)
    1047 {
    1048     return wpl_preorder(root, 0);
    1049 }
    1050 
    1051 /*
    1052 int main()
    1053 {
    1054     BinaryTree *tree;
    1055     tree = create_tree(tree);
    1056     printf("preorder
    ");
    1057     //preorder_traverse(tree);
    1058     non_recursion_preorder(tree);
    1059     printf("
    inorder
    ");
    1060     //inorder_traverse(tree);
    1061     non_recursion_inorder(tree);
    1062     printf("
    postorder
    ");
    1063     //postorder_traverse(tree);
    1064     non_recursion_postorder(tree);
    1065     printf("
    levelorder
    ");
    1066     levelorder(tree);
    1067     printf("
    invert_levelorder
    ");
    1068     invert_levelorder(tree);
    1069     printf("
    left_node`s number is %d
    ", sum_leaf(tree));
    1070     printf("
    depth is %d
    ", tree_depth2(tree));
    1071     printf("
    depth is %d
    ", tree_depth(tree));
    1072     //Telemtype A[] = {'A','B','C','D','E','F','G','H','K'};
    1073     //Telemtype B[] = {'B','D','C','A','E','H','G','K','F'};
    1074     Telemtype A[] = {' ', '1', '2', '4', '7', '3', '5', '6', '8'};
    1075     Telemtype B[] = {' ', '4', '7', '2', '1', '5', '3', '8', '6'};
    1076     BinaryTree *root, *root2;
    1077     root = pre_in_create_tree(A, B, 1, 8, 1, 8);
    1078     puts("
    *********************root traverse
    ");
    1079     preorder_traverse(root);
    1080     root2 = pre_in_create_tree2(A, B, 1, 8, 1, 8);
    1081     puts("
    *********************root2 traverse
    ");
    1082     preorder_traverse(root2);
    1083     printf("is complete %d
    ", is_complete(root));
    1084     printf("double son node is %d
    ", double_son_node(root));
    1085     printf("
    the swap_lrChild2
    ");
    1086     swap_lrchild2(tree);
    1087     preorder_traverse(tree);
    1088     puts("the end swap_LRChile
    ");
    1089     preorder_traverse(root2);
    1090     printf("
    %c
    ", search_k_node(root2, 4));
    1091     destroy_x_tree(root2, '2');
    1092     preorder_traverse(root2);
    1093     puts("
    print_ancestor_node");
    1094     print_ancestor_node(root, '5');
    1095     root2 = nearest_comm_ancestor(root, '5', '6');
    1096     printf("
    the nearest_comm_ancestor is %c ", root2->data);
    1097     printf("
    
    end!!
    
    ");
    1098 
    1099 
    1100 
    1101     ///copy_tree   Test
    1102     BinaryTree *copy_tree_root = copy_tree(tree);
    1103     preorder_traverse(copy_tree_root);
    1104     preorder_traverse(tree);
    1105     ///tree_width  Test
    1106     int width = tree_width(tree);
    1107     printf("
    the tree`s width is %d
    ", width);
    1108 
    1109     ///search_x_level Test
    1110     search_x_level(tree, '3');
    1111     search_x_level(tree, '2');
    1112     search_x_level(tree, '1');
    1113     search_x_level(tree, '4');
    1114 
    1115     ///sum_node
    1116     int s_node = sum_node(tree);
    1117     printf("%d
    ", s_node);
    1118 
    1119     return 0;
    1120 }
    1121 */
    1122 ///test case :12003400500
    Set.26 Update
  • 相关阅读:
    cliconfg
    SQL 校验身份证格式
    常用MIME类型汇总
    SqlBulkCopy批量将Excel(Aspose)数据导入至SQL Server
    C#生成图片验证码
    SqlServer PIVOT函数快速实现行转列,UNPIVOT实现列转行
    SQL Server 中 EXEC 与 SP_EXECUTESQL 的区别
    C#常用加密方式
    CURSOR 游标使用示例
    linux命令
  • 原文地址:https://www.cnblogs.com/ya-cpp/p/5819534.html
Copyright © 2020-2023  润新知