数据结构之树的问题

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。


您还未登录!|登录|注册|帮助
首页
业界
移动
云计算
研发
论坛
博客
下载

更多








石锅拌饭

一介书生,读两三卷诗书,四体不勤,五谷不分,行六百里路途,乱七八糟到大学,久不思上进,十分颓废之人的胡言乱语





目录视图
摘要视图
订阅
.



2014年1月微软MVP申请开始啦! 2013年10月微软MVP当选名单揭晓! Tag功能介绍—我们为什么打Tag “说说家乡的互联网”主题有奖征文



二叉树问题汇总(2)—常见问题
.
分类: 面试题系列数据结构与算法二叉树2012-07-19 21:43553人阅读评论(0)收藏举报

pathstructnull存储



目录(?)[+]





















在上一篇二叉树问题汇总(1)中总结了下二叉树的一些基本问题,主要是针对二叉排序树。这篇文章主要汇总二叉树的一些常见的但是难度稍大一点的问题。

1、判定二叉树是否存在和为给定值的路径

问题:

给定一个值,判定二叉树是否存在从根结点到叶结点的路径,其结点的数据之和为该值。

比如二叉树如下所示,给定的和为27:


则二叉树存在的根结点到叶结点的路径有:

path 1: 5 4 11 7
path 2: 5 4 11 2
path 3: 5 8 13
path 4: 5 8 4 1


则该二叉树存在和为27的路径,因为5+4+11+7 = 27.若是给定和为40,则不存在这样的路径。

解答:

主要思路还是递归,通过用和值减去根结点的值,然后判断左右子树是否存在和为sum-root.data的路径。代码如下:




[cpp] view plaincopy
01.int hasPathSum(struct node* root, int sum)
02.{
03. if (root == NULL) return sum == 0; //基本条件:根结点为NULL,则判断此时剩下的和值是否为0,为0则表示存在,否则不存在
04. return hasPathSum(root->left, sum-root->data) || hasPathSum(root->right, sum-root->data); //递归判断左右子树
05.}



2、打印二叉树的所有路径(从根结点到叶结点)

问题:

如1中所示,打印二叉树的所有从根结点到叶结点的路径,如上例中打印输出4条路径。

解答:




[cpp] view plaincopy
01.//打印路径主函数
02.void printPaths(struct node* root)
03.{
04. int path[1000];
05. printPathsRecur(root, path, 0);
06.}
07.
08.//递归调用打印路径
09.void printPathsRecur(struct node* root, int path[], int pathLen)
10.{
11. if (root == NULL) return;
12.
13. path[pathLen++] = root->data; //将根结点加入到路径数组中,路径长度加1
14. if (root->left==NULL && root->right==NULL) //到了叶子节点,所以打印输出路径。
15. printArray(path, pathLen);
16. else {
17. printPathsRecur(root->left, path, pathLen); //递归打印左子


18. printPathsRecur(root->right, path, pathLen); //递归打印右子树
19. }
20.}
21.
22.//该函数打印输出路径。路径存储在数组path中,pathLen为路径结点个数。
23.void printArray(int path[], int pathLen)
24.{
25. int i;
26. for (i=0; i27. printf("%d ", path[i]);
28. }
29. printf("\n");
30.}



3、二叉树镜像

问题:

二叉树镜像问题即是将二叉树所有结点的左右孩子结点指针互换。如下图所示,左边的二叉树的镜像为右边所示。



解答:

还是递归。从底向上,先交换完根结点的左右子树,再交换根结点的左右孩子结点。自顶向下也是可以的,即先交换根结点的左右孩子,再递归交换左右子树。

递归主要要理解函数的意义,mirror函数的意义就是得到该二叉树的镜像,二叉树镜像时根结点不变。则mirror(node->left)将左子树镜像,mirror(node->right)将右子树镜像,此时,左右子树的根结点即node->left和node->right还没有交换,所以接下来交换它们,这样就完成了整棵树的镜像过程。




[cpp] view plaincopy
01.//自底向上,即先交换左右子树,再交换左右孩子节点。
02.void mirror(struct node* node)
03.{
04. if (node==NULL) {
05. return;
06. } else {
07. struct node* temp;
08. // 子树完成镜像
09. mirror(node->left);
10. mirror(node->right);
11. // 交换node的左右孩子节点
12. temp = node->left;
13. node->left = node->right;
14. node->right = temp;
15. }
16.}



[cpp] view plaincopy
01.//自顶向下完成镜像
02.void mirror2(struct node* root)
03.{
04. if (root == NULL) return;
05. struct node* tmp = root->left;
06. root->left = root->right;
07. root->right = tmp;
08. mirror2(root->left);
09. mirror2(root->right);
10.}


4、二叉搜索树复制

问题:

复制二叉搜索树的各个结点,并插入其中,使得新的二叉树还是一棵二叉搜索树。

例如原来的二叉搜索树为:

2

/ \

1 3

复制后变成:


解答:

复制源结点,然后将其作为左孩子插入到源结点中。先复制完左右子树,然后将本结点复制插入到源结点的左孩子中。




[cpp] view plaincopy
01.void doubleTree(struct node* root)
02.{
03. struct node* oldLeft;
04. if (root == NULL) return;
05. doubleTree(root->left); //复制左子树
06. doubleTree(root->right); //复制右子树
07. oldLeft = root->left;
08. root->left = newNode(root->data); //复制根结点并将其作为新的左孩子,如图中所示,结点2复制一个作为原来根结点2的左孩子。
09. root->left->left = old

Left; //复制的根结点的左孩子为原来的根结点的左孩子。如图中所示,复制的结点2的左孩子为原来根结点的左孩子结点1.
10.}


5、判定两棵二叉树结构是否相同

问题:

