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

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!\n");
    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!\n");
    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!\n");
    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!\n");
    }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!\n");
    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!\n");
    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("\n%c ancestor is : \n",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\n");
    //preorder_traverse(tree);
    non_recursion_preorder(tree);
    printf("\ninorder\n");
    //inorder_traverse(tree);
    non_recursion_inorder(tree);
    printf("\npostorder\n");
    //postorder_traverse(tree);
    non_recursion_postorder(tree);
    printf("\nlevelorder\n");
    levelorder(tree);
    printf("\ninvert_levelorder\n");
    invert_levelorder(tree);
    printf("\nleft_node`s number is %d\n", sum_left(tree));
    printf("\ndepth is %d\n", tree_depth2(tree));
    printf("\ndepth is %d\n", 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("\n*********************root traverse\n");
    preorder_traverse(root);
    root2 = pre_in_create_tree2(A, B, 1, 8, 1, 8);
    puts("\n*********************root2 traverse\n");
    preorder_traverse(root2);
    printf("is complete %d\n", is_complete(root));
    printf("double son node is %d\n", double_son_node(root));

    swap_lrchild(root2);
    preorder_traverse(root2);
    printf("\n%c\n", search_k_node(root2, 4));
    destroy_x_tree(root2, '2');
    preorder_traverse(root2);
    puts("\nprint_ancestor_node");
    print_ancestor_node(root, '5');
    printf("\n\nend!!\n\n");
    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!\n");
 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!\n");
 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!\n");
 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!\n");
 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!\n");
 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!\n");
 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!\n");
 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!\n");
 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\n", 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!\n");
 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("\n%c ancestor is : \n",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\n");
1057     //preorder_traverse(tree);
1058     non_recursion_preorder(tree);
1059     printf("\ninorder\n");
1060     //inorder_traverse(tree);
1061     non_recursion_inorder(tree);
1062     printf("\npostorder\n");
1063     //postorder_traverse(tree);
1064     non_recursion_postorder(tree);
1065     printf("\nlevelorder\n");
1066     levelorder(tree);
1067     printf("\ninvert_levelorder\n");
1068     invert_levelorder(tree);
1069     printf("\nleft_node`s number is %d\n", sum_leaf(tree));
1070     printf("\ndepth is %d\n", tree_depth2(tree));
1071     printf("\ndepth is %d\n", 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("\n*********************root traverse\n");
1079     preorder_traverse(root);
1080     root2 = pre_in_create_tree2(A, B, 1, 8, 1, 8);
1081     puts("\n*********************root2 traverse\n");
1082     preorder_traverse(root2);
1083     printf("is complete %d\n", is_complete(root));
1084     printf("double son node is %d\n", double_son_node(root));
1085     printf("\nthe swap_lrChild2\n");
1086     swap_lrchild2(tree);
1087     preorder_traverse(tree);
1088     puts("the end swap_LRChile\n");
1089     preorder_traverse(root2);
1090     printf("\n%c\n", search_k_node(root2, 4));
1091     destroy_x_tree(root2, '2');
1092     preorder_traverse(root2);
1093     puts("\nprint_ancestor_node");
1094     print_ancestor_node(root, '5');
1095     root2 = nearest_comm_ancestor(root, '5', '6');
1096     printf("\nthe nearest_comm_ancestor is %c ", root2->data);
1097     printf("\n\nend!!\n\n");
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("\nthe tree`s width is %d\n", 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\n", s_node);
1118 
1119     return 0;
1120 }
1121 */
1122 ///test case :12003400500
Set.26 Update

 

posted @ 2016-08-29 20:24  unicoe  阅读(787)  评论(0编辑  收藏  举报