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