二叉树的操作
2015-12-21 22:00
387 查看
二叉树是最多有两个孩子节点的类型的树
二叉树的思想延伸有很多,最经典的就是二分查找了,还有就是用决策树来判断比较排序的最优时间复杂度。等等。我就把不一一列举了(囧~当然也列举不完)。
今天用了将近半天的时间把二叉树的很多操作都实现了一下。有些非递归的真的是不好做,也不是很好想,开始做前序非递归我绞尽脑汁~~想了很久也没有想出来,后来大多都是听老师或者百度后才知道原来是这么写的。其实非递归写的真的不多,毕竟c语言短小精悍!但是要真正掌握c的要义以后还是要多多加强练习,希望以后自己可以能够自己想出来做出来。
由于代码比较多,(其实我觉得多,毕竟太多大家也找不到重要的)本文全部写递归思想
下一篇会补上其他的非递归。
闲言少叙,开始正式的代码之旅:
1.建树:这个是方法老师给我们讲的,和之前网上看到的略有不同之处
3.递归遍历
4.递归求高度
5.递归求节点个数
6.递归求叶子节点个数
7.树的镜像。就是把树变成对称的
比如 a a
/ \ -------> / \
c b b c
8.某一层有多少节点
9.找两个节点最近的相同祖先
10.一个树是否包含另一个树
11.树的最长路径
12根据中序和前序遍历的字符串得到树
//根据前序和中序确定一个树
Tree create_tree_by_pre_mid(char *pre_str,char *mid_str,int length)
{
int index = -1;
Tree root = NULL;
if(mid_str == NULL || pre_str == NULL || length <= 0){
return NULL;
}
root = create_node();
root->ele = pre_str[0];
index = get_index(mid_str,pre_str[0]);
root->left = create_tree_by_pre_mid(pre_str+1,mid_str,index);
root->right = create_tree_by_pre_mid(pre_str+index+1,
mid_str+index+1,length-index-1);
return root;
}
13.根据中序和后序得到树
Tree create_tree_by_last_mid(char *last_str,char *mid_str,int length)
{
Tree root = NULL;
int index = -1;
if(last_str == NULL || mid_str == NULL || length <= 0){
return NULL;
}
root = create_node();
//找到根节点在中序字符串中的位置。并赋值给新子树的根节点
index = get_index(mid_str,last_str[length-1]);
root->ele = last_str[length-1];
//递归对右子树左子树进行相同操作
root->left = create_tree_by_last_mid(last_str,mid_str,index);
root->right = create_tree_by_last_mid(last_str+index,mid_str+index+1,
length-index-1);
return root;
}
二叉树的思想延伸有很多,最经典的就是二分查找了,还有就是用决策树来判断比较排序的最优时间复杂度。等等。我就把不一一列举了(囧~当然也列举不完)。
今天用了将近半天的时间把二叉树的很多操作都实现了一下。有些非递归的真的是不好做,也不是很好想,开始做前序非递归我绞尽脑汁~~想了很久也没有想出来,后来大多都是听老师或者百度后才知道原来是这么写的。其实非递归写的真的不多,毕竟c语言短小精悍!但是要真正掌握c的要义以后还是要多多加强练习,希望以后自己可以能够自己想出来做出来。
由于代码比较多,(其实我觉得多,毕竟太多大家也找不到重要的)本文全部写递归思想
下一篇会补上其他的非递归。
闲言少叙,开始正式的代码之旅:
1.建树:这个是方法老师给我们讲的,和之前网上看到的略有不同之处
二叉树是一棵最多只有两个孩子节点类型的树。 很多算法都是可以用二叉树来描述,最经典的莫非二分查找算法了。二叉树还可以用作决策树 //创建节点 static Tree_node *create_node(void) { Tree_node *node = (Tree_node *)Malloc(sizeof(Tree_node)); bzero(node,sizeof(Tree_node));//是库函数strings.h(是的你没有看错,后面有s)的函数。作用是把n个数据块清0 return node; } //注意使用二级指针,因为如果传*str这个字符串,递归回退的时候参数str指向 //没有变化。只有使用二级指针,使得指向发生变化,才能让它向后移动。 Tree create_tree(const char **str) { //根据字符串创建一个二叉树 //a#bc##d## // a // \ // b // / \ // c d //先让根为NULL,如果不是'#'那么在创建节点并且赋值 Tree root = NULL; if(**str != '#' && str != NULL && *str != NULL){ root = create_node(); root->ele = **str; //指针指向字符串的下一个位置,然后创建左子树 ++*str; root->left = create_tree(str); //如果为'#'就转到这里,创建右子树。 ++*str; root->right = create_tree(str); } return root; }2.销毁
void destroy_tree(Tree *root) { if(*root){ destroy_tree(&(*root)->left); destroy_tree(&(*root)->right); free(*root); *root = NULL; } }
3.递归遍历
//遍历 void pre_order_print(Tree root)//先序 { if(root == NULL){ return ; } if(root){ printf("%c ",root->ele); pre_order_print(root->left); pre_order_print(root->right); } } void mid_order_print(Tree root)//中序 { if(root){ mid_order_print(root->left); printf("%c ",root->ele); mid_order_print(root->right); } else{ return ; } } void last_order_print(Tree root)//后序 { if(root){ last_order_print(root->left); last_order_print(root->right); printf("%c ",root->ele); } else return ; }
4.递归求高度
int Tree_height(Tree root)//树的高度 { if(root == NULL){ return -1; } return MAX(Tree_height(root->left), Tree_height(root->right))+1; }
5.递归求节点个数
int Tree_node_count(Tree root)//节点数 { if(root == NULL){ return 0; } return Tree_node_count(root->left) + Tree_node_count(root->right) + 1; }
6.递归求叶子节点个数
int Tree_leaf_count(Tree root)//叶子节点数 { if(root == NULL){ return 0; } if(root->left == NULL && root->right == NULL){ return 1; } return Tree_leaf_count(root->left) + Tree_leaf_count(root->right); }
7.树的镜像。就是把树变成对称的
比如 a a
/ \ -------> / \
c b b c
void Tree_iso(Tree root) //树的镜像 { if(root == NULL){ return ; } //因为节点有可能指向的是NULL,所以交换节点首地址,所以就需要用 //指向节点首地址的指针。 if(root->left || root->right){ swap(&(root->left),&(root->right),sizeof(Tree_node *)); } if(root->left){ Tree_iso(root->left); } if(root->right){ Tree_iso(root->right); } }
8.某一层有多少节点
int level_count(Tree root,int level)//某层的节点数目 { if(root == NULL){ return 0; } if(level == 1){ return 1; } return level_count(root->right,level-1) + level_count(root->left,level-1); }
9.找两个节点最近的相同祖先
Tree_node *find_common_node(Tree root,Tree_node *node1,Tree_node *node2) { Tree_node *node1_ancestor; Tree_node *node = NULL; //如果root为空或节点就是root,那么返回空 if(node1 == root || node2 == root || root == NULL){ return NULL; } //找节点1的父节点 node1_ancestor = find_parent(root,node1); //如果节点1的父节点的下面路径中并不包含节点2.就继续找父节点的父节点。 //直到包含为止,返回这个节点就是公共节点 while(node == NULL){ node = find_node(node1_ancestor,node2->ele); if(node == NULL){ node1_ancestor = find_parent(root,node1_ancestor); } } if(node1_ancestor == node2){ node1_ancestor = find_parent(root,node2); } return node1_ancestor; }
10.一个树是否包含另一个树
//判断root1是否包含root2 Boolean is_tree_included(Tree root1,Tree root2) { //因为一个为空另一个不为空,那么它们的节点肯定不好判断 //所以root2只要先于root1截至就先让它返回真 //之后在通过root2中的每个节点是否与之对应来判断是否包含 if(root2 == NULL){ return TRUE; } if(root1 == NULL && root2 != NULL){ return FALSE; } if(root1->ele == root2->ele){ return TRUE; } return is_tree_included(root1->left,root2->left) && is_tree_included(root1->right,root2->right); }
11.树的最长路径
int largest_dis(Tree root) { int distance = 0; int way = 0; int tmp = 0; if(root == NULL){ return 0; } way = Tree_height(root->left) + Tree_height(root->right) + 2; tmp = MAX(way, largest_dis(root->left)); distance = MAX(tmp, largest_dis(root->right)); return distance; }
12根据中序和前序遍历的字符串得到树
//根据前序和中序确定一个树
Tree create_tree_by_pre_mid(char *pre_str,char *mid_str,int length)
{
int index = -1;
Tree root = NULL;
if(mid_str == NULL || pre_str == NULL || length <= 0){
return NULL;
}
root = create_node();
root->ele = pre_str[0];
index = get_index(mid_str,pre_str[0]);
root->left = create_tree_by_pre_mid(pre_str+1,mid_str,index);
root->right = create_tree_by_pre_mid(pre_str+index+1,
mid_str+index+1,length-index-1);
return root;
}
13.根据中序和后序得到树
Tree create_tree_by_last_mid(char *last_str,char *mid_str,int length)
{
Tree root = NULL;
int index = -1;
if(last_str == NULL || mid_str == NULL || length <= 0){
return NULL;
}
root = create_node();
//找到根节点在中序字符串中的位置。并赋值给新子树的根节点
index = get_index(mid_str,last_str[length-1]);
root->ele = last_str[length-1];
//递归对右子树左子树进行相同操作
root->left = create_tree_by_last_mid(last_str,mid_str,index);
root->right = create_tree_by_last_mid(last_str+index,mid_str+index+1,
length-index-1);
return root;
}
相关文章推荐
- 【郑轻】[1765]Lay a pancake!!!
- OPenGL中的缓冲区对象
- 建立数组的MaxTree + 栈 + HashMap + 二叉树的建立
- PHP 支持8种基本的数据类型
- MLlib回归算法(线性回归、决策树)实战演练--Spark学习(机器学习)
- Linux 中如何查询和卸载已安装的软件
- Android中killProcess()、System.exit(0)及finish()的区别
- Java线程:同步
- 流式大数据处理的三种框架:Storm,Spark和Samza
- 项目第五天
- P08 (**) 消除连续重复的列表元素
- P08 (**) 消除连续重复的列表元素
- 1. thinkphp (1)
- 启航
- 没有默认路由导致服务器无法SSH问题
- java注释
- 从头认识java-13.14 捕捉通配符替代的类型参数
- 发布阶段 github和360移动助手及总结
- JSP第二篇
- 兼容SQLSERVER、Oracle、MYSQL、SQLITE的超级DBHelper