专栏电商日志财经减肥爱情
投稿投诉
爱情常识
搭配分娩
减肥两性
孕期塑形
财经教案
论文美文
日志体育
养生学堂
电商科学
头戴业界
专栏星座
用品音乐

数据结构与算法(六)树的入门

  树的基本定义
  树是我们计算机中非常重要的一种数据结构,同时使用树这种数据结构,可以描述现实生活中的很多事物,例如家谱、单位的组织架构、等等。
  树是由n(n1)个有限结点组成一个具有层次关系的集合。把它叫做树是因为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的。
  树具有以下特点:每个结点有零个或多个子结点;没有父结点的结点为根结点;每一个非根结点只有一个父结点;每个结点及其后代结点整体上可以看做是一棵树,称为当前结点的父结点的一个子树;树的相关术语结点的度:一个结点含有的子树的个数称为该结点的度。树的度:树中所有结点的度的最大值。叶子结点:度为0的结点称为叶结点,也可以叫做终端结点。分支结点:度不为0的结点称为分支结点,也可以叫做非终端结点。
  结点的层次:从根结点开始,根结点的层次为1,根的直接后继层次为2,以此类推。结点的层序编号:将树中的结点,按照从上层到下层,同层从左到右的次序排成一个线性序列,把他们编成连续的自然数。树的高度(深度):树中结点的最大层次。
  森林:m(m0)个互不相交的树的集合,将一颗非空树的根结点删去,树就变成一个森林;给森林增加一个统一的根结点,森林就变成一棵树
  孩子结点:一个结点的直接后继结点称为该结点的孩子结点。双亲结点(父结点):一个结点的直接前驱称为该结点的双亲结点。兄弟结点:同一双亲结点的孩子结点间互称兄弟结点。
  二叉树的基本定义
  二叉树就是度不超过2的树(每个结点最多有两个子结点)
  满二叉树
  在一棵二叉树中,如果所有分支结点都存在左子树和右子树,并且所有叶子都在同一层上,这样的二叉树称为满二叉树。
  完全二叉树
  叶子节点只能出现在最下层和次下层,并且最下面一层的结点都集中在该层最左边的若干位置的二叉树。
  满二叉树一定是一棵完全二叉树,但完全二叉树不一定是满的。判断某二叉树是否是完全二叉树
  完全二叉树的特点:叶子结点只能出现在最下两层。最下层的叶子一定集中在左部连续位置。倒数二层,若有叶子结点,一定都在右部连续位置。如果结点度为1,则该结点只有左孩子,即不存在只有右子树的情况。同样结点数的二叉树,完全二叉树的深度最小。
  给每个结点按照满二叉树的结构逐层顺序编号,如果编号出现空档,就说明不是完全二叉树,否则就是。二叉查找树的创建二叉树的结点类
  根据对图的观察,我们发现二叉树其实就是由一个一个的结点及其之间的关系组成的,按照面向对象的思想,我们设计一个结点类来描述结点这个事物。结点类设计
  类名
  NodeK,V
  构造方法
  Node(Kkey,Vvalue,NodeK,Vleft,NodeK,Vright):创建Node对象
  成员变量privateNodeK,Vleft:记录左子结点
  privateNodeK,Vright:记录右子结点
  privateKkey:存储键
  privateVvalue:存储值结点类代码实现二叉查找树结点paramKparamVNoArgsConstructorAllArgsConstructorDataprivatestaticclassNodeK,V{privateKkey;privateVvalue;privateNodeK,Vleft;privateNodeK,Vright;}二叉查找树设计
  类名
  BinaryTree,V
  构造方法
  BinaryTree():创建BinaryTree对象
  成员变量privateNodeK,Vroot:记录根结点
  privateintn:记录树中元素的个数
  成员方法publicvoidput(Kkey,Vvalue):向树中插入一个键值对
  privateNodeput(NodeK,Vx,Kkey,Vvalue):给指定树x上,添加键一个键值对,并返回添加后的新树
  publicVget(Kkey):根据key,从树中找出对应的值
  privateVget(NodeK,Vx,Kkey):从指定的树x中,找出key对应的值
  publicvoiddelete(Kkey):根据key,删除树中对应的键值对
  privateNodedelete(NodeK,Vx,Kkey):删除指定树x上的键为key的键值对,并返回删除后的新树
  publicintsize():获取树中元素的个数二叉查找树代码实现publicclassBinaryTreeKextendsComparableK,V{记录根结点privateNodeK,Vroot;记录树中元素的个数privateintn;publicBinaryTree(){}插入一个键值对publicvoidput(Kkey,Vvalue){rootput(root,key,value);}1。如果当前树中没有任何一个结点,则直接把新结点当做根结点使用2。如果当前树不为空,则从根结点开始:2。1如果新结点的key小于当前结点的key,则继续找当前结点的左子结点2。2如果新结点的key大于当前结点的key,则继续找当前结点的右子结点2。3如果新结点的key等于当前结点的key,则树中已经存在这样的结点,替换该结点的value值即可privateNodeK,Vput(NodeK,Vx,Kkey,Vvalue){if(xnull){n;returnnewNode(key,value,null,null);}varcmpkey。compareTo(x。key);if(cmp0){找右子树x。rightput(x。right,key,value);}elseif(cmp0){找左子树x。leftput(x。left,key,value);}else{替换值x。valuevalue;}returnx;}publicVget(Kkey){returnget(root,key);}privateVget(NodeK,Vx,Kkey){if(xnull){returnnull;}varcmpkey。compareTo(x。key);if(cmp0){returnget(x。right,key);}elseif(cmp0){returnget(x。left,key);}else{returnx。value;}}publicvoiddelete(Kkey){delete(root,key);}1。找到被删除结点2。找到被删除结点右子树中的最小结点minNode3。删除右子树中的最小结点4。让被删除结点的左子树称为最小结点minNode的左子树,让被删除结点的右子树称为最小结点minNode的右子树5。让被删除结点的父节点指向最小结点minNodeprivateNodeK,Vdelete(NodeK,Vx,Kkey){if(xnull){returnnull;}varcmpkey。compareTo(x。key);if(cmp0){找右子树x。rightdelete(x。right,key);}elseif(cmp0){找左子树x。leftdelete(x。left,key);}else{先找到右子树中最小的结点n;if(x。rightnull){returnx。left;}if(x。leftnull){returnx。right;}遍历获取右子树最左结点varminNodemin(x。right);删除右子树中最小的节点varnx。right;while(n。left!null){if(n。left。leftnull){n。leftnull;}else{nn。left;}}让x结点的左子树成为minNode的左子树minNode。leftx。left;让x结点的右子树成为minNode的右子树minNode。rightx。right;让x节点的父节点指向minNodexminNode;}returnx;}publicintsize(){returnn;}publicNodeK,Vmin(){returnmin(root);}privateNodeK,Vmin(NodeK,Vx){if(x。left!null){returnmin(x。left);}else{returnx;}}publicNodeK,Vmax(){returnmax(root);}privateNodeK,Vmax(NodeK,Vx){if(x。right!null){returnmax(x。right);}else{returnx;}}二叉查找树结点paramKparamVNoArgsConstructorAllArgsConstructorDataprivatestaticclassNodeK,V{privateKkey;privateVvalue;privateNodeK,Vleft;privateNodeK,Vright;}}插入方法put实现思想如果当前树中没有任何一个结点,则直接把新结点当做根结点使用如果当前树不为空,则从根结点开始:如果新结点的key小于当前结点的key,则继续找当前结点的左子结点;如果新结点的key大于当前结点的key,则继续找当前结点的右子结点;如果新结点的key等于当前结点的key,则树中已经存在这样的结点,替换该结点的value值即可。
  查询方法get实现思想
  从根节点开始:如果要查询的key小于当前结点的key,则继续找当前结点的左子结点;如果要查询的key大于当前结点的key,则继续找当前结点的右子结点;如果要查询的key等于当前结点的key,则树中返回当前结点的value。删除方法delete实现思想找到被删除结点;找到被删除结点右子树中的最小结点minNode删除右子树中的最小结点让被删除结点的左子树称为最小结点minNode的左子树,让被删除结点的右子树称为最小结点minNode的右子树让被删除结点的父节点指向最小结点minNode
  二叉树的基础遍历
  很多情况下,我们可能需要像遍历数组数组一样,遍历树,从而拿出树中存储的每一个元素,由于树状结构和线性结构不一样,它没有办法从头开始依次向后遍历,所以存在如何遍历,也就是按照什么样的搜索路径进行遍历的问题。
  我们把树简单的画作上图中的样子,由一个根节点、一个左子树、一个右子树组成,那么按照根节点什么时候被访问,我们可以把二叉树的遍历分为以下三种方式:前序遍历:先访问根结点,然后再访问左子树,最后访问右子树中序遍历:先访问左子树,中间访问根节点,最后访问右子树后序遍历:先访问左子树,再访问右子树,最后访问根节点
  如果我们分别对下面的树使用三种遍历方式进行遍历,得到的结果如下:
  学习二叉树的遍历,一定要有递归思想,比如前序遍历,本质顺序是:根左右,先访问E,然后访问B,但是B也是一棵树,此时思维应该转换到以B为根结点的子树上,所以B下面是访问A。前序遍历
  根节点第一个(前面)访问,所以叫前序遍历
  实现步骤:把当前结点的key放入到队列中找到当前结点的左子树,如果不为空,递归遍历左子树找到当前结点的右子树,如果不为空,递归遍历右子树使用前序遍历,获取整个树中的所有键publicQueueKpreErgodic(){varkeysnewLinkedListK();preErgodic(root,keys);returnkeys;}使用前序遍历,把指定树x中的所有键放入到keys队列中privatevoidpreErgodic(NodeK,Vx,QueueKkeys){if(xnull){return;}把x结点的key放入queuekeys。add(x。key);preErgodic(x。left,keys);preErgodic(x。right,keys);}中序遍历
  根节点在第二个(中间)访问,所以叫中序遍历
  实现步骤:找到当前结点的左子树,如果不为空,递归遍历左子树把当前结点的key放入到队列中;找到当前结点的右子树,如果不为空,递归遍历右子树使用中序遍历,获取整个树中的所有键publicQueueKmidErgodic(){varkeysnewLinkedListK();midErgodic(root,keys);returnkeys;}privatevoidmidErgodic(NodeK,Vx,QueueKkeys){if(xnull){return;}midErgodic(x。left,keys);把x结点的key放入queuekeys。add(x。key);midErgodic(x。right,keys);}后序遍历
  根节点在第三个(后面)访问,所以叫中序遍历
  实现步骤:找到当前结点的左子树,如果不为空,递归遍历左子树找到当前结点的右子树,如果不为空,递归遍历右子树把当前结点的key放入到队列中使用后序遍历,获取整个树中的所有键publicQueueKpostErgodic(){varkeysnewLinkedListK();postErgodic(root,keys);returnkeys;}privatevoidpostErgodic(NodeK,Vx,QueueKkeys){if(xnull){return;}postErgodic(x。left,keys);postErgodic(x。right,keys);把x结点的key放入queuekeys。add(x。key);}二叉树的层序遍历
  所谓的层序遍历,就是从根节点(第一层)开始,依次向下,获取每一层所有结点的值,有二叉树如下:
  那么层序遍历的结果是:EBGADFHC
  实现步骤:创建队列,存储每一层的结点;使用循环从队列中弹出一个结点:获取当前结点的key;如果当前结点的左子结点不为空,则把左子结点放入到队列中如果当前结点的右子结点不为空,则把右子结点放入到队列中
  层序遍历1。创建队列,存储每一层的结点;2。使用循环从队列中弹出一个结点:2。1获取当前结点的key;2。2如果当前结点的左子结点不为空,则把左子结点放入到队列中2。3如果当前结点的右子结点不为空,则把右子结点放入到队列中publicQueueKlayerErgodic(){varkeysnewLinkedListK();varnodesnewLinkedListNodeK,V();nodes。add(root);while(!nodes。isEmpty()){varnodenodes。pop();keys。add(node。key);if(node。left!null){nodes。add(node。left);}if(node。right!null){nodes。add(node。right);}}returnkeys;}二叉树的最大深度问题
  给定一棵树,请计算树的最大深度(树的根节点到最远叶子结点的最长路径上的结点数)
  上面这棵树的最大深度为4。实现步骤如果根结点为空,则最大深度为0;计算左子树的最大深度;计算右子树的最大深度;当前树的最大深度左子树的最大深度和右子树的最大深度中的较大者1计算整个树的最大深度publicintmaxDepth(){returnmaxDepth(root);}计算指定树x的最大深度privateintmaxDepth(NodeK,Vx){if(xnull){return0;}varmaxL0;varmaxR0;计算左子树的最大深度if(x。left!null){maxLmaxDepth(x。left);}计算右子树的最大深度if(x。right!null){maxRmaxDepth(x。right);}比较左右子数的最大深度returnMath。max(maxL,maxR)1;}折纸问题
  请把一段纸条竖着放在桌子上,然后从纸条的下边向上方对折1次,压出折痕后展开。此时折痕是凹下去的,即折痕突起的方向指向纸条的背面。如果从纸条的下边向上方连续对折2次,压出折痕后展开,此时有三条折痕,从上到下依次是下折痕、下折痕和上折痕。
  给定一个输入参数N,代表纸条都从下边向上方连续对折n次,请从上到下打印所有折痕的方向。
  例如:n1时,打印:down;n2时,打印:downdownup
  分析
  我们把对折后的纸张翻过来,让粉色朝下,这时把第一次对折产生的折痕看做是根结点,那第二次对折产生的下折痕就是该结点的左子结点,而第二次对折产生的上折痕就是该结点的右子结点,这样我们就可以使用树型数据结构来描述对折后产生的折痕。
  这棵树有这样的特点:根结点为下折痕;每一个结点的左子结点为下折痕;每一个结点的右子结点为上折痕;
  实现步骤定义结点类构建深度为n的折痕树;第一次对折,只有一条折痕,创建根结点;如果不是第一次对折,则使用队列保存根结点;循环遍历队列:从队列中拿出一个结点;如果这个结点的左子结点不为空,则把这个左子结点添加到队列中;如果这个结点的右子结点不为空,则把这个右子结点添加到队列中;判断当前结点的左子结点和右子结点都不为空,如果是,则需要为当前结点创建一个值为down的左子结点,一个值为up的右子结点。使用中序遍历,打印出树中所有结点的内容;publicclassPagerFolding{构建深度为n的折痕树paramn深度return折痕树publicstaticNodeStringcreateTree(intn){NodeStringrootnull;for(inti0;in;i){if(i0){1。第一次对折,只有一条折痕,创建根结点;rootnewNode(down);continue;}2。如果不是第一次对折,则使用队列保存根结点;varnodesnewLinkedListNodeString();nodes。add(root);3。循环遍历队列:while(!nodes。isEmpty()){3。1从队列中拿出一个结点vartempnodes。pop();3。2如果这个结点的左子结点不为空,则把这个左子结点添加到队列中;if(temp。left!null){nodes。add(temp。left);}3。3如果这个结点的右子结点不为空,则把这个右子结点添加到队列中;elseif(temp。right!null){nodes。add(temp。right);}3。4判断当前结点的左子结点和右子结点都不为空,如果是,则需要为当前结点创建一个值为down的左子结点,一个值为up的右子结点。else{temp。leftnewNode(down);temp。rightnewNode(up);}}}returnroot;}使用中序遍历打印结果paramxpublicstaticvoidprintTree(NodeStringx){if(xnull){return;}if(x。left!null){printTree(x。left);}System。out。print(x。value);if(x。right!null){printTree(x。right);}}二叉查找树结点paramT值类型NoArgsConstructorAllArgsConstructorDataprivatestaticclassNodeT{privateTvalue;privateNodeTleft;privateNodeTright;publicNode(Tvalue){this。valuevalue;}}}
  测试classPagerFoldingTest{TestvoidcreateTree(){varpagerFoldingPagerFolding。createTree(4);downdownupdownupdownupPagerFolding。printTree(pagerFolding);}}
  输出的结果是:downdownupdownupdownup,符合题意。