给定两棵二叉树,判定其结构是否相同,即对应的所有结点值是否一样。

如下面(1)(2)两棵二叉树结构相同,但是(1)(3), (2)(3)不相同。


2 2 2


/ \ / \ / \


1 3 1 3 3 1

(1) (2) (3)

解答:

先判定根结点的data域是否相同,如果相同则继续判断左右子树。一定是根结点和左右子树都相同才能判定两棵二叉树结构相同。

特殊情况处理:如果两棵树都为NULL,则相同。其他一棵为NULL,一棵不为NULL则不同。




[cpp] view plaincopy
01.int sameTree(struct node* a, struct node* b)
02.{
03. if (a==NULL && b==NULL) //两棵树都为空,返回true
04. return true;
05. else if (a!=NULL && b!=NULL) { //两棵树都不为空,则比较根结点和递归比较左右子树
06. return a->data==b->data &&
07. sameTree(a->left, b->left) &&
08. sameTree(a->right, b->right);
09. } else //其他情况,一棵树为空,一棵不为空,返回false
10. return false;
11.}


6、二叉搜索树的数目

问题:

给定结点数目num,结点的data值为1,2,3...num。给出这些结点能够构造的二叉搜索树数目。

比如结点数目为3时,结点的data依次为1,2,3,则能够构造5棵二叉搜索树:

1 1 2 3 3

\ \ / \ / /

2 3 1 3 1 2

\ / \ /

3 2 2 1

解答:

考虑到每个结点都可能是根结点root,递归计算左右子树,总的数目就是左右子树数目的乘积之和。当结点数目为3时,则当root为1时,则左子树结点为0,只有右子树结点数目为2。当root为2时,则左右子树结点数目为1,1。root为3时,左右子树结点数目为2,0。




[cpp] view plaincopy
01.int countTrees(int numKeys)
02.{
03. if (numKeys <=1) {
04. return(1);
05. }
06. else {
07. int sum = 0;
08. int left, right, root;
09. for (root=1; root<=numKeys; root++) {
10. left = countTrees(root - 1);
11. right = countTrees(numKe

ys - root);
12. // left*right为当前root的二叉搜索树数目
13. sum += left*right;
14. }
15. return(sum);
16. }










分享到:

上一篇:二叉树问题汇总(1)—基础问题
下一篇:Cassandra中布隆过滤器详解
.


查看评论


暂无评论





您还没有登录,请[登录]或[注册]

* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场









个人资料

ssjhust123





访问:76996次
积分:1693分
排名:第5986名
. 原创:84篇
转载:24篇
译文:3篇
评论:82条
.
文章搜索

.
文章分类 面试题系列(59)
数据结构与算法(40)
JAVA相关(11)
Cassandra源码分析(6)
Linux杂谈(10)
链表(8)
二叉树(18)
字符串(5)
自己动手系列(4)
栈(2)
数字之趣(8)
排序(4)
MYSQL杂谈(3)
python相关(5)
hadoop学习(1)
redis学习(3)

文章存档
2013年10月(4).
2013年09月(3).
2013年06月(2).
2013年05月(9).
2013年02月(1).
.
.
.
.
.
.
.

展开.

阅读排行 中缀表达式转换为后缀表达式(6550)
中序遍历和先序遍历/后序遍历构建二叉树(4672)
brk(), sbrk() 用法详解(2706)
判定一棵二叉树是否是二叉搜索树(2383)
序列化/反序列化二叉树(2338)
给定一个字符数组,存储有R、G、B字符,将所有字符按照RGB顺序排序(1926)
二叉树遍历之非递归算法(1757)
Cassandra中布隆过滤器详解(1743)
JAVA泛型编程全面总结(1732)
最大连续子序列和(1602)

评论排行 中缀表达式转换为后缀表达式(24)
比特位操作算法题汇总(6)
最大连续子序列和(5)
最长回文子串(5)
JAVA类库分析之HashMap(5)
brk(), sbrk() 用法详解(4)
杨氏矩阵搜索算法(3)
二叉树遍历之非递归算法(3)
Debian6安装笔记(3)
二叉树遍历之递归算法(2)

最新评论 杨氏矩阵搜索算法
ssjhust123: @wusuopuBUPT:呵呵,不客气。要是有不明白的地方,请看英文原文。

杨氏矩阵搜索算法
wusuopuBUPT: 非常感谢!

中缀表达式转换为后缀表达式
zhushanzhi: @ssjhust123:不四,过路客

中缀表达式转换为后缀表达式
ssjhust123: @zhushanzhi:激动神马,是大宇宙实验室的么?

中缀表达式转换为后缀表达式
ssjhust123: @zhushanzhi:呵呵,这位是?

中缀表达式转换为后缀表达式
zhushanzhi: 欢迎纠错,请轻拍处女贴,好激动的说。。。

中缀表达式转换为后缀表达式
zhushanzhi: @zhushanzhi:欢迎纠错,请轻拍

中缀表达式转换为后缀表达式
zhushanzhi: char str[]="+-*/(";int getId(char ch){ int i; for(...

中缀表达式转换为后缀表达式
zhushanzhi: @ssjhust123:师兄太忙,我来代劳

brk(), sbrk() 用法详解
ssjhust123: @chenlin_418:有时间研究下,呵呵



.

公司简介|招贤纳士|广告服务|银行汇款帐号|联系方式|版权声明|法律顾问|问题报告QQ客服 微博客服 论坛反馈 联系邮箱:webmaster@ 服务热线:400-600-2320京 ICP 证 070598 号北京创新乐知信息技术有限公司 版权所有世纪乐知(北京)网络技术有限公司 提供技术支持江苏乐知网络技术有限公司 提供商务支持Copyright ? 1999-2012, , All Rights Reserved

相关文档
最新文档