简单的树的递归、非递归创建,前序中序后序遍历
扩展问题
问题1.给定前序遍历结果和中序遍历结果,重建二叉树
递归构造就可以了。
Tree* create_by_order(int* pre,int* in,int size){ if(size<=0||pre==NULL||in==NULL){ return NULL; } int i=0; Tree* rt = malloc(sizeof(Tree)); rt->value = pre[0];
//在中序中查找根节点位置 while(i<size){ if(pre[0]==in[i]){ break; }else{ i++; } } rt->left = create_by_order(pre+1,in,i); rt->right = create_by_order(pre+1+i,in+i+1,size-i-1); return rt; }
问题2.二叉树镜像
Tree* mirror(Tree* rt){ if(rt!=NULL){ //交换左右子树的指针 Tree* temp; temp = rt->right; rt->right = rt->left; rt->left = temp; rt->left = mirror(rt->left); rt->right = mirror(rt->right); } return rt; }
问题3.求二叉树节点最大距离
分三种情况
情况1.如第一个图所示,左深度加上右深度
情况2.如第二个图所示,左子树中节点的最大距离
情况3.将图二镜像一下,右子树中节点的最大距离
最后结果就是求这三个中较大的。
int depth(Tree* rt){ if(rt!=NULL){ int l_depth = depth(rt->left)+1; int r_depth = depth(rt->right)+1; return l_depth>r_depth ? l_depth:r_depth; } return 0; } int max(int a,int b,int c){ if(a>b&&a>c){ return a; } if(b>a&&b>c){ return b; } if(c>a&&c>a){ return c; }
return a; } int max_distance(Tree* rt){ if(rt!=NULL){ int l_distance = max_distance(rt->left); int r_distance = max_distance(rt->right); int l_depth = depth(rt->left)+1; int r_depth = depth(rt->right)+1; return max(l_distance,r_distance,l_depth+r_depth); } return 0; }
问题4.求两个节点的最近公共父节点(没有指向父节点指针,树为一般二叉树)
分三种情况
1.如果p1,p2节点分别在root->left,root->right,那么root为p1,p2的祖先
2.如果p1,p2都在root->left,那边将root=root->left 转换为子问题
3.如果p1,p2都在root->right, 那么将root=root->right 转换为字问题
/** *** 查找树中包含某个节点 **/ int contains(Tree* rt,const Tree* p){ if( rt==p ){ return 1; } if(rt==NULL){ return 0; } return contains(rt->left,p)||contains(rt->right,p); } /** *** 查找P1和P2的最近公共父节点 **/ Tree* get_same_parent(Tree* rt,const Tree* p1,const Tree* p2){ if(rt==NULL){ return NULL; } if(p1!=NULL&&p2!=NULL){ int left_contains_p1 = contains(rt->left,p1); int left_contains_p2 = contains(rt->left,p2); int right_contains_p1 = contains(rt->right,p1); int right_contains_p2 = contains(rt->right,p2); if( left_contains_p1 && left_contains_p2 ){ return get_same_parent(rt->left,p1,p2); } if( right_contains_p1 && right_contains_p2 ){ return get_same_parent(rt->right,p1,p2); } return rt; } }
扩展,如果树是搜索树时
1.p1,p2小于root,root=root->left
2.p1,p2大于root, root=root->right
3.p1,p2在root两边,root为p1,p2的最近公共父节点
STree* get_same_parent(STree* rt,STree* p1,STree* p2){ if(rt==NULL){ return NULL; } if( rt->value > p1->value && rt->value > p2->value ){ return get_same_parent(rt->left,p1,p2); } if( rt->value < p1->value && rt->value < p2->value ){ return get_same_parent(rt->right,p1,p2); } return rt; }
扩展,一般树
方法1.
用两个链表保存从根节点到p1,p2的路径。然后将问题转换为两个链表求交集问题。
方法2.
转自:http://www.cppblog.com/qingbizhu/archive/2012/04/05/170213.html
问题5.二叉查找树的删除
待删除节点是叶子节点,直接删除
待删除节点只有左子树或者只有右子树 ,将左(右)子树节点位置替换到待删除节点位置
待删除节点既有左子树又有右子树,遍历到待删除节点的最左下节点位置,也就是找到一个比待删除节点小,但是小得最少的,然后将这个节点替换到待删除节点位置
c语言写着还挺带感
#include<stdlib.h> #define null 0 struct tree{ struct tree* left; int value; struct tree* right; }; typedef struct tree Tree; Tree* root; Tree* insert_rcs(Tree* root, int value){ //只在叶节点位置插入 if(root == null){ root = malloc(sizeof(Tree)); root->value = value; root->left = null; root->right = null; //返回新增的叶节点 return root; } if(root->value > value){ root->left = insert_rcs(root->left, value); }else{ root->right = insert_rcs(root->right, value); } return root; } Tree* insert_no_rcs(Tree* root, int value){ Tree* newnode = malloc(sizeof(Tree)); newnode->value = value; newnode->left = null; newnode->right = null; if(root == null){ root = newnode; return root; } //p为工作指针 Tree* p = root; //p节点是插入节点,pre节点时插入节点的父节点 Tree* pre; while(p){ pre = p; if(p->value > value){ p = p->left; }else{ p = p->right; } } if(pre->value > newnode->value){ pre->left = newnode; }else{ pre->right = newnode; } return root; } //前序遍历 void pre_print_rcs(Tree* root){ if(root != null){ printf("value: %d \t",root->value); pre_print_rcs(root->left); pre_print_rcs(root->right); } } Tree* Stack[20]; int top = -1; //前序遍历 非递归 void pre_print_no_rcs(Tree* root){ //top != -1 这个条件一定要加上,这是处理单枝情况 while(root != null || top != -1){ if(root != null){ printf("%d \t",root->value); if(top+1 != 20){ Stack[++top] = root; root = root->left; } }else{ root = Stack[top--]->right; } } } //中序遍历 void in_print_rcs(Tree* root){ if(root != null){ in_print_rcs(root->left); printf("value: %d \t",root->value); in_print_rcs(root->right); } } //中序遍历 非递归 void in_print_no_rcs(Tree* root){ //top != -1 这个条件一定要加上,这是处理单枝情况 while(root != null || top != -1){ if(root != null){ if(top+1 != 20){ Stack[++top] = root; root = root->left; } }else{ root = Stack[top--]; printf("%d \t",root->value); root = root->right; } } } //后序遍历 void post_print_rcs(Tree* root){ if(root != null){ post_print_rcs(root->left); post_print_rcs(root->right); printf("value: %d \t",root->value); } } Tree* Q[20]; int front; int rear; //层序遍历 //输出队头元素,并将左右子树如队列 void level_print(Tree* root){ front = rear = 0; if(root != null){ Q[++rear] = root; while(rear != front){ Tree* p = Q[++front]; printf("%d \t",p->value); if(p->left != null){ Q[++rear] = p->left; } if(p->right != null){ Q[++rear] = p->right; } } } } Tree* create_no_rcs(int* list, int n){ int i; for(i=0; i<n; i++){ root = insert_no_rcs(root, list[i]); } return root; } Tree* create_rcs(int* list, int n){ int i; for(i=0; i<n; i++){ root = insert_rcs(root, list[i]); } return root; } int main(){ int list[10] = { 6,9,7,4,5,2,1,8,12,0 }; //root = create_no_rcs(list, 10); root = create_rcs(list, 10); //pre_print_rcs(root); //pre_print_no_rcs(root); in_print_rcs(root); in_print_no_rcs(root); //post_print_rcs(root); //level_print(root); return 0; }