新能源产业链上游业绩狂飙锂价上涨会持续吗?图据天齐锂业官网10月14日晚间,国内锂业双雄赣锋锂业(002460。SZ)天齐锂业(002466。SZ)均发布前三季度业绩预告,受益于新能源行业快速发展,两家公司前三季度净利润双洗鞋机热销出圈懒人神器能否走出独立行情?十一假期期间,又一款懒人神器受到消费者追捧。10月9日,国庆期间洗鞋机销售额暴增700的话题登上微博热搜。据央视财经报道,十一假期前三天,洗鞋机销售额较去年同期增长7倍。在评论区中一天两起!交警这波操作太圈粉近日昭阳交警近日在开展路检路查的时候两次发现有车辆拉载着急需送医的患者为了不耽误病人的抢救时机昭阳交警在保证安全的前提下一路鸣笛开道为两位患者赢得了宝贵的救治时间24小时内两次紧急香江四大才子的香艳往事自古才子爱佳人。在香港,有四位文采斐然的男子,他们是一个时代的象征,也是一段传奇的里程碑。黄霑,金庸,蔡澜,倪匡四大才子分别是金庸倪匡黄霑和蔡澜。他们不光事业成功,情史也相当丰富多孩子的取名2022育儿季名字伴随人的一生,上学工作生活,有个好名字给人自信,是成功的一半,那么怎么才能给孩子取字好名字呢?现在人许多子涵,梓涵,紫涵,且不说重名多,也没有意义,更有仼性的叫王结婚要尽快生孩子现在好多人结婚都不着急生孩子,都想着过几年二人世界。我身边也有很多这种情况,但凡只要碰到这种情况,我都会劝他们早点生。我的观念是早生早好,多子多福,不要怀疑我的年龄,其实我是个90tes激战越南1号种子gam落败,荣获小组第三享受回国机票优先权2022电竞季被我们给予厚望的tes再次刷新下限,在对战越南gam的比赛中,上演巅峰对决,最后不敌越南大魔王被反推一波结束比赛,同时也宣告tes此次世界赛之旅到此结束!虽然在最后两好消息,有替补!TES仍有机会争夺小组第一出线A组EDG小组第二出线,B组JDG小组第一出线,接下来就是C组的TES了,作为本次世界赛LPL四支队伍中最被寄予厚望的队伍,小组赛第一轮的成绩却有点不符合预期,12的开局给自己的本是否后悔对乌军事行动?普京回应10月14日,俄总统普京回应是否后悔对乌采取军事行动问题时称,俄罗斯早晚会有现在的遭遇,越迟对俄方越不利,并表示俄方的行动是正确和及时的。普京两周内完成!10月14日,俄罗斯总统普厦门大学团队用变换光学原理造出人工黑洞来源科技日报数字报黑洞是存在于宇宙空间中的一类大质量天体,因引力极大,所有进入其视界内的光和粒子都无法逃逸。受黑洞能够完美吸收视界内物质这一特性启发,研究人员一直希望能够设计一些人8K以下值得冲的笔记本头条创作挑战赛8K以内的笔记本要怎么选,品牌要大,售后要好,性能够高,性价比高,结合以上四点。今天就推荐三款非常适合学生党的游戏本!这款是性价比之选,宏碁暗影骑士擎配置是12代I5
法学小知识宪法发展历史宪法历史宪法,最早出现于近代的资本主义社会,是资本主义革命时期的产物近代宪法产生条件经济条件资本主义生产关系的确立政治条件资产阶级掌握国家政权,实现对社会的统治,确立资产阶级民主制江西省安福县历史沿革及行政区划安福县位于江西省中部偏西吉安市的西北部。地处东经11411447北纬2742736之间。东邻吉安,南接永新,西与莲花萍乡交界,北和宜春分宜接壤。历史沿革安福历史悠久,古属荆扬二州。美国资产阶级革命的过程以及意义自新航路开辟以来,英法西葡等列强争先走上了殖民掠夺的道路,列强之间为了争抢殖民地,不惜爆发了许多次世界范围内的战争,其中最著名的当属17561763年的七年战争。这场战争中英国成为刘邦到底是怎么样的一个人,你看懂了吗?历史开讲说道历代皇帝,我最喜欢最佩服确实就是刘邦了。他究竟是个怎么样的人,估计大部分普通人是读不懂看不明白的,因为缺乏通透的思维模式。纵观历史上真正排得上厉害的人,屈指可数,刘邦绝乌克兰910的领土都是俄罗斯赠送历史上有乌克兰苏维埃是苏联加盟主体没有基辅大,当代乌克兰大概910领土是俄罗斯送的。有人就辩解说是苏联分家,其实苏联说白了就是俄罗斯,俄罗斯不同意分领土给乌克兰,谁敢分?当时苏联是我们常说的三皇五帝,究竟是哪三皇?哪五帝?我们常说的三皇五帝,究竟是哪三皇?哪五帝?我国对于三皇五帝历来有不同的说法。一般,三皇指的是燧人氏伏羲氏神农氏五帝指的是黄帝颛顼帝喾尧舜。三皇燧人氏,号燧皇,又奉为天皇,是中国迄今法律小知识宪法的概念大有学问宪法释义一宪法词义的演变中国古代和西方古代都曾有过宪法这一词语,但他们的涵义却与近现代的宪法迥然不同。在中国古代的典籍中,曾出现过宪宪法宪章等词语。其涵义大致有三种情况一是清政府为何会封禁长白山200年,这其中到底有什么秘密?清朝建立政权后在顺治的命令下直接将长白山给封锁了,不准任何人进入,这其中到底有什么秘密?长白山在中朝边境地区,是东北最高的山,达到了2691米。不过,它最高峰并不在中国,而是在隔壁明末第一将,全家47口被清军灭门,300年后他子孙把溥仪赶出皇宫远山长黯,落霞似血,天光乍现,只见将军一人,执枪立于城墙之上,眸中落寂两行,眼下已是满目疮痍,千载荒凉,白骨成沙,长烟破晓,三军齐出,抬眼望去,是马革裹尸后的一腔热血,是冷贴卷刃里敦煌出土墓碑,揭开玄武门之变真相,学者难怪李建成被轻易射死大唐盛世是人们对唐朝的固有观念和印象。纵观当代古装电视剧,为我们展现了众多唐朝的历史人物和历史故事,主要集中于唐太宗唐玄宗杨贵妃等重要人物。在一场历史事件中需要大人物带头策划和许多蒙古汗国世系(12061634)一大蒙古汗国世系(12061634)太祖铁木真(成吉思汗)12061227睿宗拖雷监国(太祖四子)12271229太宗窝阔台(木亦坚汗,太祖三子)12291241乃马真皇后监国(太宗
友情链接:快好找快生活快百科快传网中准网文好找聚热点快软网