1 00:00:00,000 --> 00:00:02,770 [Powered by Google Translate] [第7条:更舒适] 2 00:00:02,770 --> 00:00:05,090 罗布·鲍登] [哈佛大学] 3 00:00:05,090 --> 00:00:07,930 [这是CS50] [CS50.TV] 4 00:00:07,930 --> 00:00:10,110 好的。所以,像我在我的电子邮件中说, 5 00:00:10,110 --> 00:00:14,060 这将是一个二进制树密集的部分。 6 00:00:14,060 --> 00:00:16,820 但也有很多问题。 7 00:00:16,820 --> 00:00:18,920 因此,我们将尝试并绘制出每一个问题 8 00:00:18,920 --> 00:00:25,430 进入痛苦的细节做的事情的最好方法。 9 00:00:25,430 --> 00:00:31,200 所以,在开始的时候,我们去通过二进制树之类的东西的样品图纸。 10 00:00:31,200 --> 00:00:35,970 所以在这里,“请记住,一个二进制树有类似的链表节点, 11 00:00:35,970 --> 00:00:38,150 除,而不是一个指针有两种:一种为在左边的'孩子' 12 00:00:38,150 --> 00:00:41,950 和一个正确的'孩子'。“ 13 00:00:41,950 --> 00:00:45,630 因此,一个二进制树就像是一个链表, 14 00:00:45,630 --> 00:00:47,910 除了结构有两个指针。 15 00:00:47,910 --> 00:00:51,390 三元树,这将有个三分球, 16 00:00:51,390 --> 00:00:56,540 有N-叉树,其中有一个通用的指针 17 00:00:56,540 --> 00:01:00,320 就是你必须对malloc足够大,有 18 00:01:00,320 --> 00:01:04,840 足够的指点所有可能的孩子。 19 00:01:04,840 --> 00:01:08,200 因此,二叉树正好有两个固定数量的。 20 00:01:08,200 --> 00:01:11,260 如果你愿意,你可以给一个链接列表为一元树, 21 00:01:11,260 --> 00:01:15,360 但我不认为任何人都需要它,。 22 00:01:15,360 --> 00:01:18,060 “画一个方框和箭头图的二进制树节点 23 00:01:18,060 --> 00:01:24,110 Nate的最喜欢的数字,7,每个孩子指针为空。“ 24 00:01:24,110 --> 00:01:27,780 因此,iPad模式。 25 00:01:27,780 --> 00:01:30,280 >> 这将是非常简单的。 26 00:01:30,280 --> 00:01:36,150 我们只是有一个节点,我会画一个矩形。 27 00:01:36,150 --> 00:01:38,730 我会在这里得出的值。 28 00:01:38,730 --> 00:01:41,090 因此,该值将在这里, 29 00:01:41,090 --> 00:01:44,770 ,然后在这里我们将不得不在右边的左指针在左,右指针。 30 00:01:44,770 --> 00:01:50,430 这是非常多,所以约定来调用它左,右,指针名。 31 00:01:50,430 --> 00:01:52,460 这些都将是空。 32 00:01:52,460 --> 00:01:57,870 这将是空的,这只会是空的。 33 00:01:57,870 --> 00:02:03,630 好吧。因此,回到这里。 34 00:02:03,630 --> 00:02:05,700 “一个链表,我们只需要存储一个指针 35 00:02:05,700 --> 00:02:09,639 在列表中的第一个节点是为了记住整个链表,或整个列表。 36 00:02:09,639 --> 00:02:11,650 同样,树木,我们只需要存储一个指针 37 00:02:11,650 --> 00:02:13,420 为了记住整个树到单个节点。 38 00:02:13,420 --> 00:02:15,980 这是卡莱节点树的“根”。 39 00:02:15,980 --> 00:02:18,320 从之前建立在你的图,或画一个新的 40 00:02:18,320 --> 00:02:21,690 这样,你有一个盒子和箭头描绘的二叉树 41 00:02:21,690 --> 00:02:25,730 与7的值,然后3在左, 42 00:02:25,730 --> 00:02:32,760 然后9在右边,然后6在右侧的3。“ 43 00:02:32,760 --> 00:02:34,810 让我们来看看,如果我能记得所有这一切在我的脑海。 44 00:02:34,810 --> 00:02:37,670 因此,这将是我们的根在这里。 45 00:02:37,670 --> 00:02:41,600 的地方,我们还会有一些指针的东西,我们会打电话给根, 46 00:02:41,600 --> 00:02:45,140 它指向了这个家伙。 47 00:02:45,140 --> 00:02:48,490 现在一个新的节点, 48 00:02:48,490 --> 00:02:52,870 我们有什么,在左边吗? 49 00:02:52,870 --> 00:02:57,140 因此,一个新的节点3,并它最初指向空。 50 00:02:57,140 --> 00:02:59,190 我就把N. 51 00:02:59,190 --> 00:03:02,250 现在,我们希望去左边的7。 52 00:03:02,250 --> 00:03:06,840 因此,我们改变这个指针指向这个家伙。 53 00:03:06,840 --> 00:03:12,420 我们这样做。我们希望有一个在这里 54 00:03:12,420 --> 00:03:14,620 它最初只是说空。 55 00:03:14,620 --> 00:03:19,600 我们要改变这个指针,指向9, 56 00:03:19,600 --> 00:03:23,310 现在我们要放6到右边的3。 57 00:03:23,310 --> 00:03:32,170 因此,它要 - 6。 58 00:03:32,170 --> 00:03:34,310 那小子将指向。 59 00:03:34,310 --> 00:03:38,320 好吧。所以,这一切都要求我们做的。 60 00:03:38,320 --> 00:03:42,770 >> 现在,让我们多一些术语。 61 00:03:42,770 --> 00:03:46,690 我们已经讨论了如何树的根是最顶端的树中的节点。 62 00:03:46,690 --> 00:03:54,720 一个包含7。在树的底部的节点被称为叶子。 63 00:03:54,720 --> 00:04:01,240 任何节点作为其子空是叶。 64 00:04:01,240 --> 00:04:03,680 因此,它是可能的,如果我们的二进制树只是一个单一的节点, 65 00:04:03,680 --> 00:04:10,130 一棵树是一片叶子,就是这样。 66 00:04:10,130 --> 00:04:12,060 “”高度“的树是你必须做的跳数 67 00:04:12,060 --> 00:04:16,620 得到从顶端到叶子。“ 68 00:04:16,620 --> 00:04:18,640 我们将进入,在第二,不同的 69 00:04:18,640 --> 00:04:21,940 之间的平衡和非平衡二叉树, 70 00:04:21,940 --> 00:04:29,470 但现在,这种树的整体高度 71 00:04:29,470 --> 00:04:34,520 我想说的是3,但如果你的跳数计数 72 00:04:34,520 --> 00:04:39,710 你必须为了得到9,那么它真的只是一个身高2。 73 00:04:39,710 --> 00:04:43,340 现在这是一个不平衡的二叉树, 74 00:04:43,340 --> 00:04:49,840 但我们会谈论平衡时,它得到相关的。 75 00:04:49,840 --> 00:04:52,040 所以,现在我们可以谈论一棵树的节点在条款 76 00:04:52,040 --> 00:04:54,700 相对于树中的其他节点。 77 00:04:54,700 --> 00:04:59,730 所以,现在我们有父母,子女,兄弟姐妹,祖先和子孙。 78 00:04:59,730 --> 00:05:05,650 他们是相当普遍的意义上说,他们的意思。 79 00:05:05,650 --> 00:05:09,610 如果我们问 - 它的父母。 80 00:05:09,610 --> 00:05:12,830 那么,什么是3的父? 81 00:05:12,830 --> 00:05:16,090 [学生] 7。 >>呀。家长只是要分给你。 82 00:05:16,090 --> 00:05:20,510 那么什么是儿童的7? 83 00:05:20,510 --> 00:05:23,860 [学生] 3和9。 >>呀。 84 00:05:23,860 --> 00:05:26,460 请注意,“孩子们”的字面意思是儿童, 85 00:05:26,460 --> 00:05:31,010 所以将不适用,因为它就像一个孙子。 86 00:05:31,010 --> 00:05:35,540 不过,如果我们去的后裔,所以是什么7的后裔? 87 00:05:35,540 --> 00:05:37,500 [学生] 3,第6和第9。 >>呀。 88 00:05:37,500 --> 00:05:42,330 根节点的后代将是树中的一切, 89 00:05:42,330 --> 00:05:47,950 可能除了根节点,如果你不想认为的后裔。 90 00:05:47,950 --> 00:05:50,750 最后,祖先,所以它是相反的方向。 91 00:05:50,750 --> 00:05:55,740 那么,什么是6的祖先吗? 92 00:05:55,740 --> 00:05:58,920 [学生] 3和7。 >>呀。 9不包括在内。 93 00:05:58,920 --> 00:06:02,520 这仅仅是直接的后裔回到根 94 00:06:02,520 --> 00:06:13,230 将是你的祖先。 95 00:06:13,230 --> 00:06:16,300 >> “我们说,一个二叉树是”责令“如果在树中的每个节点, 96 00:06:16,300 --> 00:06:19,530 其后代在左侧有小的值 97 00:06:19,530 --> 00:06:22,890 和在右边的所有的那些有较大的值。 98 00:06:22,890 --> 00:06:27,060 例如,上面的树是有序的,但它不是唯一可能的有序安排。“ 99 00:06:27,060 --> 00:06:30,180 在我们到达, 100 00:06:30,180 --> 00:06:36,420 有序二元树也被称为二叉查找树。 101 00:06:36,420 --> 00:06:38,660 在这里,我们要求有序二元树, 102 00:06:38,660 --> 00:06:41,850 但我从来没有听到它被称为有序二元树前, 103 00:06:41,850 --> 00:06:46,650 一个测验,我们更倾向于把二叉搜索树。 104 00:06:46,650 --> 00:06:49,250 它们是同一个, 105 00:06:49,250 --> 00:06:54,580 重要的是你认识二叉树和二叉搜索树的区别。 106 00:06:54,580 --> 00:06:58,830 二叉树只是一棵树,两件事情。 107 00:06:58,830 --> 00:07:02,120 每个结点两件事情。 108 00:07:02,120 --> 00:07:06,310 有没有推理,它指向的值。 109 00:07:06,310 --> 00:07:11,370 所以想在这里,因为它是一个二叉搜索树, 110 00:07:11,370 --> 00:07:14,030 我们知道,如果我们向左走7, 111 00:07:14,030 --> 00:07:16,670 然后,我们能接触到的所有的值 112 00:07:16,670 --> 00:07:19,310 将剩下的7必须是小于7。 113 00:07:19,310 --> 00:07:24,070 请注意,所有的值小于7的第3和第6。 114 00:07:24,070 --> 00:07:26,040 这些都是7左侧。 115 00:07:26,040 --> 00:07:29,020 如果我们去7的权利,一切都必须大于7, 116 00:07:29,020 --> 00:07:33,220 因此9 7是正确的,所以我们是很好的。 117 00:07:33,220 --> 00:07:36,150 这是一个不为一个二进制树的情况下, 118 00:07:36,150 --> 00:07:40,020 一个正规的二进制树中,我们就可以有3个在顶部,7的左侧, 119 00:07:40,020 --> 00:07:47,630 9至7的左侧; theres没有的值的任何顺序。 120 00:07:47,630 --> 00:07:56,140 现在,我们将不能真正做到这一点,因为它的繁琐和不必要的, 121 00:07:56,140 --> 00:07:59,400 但“试图吸引尽可能多的有序树,你能想到的 122 00:07:59,400 --> 00:08:01,900 使用的数字7,3,9和6。 123 00:08:01,900 --> 00:08:06,800 有多少个不同的安排?的高度,每一个是什么?“ 124 00:08:06,800 --> 00:08:10,480 >> 我们会做一对夫妇,但其主要思想是, 125 00:08:10,480 --> 00:08:16,530 这是在没有办法包含这些值的二进制树的一个唯一的表示。 126 00:08:16,530 --> 00:08:22,760 我们需要的是一些二进制树,它含有7,3,6,和9。 127 00:08:22,760 --> 00:08:25,960 另一个可能的有效的将3根, 128 00:08:25,960 --> 00:08:30,260 去的左侧和它的6,去左边,它是7, 129 00:08:30,260 --> 00:08:32,730 去的左侧和它的9。 130 00:08:32,730 --> 00:08:36,169 这是一个非常有效的二叉搜索树。 131 00:08:36,169 --> 00:08:39,570 这是不是非常有帮助,因为它就像一个链表 132 00:08:39,570 --> 00:08:43,750 所有这些指针是空的。 133 00:08:43,750 --> 00:08:48,900 但是,它是一个有效的树。是吗? 134 00:08:48,900 --> 00:08:51,310 [学生]值必须在正确的吗? 135 00:08:51,310 --> 00:08:56,700 或者是这样的 - ? >>我的意思是这些走另一条路。 136 00:08:56,700 --> 00:09:00,960 还有 - 是的,让我们切换,。 137 00:09:00,960 --> 00:09:07,770 9,7,6,3。良好的渔获物。 138 00:09:07,770 --> 00:09:11,730 它仍然有,服从什么是二进制树搜索是应该做的。 139 00:09:11,730 --> 00:09:15,650 所以一切向左侧是小于任何给定的节点。 140 00:09:15,650 --> 00:09:23,180 我们可以只动,说,这6,把它放在这里。 141 00:09:23,180 --> 00:09:26,880 不,我们不能。我为什么这样做呢? 142 00:09:26,880 --> 00:09:35,350 让我们做 - 这里是6,7,6点到3点。 143 00:09:35,350 --> 00:09:39,290 这仍然是一个有效的二叉搜索树。 144 00:09:39,290 --> 00:09:49,260 什么是错的,如果我 - 让我们来看看,如果我能想出​​的安排。 145 00:09:49,260 --> 00:09:52,280 是啊,好吧。那么,什么是错的这棵树吗? 146 00:09:52,280 --> 00:10:08,920 我想我已经给你一个暗示,有什么不对的地方。 147 00:10:08,920 --> 00:10:14,430 我为什么这样做呢? 148 00:10:14,430 --> 00:10:18,510 好吧。这看起来很合理的。 149 00:10:18,510 --> 00:10:22,590 如果我们看一下在每个节点上,如7,然后到左边的7 3。 150 00:10:22,590 --> 00:10:24,960 因此,我们有3个,3的权利的东西是一个6。 151 00:10:24,960 --> 00:10:27,750 如果你看的东西的权利6 6,9。 152 00:10:27,750 --> 00:10:30,910 那么,为什么这不是一个有效的二叉搜索树吗? 153 00:10:30,910 --> 00:10:36,330 [学生] 9仍是7左侧。 >>呀。 154 00:10:36,330 --> 00:10:43,710 它必须是真实的,所有你所能达到的左7的值都小于7。 155 00:10:43,710 --> 00:10:49,120 如果我们向左走7,我们得到的,我们仍然可以到6, 156 00:10:49,120 --> 00:10:52,520 我们仍然可以得到为9,但通过在经历小于7, 157 00:10:52,520 --> 00:10:55,070 我们不应该能够得到一个数字,大于7。 158 00:10:55,070 --> 00:10:59,830 因此,这是不是一个有效的二叉搜索树。 159 00:10:59,830 --> 00:11:02,330 >> 我哥哥其实是有一个面试问题, 160 00:11:02,330 --> 00:11:07,760 这基本上是一些东西来验证这一点,只是代码 161 00:11:07,760 --> 00:11:10,500 一棵树是一个二叉搜索树, 162 00:11:10,500 --> 00:11:13,580 所以他做的第一件事是检查,看看 163 00:11:13,580 --> 00:11:17,020 如果左边和右边是正确的,然后循环。 164 00:11:17,020 --> 00:11:19,700 但你不能做到这一点,你必须跟踪 165 00:11:19,700 --> 00:11:22,550 的事实,现在,我已经走了剩下的7, 166 00:11:22,550 --> 00:11:26,340 在这个子树中的一切必须小于7。 167 00:11:26,340 --> 00:11:28,430 正确的算法需要跟踪 168 00:11:28,430 --> 00:11:35,970 的值的范围可能里钻 169 00:11:35,970 --> 00:11:38,360 通过所有这些,我们不会去。 170 00:11:38,360 --> 00:11:41,630 有一个很好的递推关系, 171 00:11:41,630 --> 00:11:44,810 虽然我们没有得到这些,我们不会让那些, 172 00:11:44,810 --> 00:11:47,030 确定有多少实际上是。 173 00:11:47,030 --> 00:11:53,180 因此,有14人。 174 00:11:53,180 --> 00:11:56,020 的想法,你会怎么做数学是一样的, 175 00:11:56,020 --> 00:11:59,770 你可以选择任何一个节点是根, 176 00:11:59,770 --> 00:12:03,160 然后如果我选择7根节点, 177 00:12:03,160 --> 00:12:08,150 再有,说一些数字,可以去我的左节点, 178 00:12:08,150 --> 00:12:10,440 有一些数字,可以成为我的右节点, 179 00:12:10,440 --> 00:12:15,090 但如果我有n个总人数,然后可以去左边的金额 180 00:12:15,090 --> 00:12:18,820 加量,可以去右边的是N - 1。 181 00:12:18,820 --> 00:12:26,130 因此,剩余的数字,它们可以去的左侧或右侧。 182 00:12:26,130 --> 00:12:31,580 这似乎很难,如果我把第一,然后一切都去左边, 183 00:12:31,580 --> 00:12:35,080 但如果我把7,有些事情是可以走左边,有些事情可以去正确的。 184 00:12:35,080 --> 00:12:39,570 '3第一,我的意思是什么都可以去正确的。 185 00:12:39,570 --> 00:12:42,350 这是真的,你就必须把它作为, 186 00:12:42,350 --> 00:12:47,980 有多少东西可以去上了一个层次的树。 187 00:12:47,980 --> 00:12:50,420 出来是14,或您可以绘制所有的这些, 188 00:12:50,420 --> 00:12:54,650 然后你会得到14。 189 00:12:54,650 --> 00:13:01,120 >> 让我们再回到这里, 190 00:13:01,120 --> 00:13:03,510 非常酷,因为我们可以通过搜索“有序二叉树 191 00:13:03,510 --> 00:13:06,910 在一个非常类似的方式来寻找在一个排序的数组。 192 00:13:06,910 --> 00:13:10,120 要做到这一点,我们从根开始和工作的方式,在树 193 00:13:10,120 --> 00:13:13,440 向叶,检查每个节点的值与我们正在寻找的值。 194 00:13:13,440 --> 00:13:15,810 如果当前节点的值是小于该值,我们正在寻找, 195 00:13:15,810 --> 00:13:18,050 你去下一个节点的右孩子。 196 00:13:18,050 --> 00:13:20,030 否则,你去结点的左孩子。 197 00:13:20,030 --> 00:13:22,800 在某些时候,你会发现你正在寻找的价值,你会碰到一个空, 198 00:13:22,800 --> 00:13:28,520 的价值不是在树上。“ 199 00:13:28,520 --> 00:13:32,450 我要重绘我们面前的树,要花几秒钟。 200 00:13:32,450 --> 00:13:38,280 但是,我们想看看是否6,10,和1是在树中。 201 00:13:38,280 --> 00:13:49,180 因此,它是什么,7,9,3,6。好吧。 202 00:13:49,180 --> 00:13:52,730 你想看看这些数字,我们要查找6。 203 00:13:52,730 --> 00:13:55,440 这种算法是如何工作的? 204 00:13:55,440 --> 00:14:03,040 好了,我们也有一些到树的根指针。 205 00:14:03,040 --> 00:14:12,460 我们会去根说,这是价值相等的价值,我们正在寻找吗? 206 00:14:12,460 --> 00:14:15,000 因此,我们正在寻找6,所以它是不相等的。 207 00:14:15,000 --> 00:14:20,140 因此,我们继续前进,现在我们说,好了,所以6是小于7。 208 00:14:20,140 --> 00:14:23,940 这是否意味着我们想要去的左侧,我们要向右走? 209 00:14:23,940 --> 00:14:27,340 [学生]。 >>呀。 210 00:14:27,340 --> 00:14:33,340 这是明显更容易,所有你必须​​做的就是画一个可能的树节点 211 00:14:33,340 --> 00:14:37,760 然后你不知道不知道 - 而不是试图想在你的头上, 212 00:14:37,760 --> 00:14:40,020 没关系,如果它的不足,我去左边或走右边, 213 00:14:40,020 --> 00:14:43,030 只是在看这幅画,这是非常清楚的,我必须去左边 214 00:14:43,030 --> 00:14:47,700 如果此节点是大于我在寻找的值。 215 00:14:47,700 --> 00:14:52,600 所以,你去左边,现在我在3。 216 00:14:52,600 --> 00:14:57,770 我想 - 3是不到我在寻找的价值,这是6。 217 00:14:57,770 --> 00:15:03,420 所以,我们去正确的,现在我结束了在6, 218 00:15:03,420 --> 00:15:07,380 这是我要找的,所以我返回真值。 219 00:15:07,380 --> 00:15:15,760 我要寻找的下一个值是10。 220 00:15:15,760 --> 00:15:23,230 好吧。所以,现在,10 - 切断 - 要遵循的根本。 221 00:15:23,230 --> 00:15:27,670 如今,10个是要大于7,所以我想看看的权利。 222 00:15:27,670 --> 00:15:31,660 10我要到这里来,是要大于9, 223 00:15:31,660 --> 00:15:34,520 所以我想看看的权利。 224 00:15:34,520 --> 00:15:42,100 我来这里,但在这里,现在我在空。 225 00:15:42,100 --> 00:15:44,170 我该怎么做,如果我打空? 226 00:15:44,170 --> 00:15:47,440 [学生]:返回假的? >>呀。我没有找到10。 227 00:15:47,440 --> 00:15:49,800 1将是几乎相同的情况下, 228 00:15:49,800 --> 00:15:51,950 除了它只是要翻转,而不是寻找 229 00:15:51,950 --> 00:15:56,540 右侧向下,我要看看左侧。 230 00:15:56,540 --> 00:16:00,430 >> 现在,我认为我们真正的代码。 231 00:16:00,430 --> 00:16:04,070 这里的地方 - 打开CS50设备和导航用自己的方式, 232 00:16:04,070 --> 00:16:07,010 但你也可以做到这一点的空间。 233 00:16:07,010 --> 00:16:09,170 做到这一点的空间,这也可能是理想的, 234 00:16:09,170 --> 00:16:13,760 因为我们可以工作的空间。 235 00:16:13,760 --> 00:16:19,170 他说:“首先,我们需要一个新的类型定义一个包含int值的二进制树节点。 236 00:16:19,170 --> 00:16:21,400 使用的typedef以下的样板, 237 00:16:21,400 --> 00:16:24,510 创建一个新的类型定义为一个二进制树中的节点。 238 00:16:24,510 --> 00:16:27,930 如果你被卡住。 。 。 “等等,等等,等等。好。 239 00:16:27,930 --> 00:16:30,380 因此,让我们把这里的样板, 240 00:16:30,380 --> 00:16:41,630 typedef结构节点和节点。是啊,好吧。 241 00:16:41,630 --> 00:16:44,270 那么,什么样的领域,我们将要在我们的节点吗? 242 00:16:44,270 --> 00:16:46,520 [学生]:int,然后两个指针吗? 243 00:16:46,520 --> 00:16:49,700 >> int值,两个指针吗?我怎样写指针吗? 244 00:16:49,700 --> 00:16:58,440 [学生]结构。 >>我要放大是啊,所以结构节点离开, 245 00:16:58,440 --> 00:17:01,320 和结构节点*。 246 00:17:01,320 --> 00:17:03,460 请记住最后一次讨论, 247 00:17:03,460 --> 00:17:15,290 这是没有意义的,这是没有意义的, 248 00:17:15,290 --> 00:17:18,270 这是没有意义的。 249 00:17:18,270 --> 00:17:25,000 你需要的一切,以便确定这种递归结构。 250 00:17:25,000 --> 00:17:27,970 好了,所以这就是我们的树是怎么回事的样子。 251 00:17:27,970 --> 00:17:37,670 如果我们做了一个三叉树,然后一个节点可能看起来像B1,B2,结构节点* B3, 252 00:17:37,670 --> 00:17:43,470 其中b是一个分支 - 其实,我更听到它的左,中,右,但不管。 253 00:17:43,470 --> 00:17:55,610 我们关心的只是二进制,右,左。 254 00:17:55,610 --> 00:17:59,110 “现在,声明一个全局变量为根的树节点*。” 255 00:17:59,110 --> 00:18:01,510 因此,我们不打算这样做。 256 00:18:01,510 --> 00:18:08,950 为了使事情变得稍微更困难,更广义的, 257 00:18:08,950 --> 00:18:11,570 我们不会有一个全球性的节点变量。 258 00:18:11,570 --> 00:18:16,710 相反,在主,我们将宣布我们的所有节点的事情, 259 00:18:16,710 --> 00:18:20,500 这意味着,在下面,当我们开始运行 260 00:18:20,500 --> 00:18:23,130 包含函数和我们的插入功能, 261 00:18:23,130 --> 00:18:27,410 而不是我们的CONTAINS函数只是使用这一全球性的节点变量, 262 00:18:27,410 --> 00:18:34,280 我们将它作为参数树,我们希望它来处理。 263 00:18:34,280 --> 00:18:36,650 有全局变量应该使事情变得更容易。 264 00:18:36,650 --> 00:18:42,310 我们将让事情变得更糟糕。 265 00:18:42,310 --> 00:18:51,210 现在只需要一分钟左右的时间做这样的事情, 266 00:18:51,210 --> 00:18:57,690 内的主要你要创建这个树,这就是所有你想做的事。 267 00:18:57,690 --> 00:19:04,530 尝试和构造这棵树在您的主要功能。 268 00:19:42,760 --> 00:19:47,610 >> 好吧。所以,你甚至不必构建了树的整个方式。 269 00:19:47,610 --> 00:19:49,840 但是,任何人有什么我可以拉起来 270 00:19:49,840 --> 00:20:03,130 如何开始构建这样的树吗? 271 00:20:03,130 --> 00:20:08,080 [学生]:有人撞,试图摆脱。 272 00:20:08,080 --> 00:20:13,100 鲍登]的任何舒适与自己的树建设? 273 00:20:13,100 --> 00:20:15,520 [学生]:当然可以。它没有这样做。 >>这是正常的。我们就可以完成 - 274 00:20:15,520 --> 00:20:26,860 哦,你可以将它保存吗?万岁。 275 00:20:26,860 --> 00:20:32,020 所以,在这里,我们有 - 哦,我有点切断。 276 00:20:32,020 --> 00:20:34,770 我放大? 277 00:20:34,770 --> 00:20:37,730 缩放,滚动。 >>我有一个问题。 >>呀? 278 00:20:37,730 --> 00:20:44,410 [学生]:当你定义结构,是类的东西初始化到什么? 279 00:20:44,410 --> 00:20:47,160 [鲍登号>>好。所以,你必须初始化 - 280 00:20:47,160 --> 00:20:50,450 [鲍登号当你定义,或当你声明一个结构, 281 00:20:50,450 --> 00:20:55,600 未初始化默认情况下,它就像如果你声明一个int。 282 00:20:55,600 --> 00:20:59,020 这是完全一样的东西。这就像其各自的领域 283 00:20:59,020 --> 00:21:04,460 可以有一个垃圾的价值所在。 “和它可能的定义 - 定义了一个struct 284 00:21:04,460 --> 00:21:07,740 在一种方式,它初始化它们? 285 00:21:07,740 --> 00:21:13,200 波顿:是的。所以,快捷的初始化语法 286 00:21:13,200 --> 00:21:18,660 是怎么回事的样子 - 287 00:21:18,660 --> 00:21:22,200 有两种方法,我们可以做到这一点。我认为,我们应该编译它 288 00:21:22,200 --> 00:21:25,840 以确保锵也这样做了。 289 00:21:25,840 --> 00:21:28,510 参数顺序的结构, 290 00:21:28,510 --> 00:21:32,170 你把这些花括号内的参数的顺序。 291 00:21:32,170 --> 00:21:35,690 所以,如果你想要初始化它9空,然后右边是空的, 292 00:21:35,690 --> 00:21:41,570 这将是9,NULL,NULL。 293 00:21:41,570 --> 00:21:47,890 另一种方法是,编辑器不喜欢这种语法, 294 00:21:47,890 --> 00:21:50,300 认为我想要一个新的块, 295 00:21:50,300 --> 00:22:01,800 但选择是一样的东西 - 296 00:22:01,800 --> 00:22:04,190 这里,我把它放在一个新行。 297 00:22:04,190 --> 00:22:09,140 你可以明确地说,我忘了确切的语法。 298 00:22:09,140 --> 00:22:13,110 所以,你可以明确地解决他们的名字,并说, 299 00:22:13,110 --> 00:22:21,570 c或。值= 9,左= NULL。 300 00:22:21,570 --> 00:22:24,540 我猜这些需要逗号。 301 00:22:24,540 --> 00:22:29,110 右= NULL,所以这样一来,你不这样做 302 00:22:29,110 --> 00:22:33,780 确实需要知道的结构顺序, 303 00:22:33,780 --> 00:22:36,650 当你读这篇文章,它更明确 304 00:22:36,650 --> 00:22:41,920 什么价值被初始化。 305 00:22:41,920 --> 00:22:44,080 >> 这种情况发生的事情,是一个 - 306 00:22:44,080 --> 00:22:49,100 因此,在大多数情况下,C + +是一个C的超集 307 00:22:49,100 --> 00:22:54,160 你可以把C代码,将其移动到C + +,和它应该编译。 308 00:22:54,160 --> 00:22:59,570 这是一个C + +不支持的事情,这样的人往往不这样做。 309 00:22:59,570 --> 00:23:01,850 我不知道如果这是唯一的原因,人们往往不这样做, 310 00:23:01,850 --> 00:23:10,540 但需要的情况下,我需要使用C + +,所以我不能使用此工作。 311 00:23:10,540 --> 00:23:14,000 另一个例子的东西,不与C + +是 312 00:23:14,000 --> 00:23:16,940 如何malloc返回一个“无效*,”从技术上说, 313 00:23:16,940 --> 00:23:20,200 但你可以说的char * x = malloc的什么, 314 00:23:20,200 --> 00:23:22,840 它会自动转换为char *。 315 00:23:22,840 --> 00:23:25,450 该自动转换不会发生在C + +。 316 00:23:25,450 --> 00:23:28,150 这将无法编译,你会明确地说 317 00:23:28,150 --> 00:23:34,510 是char *,malloc的,不管结果如何,将它转换为一个char *。 318 00:23:34,510 --> 00:23:37,270 不会有太多的事情,C和C + +不同意, 319 00:23:37,270 --> 00:23:40,620 但这些都是两个。 320 00:23:40,620 --> 00:23:43,120 因此,我们将用这个语法。 321 00:23:43,120 --> 00:23:46,150 但是,即使我们没有去与语法, 322 00:23:46,150 --> 00:23:49,470 是什么 - 可能是错的吗? 323 00:23:49,470 --> 00:23:52,170 [学生]:我不需要取消对它的引用? >>呀。 324 00:23:52,170 --> 00:23:55,110 请记住,箭头有一个隐含的间接引用, 325 00:23:55,110 --> 00:23:58,230 所以当我们只是处理与结构, 326 00:23:58,230 --> 00:24:04,300 我们要使用的。在一个领域内的结构。 327 00:24:04,300 --> 00:24:07,200 我们想要做的唯一的一次是,当我们使用箭头 - 328 00:24:07,200 --> 00:24:13,450 ,箭头相当于 - 329 00:24:13,450 --> 00:24:17,020 这将意味着什么,如果我用箭头。 330 00:24:17,020 --> 00:24:24,600 所有的箭头表示,取消引用此,现在我在一个结构,我可以得到该领域。 331 00:24:24,600 --> 00:24:28,040 要么领域直接或间接引用,并获得字段 - 332 00:24:28,040 --> 00:24:30,380 我想这应该是价值。 333 00:24:30,380 --> 00:24:33,910 但是,我在这里只是一个结构,而不是一个结构的指针来处理, 334 00:24:33,910 --> 00:24:38,780 所以我不能使用的箭头。 335 00:24:38,780 --> 00:24:47,510 但是,这样的事情我们可以做的所有节点上。 336 00:24:47,510 --> 00:24:55,790 哦,我的上帝。 337 00:24:55,790 --> 00:25:09,540 这是6,7,和3。 338 00:25:09,540 --> 00:25:16,470 然后我们就可以在我们的树,设立了分公司,我们可以有7个 - 339 00:25:16,470 --> 00:25:21,650 我们可以有,其左应指向3。 340 00:25:21,650 --> 00:25:25,130 那么,如何才能做到这一点呢? 341 00:25:25,130 --> 00:25:29,320 [学生,不知所云] >>呀。节点3的地址, 342 00:25:29,320 --> 00:25:34,170 ,如果你没有地址,那么就无法编译。 343 00:25:34,170 --> 00:25:38,190 但要记住,这些都是到下一个节点的指针。 344 00:25:38,190 --> 00:25:44,930 正确的应该点到9, 345 00:25:44,930 --> 00:25:53,330 3至6点。 346 00:25:53,330 --> 00:25:58,480 我认为这是所有设置。有任何意见或问题? 347 00:25:58,480 --> 00:26:02,060 [学生,不知所云]根正在为7。 348 00:26:02,060 --> 00:26:08,210 我们只能说节点* = 349 00:26:08,210 --> 00:26:14,160 或根,=&node7的。 350 00:26:14,160 --> 00:26:20,730 >> 对于我们的目的,我们将要处理的插入, 351 00:26:20,730 --> 00:26:25,490 所以,我们将要编写一个函数插入到这个二叉树 352 00:26:25,490 --> 00:26:34,230 并插入不可避免地会调用malloc来创建一个新的节点,这棵树。 353 00:26:34,230 --> 00:26:36,590 因此,事情会变得混乱的事实,有些节点 354 00:26:36,590 --> 00:26:38,590 当前堆栈上 355 00:26:38,590 --> 00:26:43,680 与其他节点要结束的堆,当我们插入。 356 00:26:43,680 --> 00:26:47,640 这是完全有效的,但唯一的原因 357 00:26:47,640 --> 00:26:49,600 我们能够做到这一点的堆栈 358 00:26:49,600 --> 00:26:51,840 是因为它是一个人为的例子,我们知道 359 00:26:51,840 --> 00:26:56,360 树应该被构造为7,3,6,9。 360 00:26:56,360 --> 00:27:02,970 如果我们不具备这一点,那么我们就没有对malloc摆在首位。 361 00:27:02,970 --> 00:27:06,160 正如我们将看到的晚了一点,我们应该malloc'ing。 362 00:27:06,160 --> 00:27:08,570 现在它是完全合理的,放在堆栈中, 363 00:27:08,570 --> 00:27:14,750 但让我们改变一个malloc实现。 364 00:27:14,750 --> 00:27:17,160 因此,这些现在是这样的 365 00:27:17,160 --> 00:27:24,240 的节点* node9 = malloc的(如sizeof(节点))。 366 00:27:24,240 --> 00:27:28,040 现在,我们将不得不做我们的检查。 367 00:27:28,040 --> 00:27:34,010 (node9 == NULL) - 我不想 - 368 00:27:34,010 --> 00:27:40,950 返回1,那么我们就可以做node9因为现在它是一个指针, 369 00:27:40,950 --> 00:27:45,300 值= 6,node9的左= NULL, 370 00:27:45,300 --> 00:27:48,930 node9 - > = NULL, 371 00:27:48,930 --> 00:27:51,410 我们将要做到这一点,每个节点。 372 00:27:51,410 --> 00:27:57,490 所以,让我们把它里面的一个单独的函数。 373 00:27:57,490 --> 00:28:00,620 让我们叫该节点* build_node, 374 00:28:00,620 --> 00:28:09,050 这是有点类似的API,我们提供的霍夫曼编码。 375 00:28:09,050 --> 00:28:12,730 我们为您提供的初始化函数的树 376 00:28:12,730 --> 00:28:20,520 拆解为这些树木和森林相同的“功能”。 377 00:28:20,520 --> 00:28:22,570 >> 所以,在这里我们将有一个初始化函数 378 00:28:22,570 --> 00:28:25,170 只是为我们建立一个节点。 379 00:28:25,170 --> 00:28:29,320 它看起来几乎完全一样这是怎么回事。 380 00:28:29,320 --> 00:28:32,230 我我什至会偷懒,不改变的变量名, 381 00:28:32,230 --> 00:28:34,380 即使node9没有任何意义了。 382 00:28:34,380 --> 00:28:38,610 哦,,我想node9的价值不应该被6。 383 00:28:38,610 --> 00:28:42,800 现在我们可以回到node9。 384 00:28:42,800 --> 00:28:49,550 在这里,我们应该返回null。 385 00:28:49,550 --> 00:28:52,690 每个人都同意,构建一个节点的功能吗? 386 00:28:52,690 --> 00:28:59,780 所以,现在我们可以直接调用的任何节点,建立与给定值和空指针。 387 00:28:59,780 --> 00:29:09,750 现在,我们可以调用,我们可以做节点* node9 = build_node(9)。 388 00:29:09,750 --> 00:29:25,810 让我们做。 。 。 389 00:29:25,810 --> 00:29:33,980 6,3,7,6,3,7。 390 00:29:33,980 --> 00:29:39,330 现在我们要设置相同的指针, 391 00:29:39,330 --> 00:29:42,470 但现在一切都已经在指针 392 00:29:42,470 --> 00:29:48,480 因此不再需要的地址。 393 00:29:48,480 --> 00:29:56,300 好吧。那么,什么是我想要做的最后一件事吗? 394 00:29:56,300 --> 00:30:03,850 有一个错误检查,我不这样做。 395 00:30:03,850 --> 00:30:06,800 什么构建节点回报吗? 396 00:30:06,800 --> 00:30:11,660 [学生,不知所云] >>呀。如果malloc失败,它会返回null。 397 00:30:11,660 --> 00:30:16,460 所以,我要在这里懒洋洋地把它放下,而不是做各自的条件。 398 00:30:16,460 --> 00:30:22,320 如果(node9 == NULL,或者 - 甚至更简单, 399 00:30:22,320 --> 00:30:28,020 这相当于只是如果不node9。 400 00:30:28,020 --> 00:30:38,310 因此,如果不node9,或不node6,或没有节点3,或不node7,返回1。 401 00:30:38,310 --> 00:30:42,850 也许我们应该打印的malloc失败,或某事。 402 00:30:42,850 --> 00:30:46,680 [学生]:是虚假等于NULL作为吗? 403 00:30:46,680 --> 00:30:51,290 鲍登任何零值是假的。 404 00:30:51,290 --> 00:30:53,920 因此,null是一个零值。 405 00:30:53,920 --> 00:30:56,780 零是零值。 False是一个零值。 406 00:30:56,780 --> 00:31:02,130 任何 - 几乎只有2个零值是空的,零, 407 00:31:02,130 --> 00:31:07,900 假的就是哈希值被定义为“0”。 408 00:31:07,900 --> 00:31:13,030 这也适用于我们声明了全局变量。 409 00:31:13,030 --> 00:31:17,890 如果我们确实有节点*的根在这里, 410 00:31:17,890 --> 00:31:24,150 - 有关全局变量是很好的事情,他们总是有一个初始值。 411 00:31:24,150 --> 00:31:27,500 这是不正确的功能,在这里, 412 00:31:27,500 --> 00:31:34,870 如果我们有,像,节点*节点x。 413 00:31:34,870 --> 00:31:37,380 我们不知道x.value,x.whatever, 414 00:31:37,380 --> 00:31:40,700 或者我们也可以打印出来,他们可以是任意的。 415 00:31:40,700 --> 00:31:44,980 这是不正确的全局变量。 416 00:31:44,980 --> 00:31:47,450 所以的节点根或节点x。 417 00:31:47,450 --> 00:31:53,410 默认情况下,这是全球的一切,如果没有显式初始化为某个值, 418 00:31:53,410 --> 00:31:57,390 具有零值作为其值。 419 00:31:57,390 --> 00:32:01,150 节点*根,所以在这里,我们没有显式初始化它的任何事情, 420 00:32:01,150 --> 00:32:06,350 所以它的默认值将是空的,这是零值的指针。 421 00:32:06,350 --> 00:32:11,870 默认的x的值将表示x.value为零, 422 00:32:11,870 --> 00:32:14,260 x.left为空,是空x.right。 423 00:32:14,260 --> 00:32:21,070 所以,因为它是一个结构,该结构中的所有领域的零值。 424 00:32:21,070 --> 00:32:24,410 我们并不需要使用,在这里,虽然。 425 00:32:24,410 --> 00:32:27,320 [学生]比其他变量的结构是不同的,和其它变量 426 00:32:27,320 --> 00:32:31,400 垃圾值,这些都是零? 427 00:32:31,400 --> 00:32:36,220 [鲍登其他值。因此,在x,x将是零。 428 00:32:36,220 --> 00:32:40,070 如果它在全球范围内,它有一个初始值。 “好了。 429 00:32:40,070 --> 00:32:48,950 鲍登无论是初始值你给或零。 430 00:32:48,950 --> 00:32:53,260 我认为所有这一切负责。 431 00:32:53,260 --> 00:32:58,390 >> 好吧。所以接下来的部分是问, 432 00:32:58,390 --> 00:33:01,260 “现在,我们要编写一个函数调用包含 433 00:33:01,260 --> 00:33:04,930 布尔的原型包含的int值。“ 434 00:33:04,930 --> 00:33:08,340 我们不打算做布尔包含的int值。 435 00:33:08,340 --> 00:33:15,110 我们的原型看起来像 436 00:33:15,110 --> 00:33:22,380 包含布尔(int值。 437 00:33:22,380 --> 00:33:24,490 然后,我们也将传递给它的树 438 00:33:24,490 --> 00:33:28,870 它应该被检查,看它是否具有该值。 439 00:33:28,870 --> 00:33:38,290 因此,节点树)。好吧。 440 00:33:38,290 --> 00:33:44,440 然后,我们可以把它喜欢的东西, 441 00:33:44,440 --> 00:33:46,090 也许我们会想printf或什么的。 442 00:33:46,090 --> 00:33:51,040 包含6,我们的根。 443 00:33:51,040 --> 00:33:54,300 这应该返回一个或真, 444 00:33:54,300 --> 00:33:59,390 而包含5根应该返回false。 445 00:33:59,390 --> 00:34:02,690 因此,需要实现这一点。 446 00:34:02,690 --> 00:34:06,780 你可以做到这一点的迭代或递归。 447 00:34:06,780 --> 00:34:09,739 的方式,我们已经设置的东西是美好的事情, 448 00:34:09,739 --> 00:34:12,300 它本身的递归解决方案更容易 449 00:34:12,300 --> 00:34:14,719 比全局变量的方式。 450 00:34:14,719 --> 00:34:19,750 因为如果我们只是有包含的int值,那么我们就没有办法搜索子树。 451 00:34:19,750 --> 00:34:24,130 我们就必须有一个单独的辅助函数,递归我们的子树。 452 00:34:24,130 --> 00:34:29,610 但因为我们已经改变了它的树作为参数, 453 00:34:29,610 --> 00:34:32,760 它应该一直摆在首位, 454 00:34:32,760 --> 00:34:35,710 现在我们可以递归更容易。 455 00:34:35,710 --> 00:34:38,960 因此,迭代或递归的,我们就去了两种, 456 00:34:38,960 --> 00:34:46,139 但我们会看到,递归端起来是很容易的。 457 00:34:59,140 --> 00:35:02,480 好吧。有没有人有什么我们可以使用吗? 458 00:35:02,480 --> 00:35:12,000 >> [学生]:我有一个迭代的解决方案。 >>所有权利,迭代。 459 00:35:12,000 --> 00:35:16,030 好吧,这看起来不错。 460 00:35:16,030 --> 00:35:18,920 所以,想通过它我们走? 461 00:35:18,920 --> 00:35:25,780 [学生]:当然可以。所以我设置一个临时变量来获得的第一个节点树。 462 00:35:25,780 --> 00:35:28,330 然后我就通过,而温度不等于空循环, 463 00:35:28,330 --> 00:35:31,700 因此,虽然仍然在树中,我猜。 464 00:35:31,700 --> 00:35:35,710 并且如果该值是相等的值,temp被指向 465 00:35:35,710 --> 00:35:37,640 然后它返回该值。 466 00:35:37,640 --> 00:35:40,210 否则,它会检查,如果是上的右侧或左侧。 467 00:35:40,210 --> 00:35:43,400 如果你有机会的情况下,有没有更多的树, 468 00:35:43,400 --> 00:35:47,330 那么它的回报 - 退出循环,返回false。 469 00:35:47,330 --> 00:35:52,190 鲍登]好吧。因此,这似乎不错。 470 00:35:52,190 --> 00:35:58,470 在任何问题上有任何人有任何意见? 471 00:35:58,470 --> 00:36:02,400 我没有在所有的正确意见。 472 00:36:02,400 --> 00:36:11,020 有一件事我们可以做的就是这个家伙。 473 00:36:11,020 --> 00:36:21,660 哦,这是要去一个小稍长。 474 00:36:21,660 --> 00:36:33,460 我会解决这个问题了。好吧。 475 00:36:33,460 --> 00:36:37,150 >> 每个人都应该还记得三元工作。 476 00:36:37,150 --> 00:36:38,610 有肯定是测验在过去 477 00:36:38,610 --> 00:36:41,170 给你一个三元运算符的功能, 478 00:36:41,170 --> 00:36:45,750 说,翻译,做一些不使用三元。 479 00:36:45,750 --> 00:36:49,140 所以这是一个很常见的情况时,我会觉得使用三元, 480 00:36:49,140 --> 00:36:54,610 其中,如果某些条件设置一个变量的东西, 481 00:36:54,610 --> 00:36:58,580 其他设置相同的变量别的东西。 482 00:36:58,580 --> 00:37:03,390 这件事情,这样的事情很经常可以转化为 483 00:37:03,390 --> 00:37:14,420 在那里设置该变量 - 或者说,好了,这是真的吗?然后,否则这一点。 484 00:37:14,420 --> 00:37:18,550 [学生]:第一个是,如果真实的,对不对? 485 00:37:18,550 --> 00:37:25,570 鲍登]是啊。我总是看它的方式是,温度大于等于温度值, 486 00:37:25,570 --> 00:37:30,680 然后,否则这一点。问一个问题。 487 00:37:30,680 --> 00:37:35,200 它更大的吗?然后做的第一件事。否则做的第二件事情。 488 00:37:35,200 --> 00:37:41,670 我几乎总是 - 结肠,我只是 - 我的头,我读别的。 489 00:37:41,670 --> 00:37:47,180 >> 有没有人有一个递归的解决方案吗? 490 00:37:47,180 --> 00:37:49,670 好吧。这一次,我们要 - 它可能已经是巨大的, 491 00:37:49,670 --> 00:37:53,990 但我们要使其更好。 492 00:37:53,990 --> 00:37:58,720 这几乎是完全相同的想法。 493 00:37:58,720 --> 00:38:03,060 好,只是,你想解释一下吗? 494 00:38:03,060 --> 00:38:08,340 [学生]:当然可以。因此,我们确定该树不为空,第一, 495 00:38:08,340 --> 00:38:13,380 因为如果树是空的,那么它会返回false,因为我们还没有找到它。 496 00:38:13,380 --> 00:38:19,200 如果还是有一棵树,我们进入 - 我们首先检查该值是当前节点。 497 00:38:19,200 --> 00:38:23,740 如果是,则返回true,如果没有,我们递归向左或向右。 498 00:38:23,740 --> 00:38:25,970 这听起来是适当的吗? >>嗯,嗯。 (协议) 499 00:38:25,970 --> 00:38:33,880 所以注意到这几乎是 - 结构非常相似,迭代求解。 500 00:38:33,880 --> 00:38:38,200 只是,而不是递归的,我们有一个while循环。 501 00:38:38,200 --> 00:38:40,840 而基地的情况下,这里的树不等于空 502 00:38:40,840 --> 00:38:44,850 的条件下,我们爆发出的while循环。 503 00:38:44,850 --> 00:38:50,200 他们是非常相似的。但是,我们要进一步采取这一步。 504 00:38:50,200 --> 00:38:54,190 现在,我们做同样的事情在这里。 505 00:38:54,190 --> 00:38:57,680 请注意,我们正在返回同样的事情在这些线路, 506 00:38:57,680 --> 00:39:00,220 除了一个参数是不同的。 507 00:39:00,220 --> 00:39:07,950 因此,我们要到一个三元。 508 00:39:07,950 --> 00:39:13,790 我打选项的东西,它的象征。好吧。 509 00:39:13,790 --> 00:39:21,720 因此,我们将返回包含。 510 00:39:21,720 --> 00:39:28,030 这是多行,好,放大它。 511 00:39:28,030 --> 00:39:31,060 通常情况下,作为一个文体的事情,我不认为很多人 512 00:39:31,060 --> 00:39:38,640 加一个空格后的箭头,但我想,如果你是一致的,它的罚款。 513 00:39:38,640 --> 00:39:44,320 如果值是小于树的价值,我们希望在树上左递归的, 514 00:39:44,320 --> 00:39:53,890 否则,我们要递归树权。 515 00:39:53,890 --> 00:39:58,610 所以这是第一个步骤,使这个看起来小一些。 516 00:39:58,610 --> 00:40:02,660 这个看起来小一些的第二步 - 517 00:40:02,660 --> 00:40:09,150 我们可以将多行。 518 00:40:09,150 --> 00:40:16,500 好吧。使它看起来更小的第二步是在这里, 519 00:40:16,500 --> 00:40:25,860 返回值等于树的值,或包含什么。 520 00:40:25,860 --> 00:40:28,340 >> 这是一个重要的事情。 521 00:40:28,340 --> 00:40:30,860 我不知道,如果他在课堂上说,它明确, 522 00:40:30,860 --> 00:40:34,740 但它被称为短路的评价。 523 00:40:34,740 --> 00:40:41,060 这里的想法是价值==树价值。 524 00:40:41,060 --> 00:40:49,960 如果这是真的,那么这是真实的,我们要'或',无论是在这里。 525 00:40:49,960 --> 00:40:52,520 因此,无论是在这里,甚至没有考虑, 526 00:40:52,520 --> 00:40:55,070 整个表达式将返回是什么? 527 00:40:55,070 --> 00:40:59,430 [学生]:真? >>是的,因为真实的东西, 528 00:40:59,430 --> 00:41:04,990 用OR - 或真或运算与任何必然是真实的。 529 00:41:04,990 --> 00:41:08,150 因此,只要我们看到的返回值= tree值, 530 00:41:08,150 --> 00:41:10,140 我们只是返回true。 531 00:41:10,140 --> 00:41:15,710 甚至不打算进一步递归包含了就行了。 532 00:41:15,710 --> 00:41:20,980 我们可以采取这一步。 533 00:41:20,980 --> 00:41:29,490 返回树不等于空,所有的一切。 534 00:41:29,490 --> 00:41:32,650 它做了一个在线的功能。 535 00:41:32,650 --> 00:41:36,790 这也是一个例子短路评价。 536 00:41:36,790 --> 00:41:40,680 但现在,它也是同样的想法 - 537 00:41:40,680 --> 00:41:47,320 而不是 - 所以,如果树不等于空 - 或者说,好, 538 00:41:47,320 --> 00:41:49,580 如果树不等于空,这是不好的情况下, 539 00:41:49,580 --> 00:41:54,790 如果树等于null,那么第一个条件是假的。 540 00:41:54,790 --> 00:42:00,550 所以假“与”与什么将是什么? 541 00:42:00,550 --> 00:42:04,640 [学生]假。 >>呀。这是短路评价的另一半, 542 00:42:04,640 --> 00:42:10,710 如果树不等于空,然后我们都不会,甚至去的地方 - 543 00:42:10,710 --> 00:42:14,930 独木等于空,那么我们就不会做价值==树价值。 544 00:42:14,930 --> 00:42:17,010 我们只是要立即返回false。 545 00:42:17,010 --> 00:42:20,970 这是非常重要的,因为如果没有短路求值, 546 00:42:20,970 --> 00:42:25,860 那么,如果树不等于空,这第二个条件是要赛格故障, 547 00:42:25,860 --> 00:42:32,510 因为树>的值被提领空。 548 00:42:32,510 --> 00:42:40,490 所以,就是这样。这一点 - 一旦过了转移。 549 00:42:40,490 --> 00:42:44,840 这是一个很常见的事情,这个没有这一行, 550 00:42:44,840 --> 00:42:49,000 但它是一个共同的东西的条件下,也许不正确的, 551 00:42:49,000 --> 00:42:59,380 但如果(树!= NULL,和树>的值==值),做任何事情。 552 00:42:59,380 --> 00:43:01,560 这是一个非常常见的情况,在那里,而不必 553 00:43:01,560 --> 00:43:06,770 要打破这个分为两个中频,在那里一样,是树空? 554 00:43:06,770 --> 00:43:11,780 好吧,这不是空的,所以现在是树的值等于值吗?做到这一点。 555 00:43:11,780 --> 00:43:17,300 相反,这种情况下,这将永远段错误 556 00:43:17,300 --> 00:43:21,220 因为它会破坏,如果发生这种情况是空的。 557 00:43:21,220 --> 00:43:24,000 嗯,我想,如果你的树是完全无效的指针,它仍然可以赛格故障, 558 00:43:24,000 --> 00:43:26,620 但它不能赛格故障,如果树是空的。 559 00:43:26,620 --> 00:43:32,900 如果是空的,这将打破之前你曾经解除引用的指针摆在首位。 560 00:43:32,900 --> 00:43:35,000 [学生]:这是所谓的懒惰的评价吗? 561 00:43:35,000 --> 00:43:40,770 >> [鲍登]懒惰的评价是一个独立的东西。 562 00:43:40,770 --> 00:43:49,880 懒惰的评价更像是你要求的值, 563 00:43:49,880 --> 00:43:54,270 你问计算出一个数值,种,但你并不需要它立即。 564 00:43:54,270 --> 00:43:59,040 所以,直到你真正需要它,它不评估。 565 00:43:59,040 --> 00:44:03,920 这是不完全一样的东西,但在霍夫曼的pset, 566 00:44:03,920 --> 00:44:06,520 它说,“懒洋洋”的编写。 567 00:44:06,520 --> 00:44:08,670 我们这样做的原因是因为我们实际上是在缓冲写 - 568 00:44:08,670 --> 00:44:11,820 我们不希望在同一时间写的各个位, 569 00:44:11,820 --> 00:44:15,450 或单个字节的时间,而不是要得到一个块的字节。 570 00:44:15,450 --> 00:44:19,270 然后,一旦我们有一个块的字节,然后我们将它写出来。 571 00:44:19,270 --> 00:44:22,640 即使你问它来写 - FWRITE和fread做同样的事情。 572 00:44:22,640 --> 00:44:26,260 他们缓冲的读取和写入操作。 573 00:44:26,260 --> 00:44:31,610 即使你要求它立即写入,它可能不会。 574 00:44:31,610 --> 00:44:34,540 你不能确定的东西都将被写入 575 00:44:34,540 --> 00:44:37,540 直到你调用hfclose或不管它是什么, 576 00:44:37,540 --> 00:44:39,620 然后说,好吧,我关闭我的文件, 577 00:44:39,620 --> 00:44:43,450 这意味着更好,我写的一切,但我没有写。 578 00:44:43,450 --> 00:44:45,770 它不需要编写了 579 00:44:45,770 --> 00:44:49,010 直到您关闭该文件,然后需要的地方。 580 00:44:49,010 --> 00:44:56,220 所以,这只是什么懒 - 等待,直到它发生的。 581 00:44:56,220 --> 00:44:59,990 - 以51你将进入更详细, 582 00:44:59,990 --> 00:45:05,470 因为OCaml和一切,一切都在51递归。 583 00:45:05,470 --> 00:45:08,890 有没有迭代的解决方案,基本上。 584 00:45:08,890 --> 00:45:11,550 一切都是递归和懒惰的评价 585 00:45:11,550 --> 00:45:14,790 很多情况下是非常重要的 586 00:45:14,790 --> 00:45:19,920 在那里,如果你没有懒洋洋地评估,这将意味着 - 587 00:45:19,920 --> 00:45:24,760 该示例是流,这是无限长。 588 00:45:24,760 --> 00:45:30,990 从理论上讲,你能想到的自然数为1-2-3-4-5-6-7流, 589 00:45:30,990 --> 00:45:33,090 所以,懒洋洋地评估事情的罚款。 590 00:45:33,090 --> 00:45:37,210 如果我说我想要的第十号,然后我就可以评估的10号。 591 00:45:37,210 --> 00:45:40,300 如果我想百分之一的数量,然后我就可以评估到百分之数量。 592 00:45:40,300 --> 00:45:46,290 没有懒惰的评价,那么它会尝试立即评估所有的数字。 593 00:45:46,290 --> 00:45:50,000 您正在评估无限多的数字,这是根本不可能的。 594 00:45:50,000 --> 00:45:52,080 因此,有很多情况下,懒惰的评价 595 00:45:52,080 --> 00:45:57,840 得到的东西的工作是必不可少的。 596 00:45:57,840 --> 00:46:05,260 >> 现在,我们要编写INSERT插入将是 597 00:46:05,260 --> 00:46:08,430 同样改变在其定义中。 598 00:46:08,430 --> 00:46:10,470 所以,现在它的布尔插入(int值)。 599 00:46:10,470 --> 00:46:23,850 我们要改变这种状况为bool插入(int值,节点树)。 600 00:46:23,850 --> 00:46:29,120 我们实际上会改变,再次一点,我们就会明白为什么。 601 00:46:29,120 --> 00:46:32,210 让我们继续前进build_node,只为它赫克, 602 00:46:32,210 --> 00:46:36,730 上面插入,所以我们没有写一个函数原型。 603 00:46:36,730 --> 00:46:42,450 这是一个暗示,你将要使用build_node在插入。 604 00:46:42,450 --> 00:46:49,590 好吧。 ,一分钟的时间。 605 00:46:49,590 --> 00:46:52,130 我想我保存的版本,如果你想拉, 606 00:46:52,130 --> 00:47:00,240 或者,至少,我现在这样。 607 00:47:00,240 --> 00:47:04,190 我想稍作休息时间,思考的逻辑插入, 608 00:47:04,190 --> 00:47:08,750 如果你无法想起来了。 609 00:47:08,750 --> 00:47:12,860 基本上,你将永远只能被插入的叶子。 610 00:47:12,860 --> 00:47:18,640 想,如果我插入,然后我不可避免地将要插入1 - 611 00:47:18,640 --> 00:47:21,820 我会改以黑色 - 我会在这里插入1。 612 00:47:21,820 --> 00:47:28,070 或者,如果我插入,我要在这里插入4。 613 00:47:28,070 --> 00:47:32,180 所以无论你做什么,你要插入的叶子。 614 00:47:32,180 --> 00:47:36,130 所有你必须​​做的是遍历树,直到你得到的节点 615 00:47:36,130 --> 00:47:40,890 这应该是节点的父节点,新节点的父节点, 616 00:47:40,890 --> 00:47:44,560 然后改变其向左或向右的指针,这取决于是否 617 00:47:44,560 --> 00:47:47,060 它是大于或小于当前节点。 618 00:47:47,060 --> 00:47:51,180 修改这个指针指向新节点。 619 00:47:51,180 --> 00:48:05,490 所以遍历树的叶点到新的节点。 620 00:48:05,490 --> 00:48:09,810 也觉得为什么会禁止这类情况之前, 621 00:48:09,810 --> 00:48:17,990 我构建二叉树,它是正确的 622 00:48:17,990 --> 00:48:19,920 如果你只看着一个单一的节点, 623 00:48:19,920 --> 00:48:24,830 但9左侧7,如果你遍历了所有的方式。 624 00:48:24,830 --> 00:48:29,770 所以在这种情况下这是不可能的,因为 - 625 00:48:29,770 --> 00:48:32,530 想插入的东西;(9)在第一个节点, 626 00:48:32,530 --> 00:48:35,350 我会看,我只是要到正确的。 627 00:48:35,350 --> 00:48:38,490 所以不管我做什么,如果我插入到叶, 628 00:48:38,490 --> 00:48:40,790 ,并使用合适的算法的叶, 629 00:48:40,790 --> 00:48:43,130 这将是不可能的,我插入9日至7左 630 00:48:43,130 --> 00:48:48,250 因为,只要我打7,我会去的权利。 631 00:48:59,740 --> 00:49:02,070 有没有人有东西开始? 632 00:49:02,070 --> 00:49:05,480 [学生]:我做的。 “当然可以。 633 00:49:05,480 --> 00:49:09,200 [学生,不知所云] 634 00:49:09,200 --> 00:49:14,390 [其他学生,不知所云] 635 00:49:14,390 --> 00:49:18,330 [鲍登的赞赏。好吧。要解释? 636 00:49:18,330 --> 00:49:20,690 >> [学生]因为我们知道,我们将 637 00:49:20,690 --> 00:49:24,060 新的节点,在树的结尾, 638 00:49:24,060 --> 00:49:28,070 我循环通过迭代树 639 00:49:28,070 --> 00:49:31,360 直到我得到了一个节点,指出为空。 640 00:49:31,360 --> 00:49:34,220 然后,我决定把它的右侧或左侧 641 00:49:34,220 --> 00:49:37,420 使用此变量,它告诉我把它放在哪里。 642 00:49:37,420 --> 00:49:41,850 然后,从本质上讲,我只是做,最后 - 643 00:49:41,850 --> 00:49:47,520 该临时结点,它是创造新的节点, 644 00:49:47,520 --> 00:49:50,770 无论是在左侧或右侧,这取决于什么值权。 645 00:49:50,770 --> 00:49:56,530 最后,我设置了新的节点值,其测试值。 646 00:49:56,530 --> 00:49:59,550 [鲍登]好了,所以我在这里看到一个问题。 647 00:49:59,550 --> 00:50:02,050 这是95%的方式存在的。 648 00:50:02,050 --> 00:50:07,550 一个问题,我看到,没有任何人看到一个问题吗? 649 00:50:07,550 --> 00:50:18,400 的情况下,他们跳出循环是什么? 650 00:50:18,400 --> 00:50:22,100 [学生]:如果temp是空的? >>呀。因此,如何跳出循环,是如果温度为空。 651 00:50:22,100 --> 00:50:30,220 但是,我该怎么办就在这里吗? 652 00:50:30,220 --> 00:50:35,410 我解引用的温度,这是不可避免的空。 653 00:50:35,410 --> 00:50:39,840 因此,其他的事情,你需要做的不只是跟踪,直到温度是空的, 654 00:50:39,840 --> 00:50:45,590 你要跟踪的父母在任何时候都。 655 00:50:45,590 --> 00:50:52,190 我们也希望*父节点,我想我们可以保持,空第一。 656 00:50:52,190 --> 00:50:55,480 这是要为根的树有怪异的行为, 657 00:50:55,480 --> 00:50:59,210 但我们会得到的。 658 00:50:59,210 --> 00:51:03,950 如果值是大于任何,然后TEMP =临时的权利。 659 00:51:03,950 --> 00:51:07,910 但在此之前我们做到这一点,父母温度。 660 00:51:07,910 --> 00:51:14,500 或者父母总是平等的温度吗?是这样呢? 661 00:51:14,500 --> 00:51:19,560 如果温度不为空,然后我要向下移动,不管是什么, 662 00:51:19,560 --> 00:51:24,030 temp是父节点。 663 00:51:24,030 --> 00:51:27,500 所以,家长会为temp,然后我谨温度下降。 664 00:51:27,500 --> 00:51:32,410 现在的温度是空的,但父母的事情是空的父。 665 00:51:32,410 --> 00:51:39,110 所以在这里,我不希望设置等于1。 666 00:51:39,110 --> 00:51:41,300 所以,我移动到右侧,因此,如果右= 1, 667 00:51:41,300 --> 00:51:45,130 我猜你也想这样做 - 668 00:51:45,130 --> 00:51:48,530 如果你移动到左边,你要设置等于0。 669 00:51:48,530 --> 00:51:55,950 否则,如果你移动到右侧。 670 00:51:55,950 --> 00:51:58,590 所以右侧= 0。如果右= 1, 671 00:51:58,590 --> 00:52:04,260 现在我们要父权指针newnode, 672 00:52:04,260 --> 00:52:08,520 否则,我们想使父左指针newnode。 673 00:52:08,520 --> 00:52:16,850 该问题吗? 674 00:52:16,850 --> 00:52:24,880 好吧。因此,这是我们的方式 - 好吧,其实不是这样做,而是 675 00:52:24,880 --> 00:52:29,630 我们一半预计您使用build_node。 676 00:52:29,630 --> 00:52:40,450 然后,如果newnode等于null,则返回false。 677 00:52:40,450 --> 00:52:44,170 就是这样。现在,这是我们希望你做什么。 678 00:52:44,170 --> 00:52:47,690 >> 这是工作人员解决方案做什么。 679 00:52:47,690 --> 00:52:52,360 我不同意这是“正确”的方式去了解它 680 00:52:52,360 --> 00:52:57,820 但是,这是完全没有问题的,它会工作。 681 00:52:57,820 --> 00:53:02,840 有一件事,这是一个有点古怪,现在是 682 00:53:02,840 --> 00:53:08,310 如果树为空,我们传递了一个空树。 683 00:53:08,310 --> 00:53:12,650 我想这取决于你如何定义传递一个空树的行为。 684 00:53:12,650 --> 00:53:15,490 我认为,如果你传递一个空树, 685 00:53:15,490 --> 00:53:17,520 然后插入值到一个空的树 686 00:53:17,520 --> 00:53:23,030 应该只返回一个唯一的价值是单个节点的树中。 687 00:53:23,030 --> 00:53:25,830 人们同意吗?你可以,如果你想, 688 00:53:25,830 --> 00:53:28,050 如果你传递一个空的树 689 00:53:28,050 --> 00:53:31,320 你想插入值,则返回false。 690 00:53:31,320 --> 00:53:33,830 它是由你来定义。 691 00:53:33,830 --> 00:53:38,320 要我说,然后做的第一件事 - 692 00:53:38,320 --> 00:53:40,720 好了,你打算这样做有问题,因为 693 00:53:40,720 --> 00:53:44,090 如果我们有一个全局指针的东西,它会更容易, 694 00:53:44,090 --> 00:53:48,570 但我们没有,所以,如果树是空的,有什么我们可以做的。 695 00:53:48,570 --> 00:53:50,960 我们就可以返回false。 696 00:53:50,960 --> 00:53:52,840 所以我要改变插入。 697 00:53:52,840 --> 00:53:56,540 我们在技术上可以只改变这一权利在这里, 698 00:53:56,540 --> 00:53:58,400 它是如何遍历的事情, 699 00:53:58,400 --> 00:54:04,530 但我要改变插入一个节点**树。 700 00:54:04,530 --> 00:54:07,510 双指针。 701 00:54:07,510 --> 00:54:09,710 这是什么意思呢? 702 00:54:09,710 --> 00:54:12,330 而不是处理的节点的指针, 703 00:54:12,330 --> 00:54:16,690 我要操作的东西是这样的指针。 704 00:54:16,690 --> 00:54:18,790 我要操纵这些指针。 705 00:54:18,790 --> 00:54:21,770 我要直接操纵指针。 706 00:54:21,770 --> 00:54:25,760 这是有道理的,因为,想想下来 - 707 00:54:25,760 --> 00:54:33,340 好了,现在这点为空。 708 00:54:33,340 --> 00:54:38,130 我想要做的是操作这个指针指向为NOT NULL。 709 00:54:38,130 --> 00:54:40,970 我想它指向我的新节点。 710 00:54:40,970 --> 00:54:44,870 如果我只是记录我的指针的指针, 711 00:54:44,870 --> 00:54:47,840 然后,我不需要跟踪的父指针。 712 00:54:47,840 --> 00:54:52,640 我就可以跟踪看,如果指针指向空, 713 00:54:52,640 --> 00:54:54,580 如果指针指向为null, 714 00:54:54,580 --> 00:54:57,370 将其更改为指向我想要的节点。 715 00:54:57,370 --> 00:55:00,070 我可以改变它,因为我有一个指针的指针。 716 00:55:00,070 --> 00:55:02,040 让我们来看看这个权利。 717 00:55:02,040 --> 00:55:05,470 实际上,你可以递归很容易地做到这一点。 718 00:55:05,470 --> 00:55:08,080 我们要做到这一点呢? 719 00:55:08,080 --> 00:55:10,980 是的,我们做的。 720 00:55:10,980 --> 00:55:16,790 >> 让我们来看看它递归。 721 00:55:16,790 --> 00:55:24,070 首先,什么是我们的基本情况又如何呢? 722 00:55:24,070 --> 00:55:29,140 几乎永远是我们的基本情况,但实际上,这是一种棘手的。 723 00:55:29,140 --> 00:55:34,370 首先第一件事情,如果(树== NULL) 724 00:55:34,370 --> 00:55:37,550 我想我们只是要返回false。 725 00:55:37,550 --> 00:55:40,460 树是空的,这是不同的。 726 00:55:40,460 --> 00:55:44,510 这就是指针到你的根指针为null 727 00:55:44,510 --> 00:55:48,360 这意味着你的根指针不存在。 728 00:55:48,360 --> 00:55:52,390 因此,在这里,如果我这样做 729 00:55:52,390 --> 00:55:55,760 节点* - 让我们只是重复。 730 00:55:55,760 --> 00:55:58,960 节点根= NULL, 731 00:55:58,960 --> 00:56:00,730 ,然后我就打电话给插入,做这样的事情, 732 00:56:00,730 --> 00:56:04,540 和根中插入4。 733 00:56:04,540 --> 00:56:06,560 因此,根,如果根是一个节点* 734 00:56:06,560 --> 00:56:11,170 然后与根将是一个节点**。 735 00:56:11,170 --> 00:56:15,120 这是有效的。在这种情况下,树,在这里, 736 00:56:15,120 --> 00:56:20,120 树不为空 - 或插入。 737 00:56:20,120 --> 00:56:24,630 在这里。树不空; *树为空,这是很好 738 00:56:24,630 --> 00:56:26,680 *树,因为如果是空的,那么我可以操纵它 739 00:56:26,680 --> 00:56:29,210 现在指向什么,我想它指向。 740 00:56:29,210 --> 00:56:34,750 但是,如果树是空的,这意味着我来到这里,说空。 741 00:56:34,750 --> 00:56:42,710 这没有任何意义。我不能做什么用的。 742 00:56:42,710 --> 00:56:45,540 如果树是空的,则返回false。 743 00:56:45,540 --> 00:56:48,220 所以,我基本上已经说了我们真正的基本情况是什么。 744 00:56:48,220 --> 00:56:50,580 那是什么打算? 745 00:56:50,580 --> 00:56:55,030 [学生,不知所云] 746 00:56:55,030 --> 00:57:00,000 波顿:是的。所以,如果(*树== NULL)。 747 00:57:00,000 --> 00:57:04,520 这涉及到的情况下在这里 748 00:57:04,520 --> 00:57:09,640 我的红色指针,如果指针,我很专注, 749 00:57:09,640 --> 00:57:12,960 我集中在这指针一样,现在我专注于这个指针。 750 00:57:12,960 --> 00:57:15,150 现在我专注于这个指针。 751 00:57:15,150 --> 00:57:18,160 所以,如果我的红色指针,这是我的节点** 752 00:57:18,160 --> 00:57:22,880 曾经是 - 如果*,我的红色指针,是以往任何时候都为空, 753 00:57:22,880 --> 00:57:28,470 这意味着,我在我专注于一个指针指向的情况下 - 754 00:57:28,470 --> 00:57:32,530 这是一个指针,属于一片叶子。 755 00:57:32,530 --> 00:57:41,090 我想改变这个指针指向我的新节点。 756 00:57:41,090 --> 00:57:45,230 快回来。 757 00:57:45,230 --> 00:57:56,490 我的newnode将是节点* N = build_node(值) 758 00:57:56,490 --> 00:58:07,300 那么n,如果n = NULL,则返回false。 759 00:58:07,300 --> 00:58:12,600 否则,我们要改变指针指向 760 00:58:12,600 --> 00:58:17,830 现在我们新建的节点。 761 00:58:17,830 --> 00:58:20,280 事实上,我们可以做到这一点。 762 00:58:20,280 --> 00:58:30,660 而不是说Ň,我们说* = *树的树。 763 00:58:30,660 --> 00:58:35,450 每个人都明白吗? ,处理指向指针的指针, 764 00:58:35,450 --> 00:58:40,750 我们可以改变空指针指向它们指向我们想要的东西。 765 00:58:40,750 --> 00:58:42,820 这是我们的基本情况。 766 00:58:42,820 --> 00:58:45,740 >> 现在,我们的复发,或我们的递归, 767 00:58:45,740 --> 00:58:51,430 将是非常相似,我们已经做了所有其他的递归。 768 00:58:51,430 --> 00:58:55,830 我们将要插入的值, 769 00:58:55,830 --> 00:58:59,040 现在我要再次使用三元,但我们的条件是什么要? 770 00:58:59,040 --> 00:59:05,180 它是什么,我们要寻找的决定,我们是否要向左走还是向右? 771 00:59:05,180 --> 00:59:07,760 让我们这样做在单独的步骤。 772 00:59:07,760 --> 00:59:18,850 (值)是什么? 773 00:59:18,850 --> 00:59:23,200 [学生]:这棵树的价值? 774 00:59:23,200 --> 00:59:27,490 鲍登所以请记住,我目前 - 775 00:59:27,490 --> 00:59:31,260 [学生,不知所云] 776 00:59:31,260 --> 00:59:34,140 [鲍登]是啊,所以就在这里,让我们说,这个绿色的箭头 777 00:59:34,140 --> 00:59:39,050 是什么树目前是一个例子,是一个指针,该指针。 778 00:59:39,050 --> 00:59:46,610 因此,这意味着我是一个​​指针,指向一个指针,指向3。 779 00:59:46,610 --> 00:59:48,800 两次解引用听起来不错。 780 00:59:48,800 --> 00:59:51,010 这是什么 - 怎么我做的是什么? 781 00:59:51,010 --> 00:59:53,210 [学生]:取消引用一次,然后做箭头? 782 00:59:53,210 --> 00:59:58,420 [鲍登](树)提领一次, - >值 783 00:59:58,420 --> 01:00:05,960 是想给我的价值,我间接指向的节点。 784 01:00:05,960 --> 01:00:11,980 所以我也可以写它** tree.value的,如果你喜欢。 785 01:00:11,980 --> 01:00:18,490 无论是工作的。 786 01:00:18,490 --> 01:00:26,190 如果是这样的话,那么我想打电话给插入与价值。 787 01:00:26,190 --> 01:00:32,590 什么是我更新的节点又如何呢? 788 01:00:32,590 --> 01:00:39,440 我想往左走,所以** tree.left的将是我的左手。 789 01:00:39,440 --> 01:00:41,900 我想这东西的指针 790 01:00:41,900 --> 01:00:44,930 所以,如果左边的结束是空指针, 791 01:00:44,930 --> 01:00:48,360 我可以修改它指向我的新节点。 792 01:00:48,360 --> 01:00:51,460 >> 其他情况下,可以是非常相似的。 793 01:00:51,460 --> 01:00:55,600 其实,我的三元现在。 794 01:00:55,600 --> 01:01:04,480 插入值,如果值<(**树)。值。 795 01:01:04,480 --> 01:01:11,040 然后我们要更新我们的**的左侧, 796 01:01:11,040 --> 01:01:17,030 否则,我们要更新我们的**的权利。 797 01:01:17,030 --> 01:01:22,540 [学生]:那拿到的指针的指针? 798 01:01:22,540 --> 01:01:30,940 鲍登 - ** tree.right是节点的明星。 799 01:01:30,940 --> 01:01:35,040 [学生,不知所云] >>呀。 800 01:01:35,040 --> 01:01:41,140 ** tree.right是这样的指针或什么的。 801 01:01:41,140 --> 01:01:45,140 因此,通过一个指向,这给了我我想要的 802 01:01:45,140 --> 01:01:50,090 那家伙的指针。 803 01:01:50,090 --> 01:01:54,260 [学生]:我们能不能​​走一遍,为什么我们使用的是两个指针吗? 804 01:01:54,260 --> 01:01:58,220 鲍登]是啊。所以 - 不,你可以,而且该解决方案之前 805 01:01:58,220 --> 01:02:04,540 一种方法做这件事而不做两个指针。 806 01:02:04,540 --> 01:02:08,740 你需要能够了解两个指针, 807 01:02:08,740 --> 01:02:11,660 这是一个清洁的解决方案。 808 01:02:11,660 --> 01:02:16,090 另外,请注意,会发生什么,如果我的树 - 809 01:02:16,090 --> 01:02:24,480 发生什么,如果我的根目录为空?在这里如果我这样做的情况下,会发生什么情况? 810 01:02:24,480 --> 01:02:30,540 因此,节点*根= NULL,插入4到与根。 811 01:02:30,540 --> 01:02:35,110 什么是根将是在此之后呢? 812 01:02:35,110 --> 01:02:37,470 [学生,不知所云] >>呀。 813 01:02:37,470 --> 01:02:41,710 根值是4。 814 01:02:41,710 --> 01:02:45,510 根左边的这个是空的,根本的权利是空的。 815 01:02:45,510 --> 01:02:49,490 的情况下,我们没有通过根地址, 816 01:02:49,490 --> 01:02:52,490 我们不能修改根。 817 01:02:52,490 --> 01:02:56,020 树 - 根为空的情况下, 818 01:02:56,020 --> 01:02:58,410 我们刚刚返回false。我们没有什么可以做的。 819 01:02:58,410 --> 01:03:01,520 我们不能插入到一个空的树节点。 820 01:03:01,520 --> 01:03:06,810 但现在我们可以到一个节点树,我们只是一个空的树。 821 01:03:06,810 --> 01:03:13,400 这通常是预期的方式,它应该工作。 822 01:03:13,400 --> 01:03:21,610 >> 此外,这是显着短于 823 01:03:21,610 --> 01:03:26,240 跟踪的父母,所以你遍历了所有的方式。 824 01:03:26,240 --> 01:03:30,140 现在,我有我的父母,我只是有我的父权的任何指针。 825 01:03:30,140 --> 01:03:35,640 相反,如果我们这样做迭代,它会是一个while循环同样的想法。 826 01:03:35,640 --> 01:03:38,100 但不是我的父指针处理, 827 01:03:38,100 --> 01:03:40,600 而不是我现在的指针的东西 828 01:03:40,600 --> 01:03:43,790 我直接修改指向我的新节点。 829 01:03:43,790 --> 01:03:46,090 我没有处理,无论是指向左边。 830 01:03:46,090 --> 01:03:48,810 我没有处理是否指向正确的。 831 01:03:48,810 --> 01:04:00,860 这只是不管这个指针,我将其设置为指向我的新节点。 832 01:04:00,860 --> 01:04:05,740 每个人都明白它是如何工作的? 833 01:04:05,740 --> 01:04:09,460 如果没有,为什么我们想这样做,这样一来, 834 01:04:09,460 --> 01:04:14,920 但至少,这个工程作为一个解决方案? 835 01:04:14,920 --> 01:04:17,110 [学生]:我们从哪里传回是真的吗? 836 01:04:17,110 --> 01:04:21,550 鲍登这很可能就在这里。 837 01:04:21,550 --> 01:04:26,690 如果我们正确地插入,则返回true。 838 01:04:26,690 --> 01:04:32,010 否则,在这里我们将要返回任何插入的回报。 839 01:04:32,010 --> 01:04:35,950 >> 和有关这个递归函数有什么特别呢? 840 01:04:35,950 --> 01:04:43,010 这是尾递归的,所以只要我们编译了一些优化, 841 01:04:43,010 --> 01:04:48,060 它会认识到,你将永远不会得到一个堆栈溢出, 842 01:04:48,060 --> 01:04:53,230 即使我们的树的高度1万或10万。 843 01:04:53,230 --> 01:04:55,630 [学生,不知所云] 844 01:04:55,630 --> 01:05:00,310 [鲍登]我认为它在短跑 - 优化级别 845 01:05:00,310 --> 01:05:03,820 需要被认可为一个尾递归。 846 01:05:03,820 --> 01:05:09,350 我认为它承认 - GCC和Clang的 847 01:05:09,350 --> 01:05:12,610 也有不同的含义的优化水平。 848 01:05:12,610 --> 01:05:17,870 我想说这是达绍2,为确保它会识别尾递归。 849 01:05:17,870 --> 01:05:27,880 但是,我们 - 你可以构建这样一个Fibonocci的例子或什么的。 850 01:05:27,880 --> 01:05:30,030 这是不容易的测试,因为它是难以建立 851 01:05:30,030 --> 01:05:32,600 这么大的一个二叉树。 852 01:05:32,600 --> 01:05:37,140 但是,是的,我认为这是达绍2, 853 01:05:37,140 --> 01:05:40,580 如果在编译时使用达绍2,它会寻找尾递归 854 01:05:40,580 --> 01:05:54,030 并优化了这一点。 855 01:05:54,030 --> 01:05:58,190 让我们回去 - 插入从字面上它需要的最后一件事。 856 01:05:58,190 --> 01:06:04,900 让我们回到在这里插入 857 01:06:04,900 --> 01:06:07,840 我们要去的地方,做同样的想法。 858 01:06:07,840 --> 01:06:14,340 它仍然有缺陷,不能够完全处理 859 01:06:14,340 --> 01:06:17,940 当根目录本身是空的,或在过去的项目是空的, 860 01:06:17,940 --> 01:06:20,060 但是,而不是处理与父母指针, 861 01:06:20,060 --> 01:06:27,430 让我们应用同样的逻辑,保持指针的指针。 862 01:06:27,430 --> 01:06:35,580 如果我们保持我们的节点**当前, 863 01:06:35,580 --> 01:06:37,860 而我们不需要跟踪了, 864 01:06:37,860 --> 01:06:47,190 但节点**当前和树。 865 01:06:47,190 --> 01:06:54,800 现在,我们的while循环将是*电流不等于空。 866 01:06:54,800 --> 01:07:00,270 不需要跟踪的父母了。 867 01:07:00,270 --> 01:07:04,180 不要需要跟踪的左边和右边。 868 01:07:04,180 --> 01:07:10,190 我会打电话给它温度,因为我们已经使用温度。 869 01:07:10,190 --> 01:07:17,200 好吧。所以,如果(值> *温度), 870 01:07:17,200 --> 01:07:24,010 (临时) - >右键 871 01:07:24,010 --> 01:07:29,250 TEMP =&(*温度) - >离开。 872 01:07:29,250 --> 01:07:32,730 而现在,在这一点上,这个while循环后, 873 01:07:32,730 --> 01:07:36,380 我只能这样做,因为也许它更容易比递归迭代想想, 874 01:07:36,380 --> 01:07:39,010 但这个while循环后, 875 01:07:39,010 --> 01:07:43,820 * temp是我们要改变的指针。 876 01:07:43,820 --> 01:07:48,960 >> 之前,我们的父母,我们想改变父母任何一方左或父权, 877 01:07:48,960 --> 01:07:51,310 但如果我们想改变家长的权利, 878 01:07:51,310 --> 01:07:54,550 *温度是父母的权利,我们可以直接改变它。 879 01:07:54,550 --> 01:08:05,860 所以在这里,我们可以做TEMP = newnode,这就是它。 880 01:08:05,860 --> 01:08:09,540 因此,通知,我们在这行代码。 881 01:08:09,540 --> 01:08:14,770 为了保持轨道是额外的努力在所有的父。 882 01:08:14,770 --> 01:08:18,689 在这里,如果我们只是一味地跟踪指针的指针, 883 01:08:18,689 --> 01:08:22,990 即使我们想摆脱现在所有这些大括号中, 884 01:08:22,990 --> 01:08:27,170 使它看起来更短。 885 01:08:27,170 --> 01:08:32,529 这现在是完全一样的解决方案, 886 01:08:32,529 --> 01:08:38,210 但更少的代码行。 887 01:08:38,210 --> 01:08:41,229 一旦你开始认识到这是一个有效的解决方案, 888 01:08:41,229 --> 01:08:43,529 它也更容易的原因有关,而不像,没关系, 889 01:08:43,529 --> 01:08:45,779 为什么我有这个标志的诠释权吗? 890 01:08:45,779 --> 01:08:49,290 这是什么意思呢?哦,这是表示 891 01:08:49,290 --> 01:08:51,370 我每次去正确的,我需要设置, 892 01:08:51,370 --> 01:08:53,819 否则,如果我向左走,我需要将其设置为0。 893 01:08:53,819 --> 01:09:04,060 在这里,我没有原因有关,它只是更容易思考的问题。 894 01:09:04,060 --> 01:09:06,710 有问题吗? 895 01:09:06,710 --> 01:09:16,290 [学生,不知所云] >>呀。 896 01:09:16,290 --> 01:09:23,359 好了,所以在最后一位 - 897 01:09:23,359 --> 01:09:28,080 我想一个快速和简单的函数,我们可以做的是, 898 01:09:28,080 --> 01:09:34,910 let's - 一起,我想尝试写一个包含功能 899 01:09:34,910 --> 01:09:38,899 不关心它是否是一个二叉搜索树。 900 01:09:38,899 --> 01:09:43,770 这包含函数应返回TRUE 901 01:09:43,770 --> 01:09:58,330 如果在此二叉树的价值是我们正在寻找的任何地方。 902 01:09:58,330 --> 01:10:02,520 因此,让我们第一次做递归和迭代,我们将做到这一点。 903 01:10:02,520 --> 01:10:07,300 事实上,我们可以做起来,因为这将是非常短的。 904 01:10:07,300 --> 01:10:11,510 >> 什么是我的基本情况又如何呢? 905 01:10:11,510 --> 01:10:13,890 [学生,不知所云] 906 01:10:13,890 --> 01:10:18,230 [鲍登]所以,​​如果(树== NULL),然后呢? 907 01:10:18,230 --> 01:10:22,740 [学生]:返回false。 908 01:10:22,740 --> 01:10:26,160 [鲍登否则,好了,我不需要别的。 909 01:10:26,160 --> 01:10:30,250 如果是我的基本情况。 910 01:10:30,250 --> 01:10:32,450 [学生]:树的价值呢? >>呀。 911 01:10:32,450 --> 01:10:36,430 所以,如果(树 - >值==值。 912 01:10:36,430 --> 01:10:39,920 请注意,我们又回到了节点*,而不是节点的**吗? 913 01:10:39,920 --> 01:10:42,990 蕴涵永远不会需要使用一个节点** 914 01:10:42,990 --> 01:10:45,480 因为我们没有修改指针。 915 01:10:45,480 --> 01:10:50,540 我们只是遍历。 916 01:10:50,540 --> 01:10:53,830 如果出现这种情况,那么,我们要返回true。 917 01:10:53,830 --> 01:10:58,270 否则,我们要遍历的孩子。 918 01:10:58,270 --> 01:11:02,620 因此,我们不能推理是否所有的左边是 919 01:11:02,620 --> 01:11:05,390 的一切权利。 920 01:11:05,390 --> 01:11:09,590 那么,什么是我们的条件,要在这里 - 或者说,什么是我们该怎么办? 921 01:11:09,590 --> 01:11:11,840 [学生,不知所云] >>呀。 922 01:11:11,840 --> 01:11:17,400 返回包含(价值树 - >左) 923 01:11:17,400 --> 01:11:26,860 或(价值树 - >右)。就是这样。 924 01:11:26,860 --> 01:11:29,080 发现有短路的评价, 925 01:11:29,080 --> 01:11:32,520 如果我们碰巧发现在左边的树形, 926 01:11:32,520 --> 01:11:36,820 我们永远需要寻找正确的树。 927 01:11:36,820 --> 01:11:40,430 这是整个函数。 928 01:11:40,430 --> 01:11:43,690 现在,让我们做迭代, 929 01:11:43,690 --> 01:11:48,060 这将是那么好。 930 01:11:48,060 --> 01:11:54,750 我们将采取一贯的起始节点的电流=树。 931 01:11:54,750 --> 01:12:03,250 虽然(当前= NULL)。 932 01:12:03,250 --> 01:12:08,600 快速将看到一个问题。 933 01:12:08,600 --> 01:12:12,250 如果电流 - 在这里,如果我们打破这个, 934 01:12:12,250 --> 01:12:16,020 然后,我们已经用完了的事情来看待,所以返回false。 935 01:12:16,020 --> 01:12:24,810 如果(当前值==值),则返回true。 936 01:12:24,810 --> 01:12:32,910 所以,现在,我们是在一个地方 - 937 01:12:32,910 --> 01:12:36,250 我们不知道,我们是否要向左走还是向右。 938 01:12:36,250 --> 01:12:44,590 所以,随意,让我们去离开。 939 01:12:44,590 --> 01:12:47,910 显然,我遇到一个问题,我已经完全放弃一切 - 940 01:12:47,910 --> 01:12:50,760 我将永远只能检查左侧的树。 941 01:12:50,760 --> 01:12:56,050 我永远都不会检查任何孩子的东西是正确的。 942 01:12:56,050 --> 01:13:00,910 我该如何解决这个问题? 943 01:13:00,910 --> 01:13:05,260 [学生]:您有堆栈跟踪的左,右。 944 01:13:05,260 --> 01:13:13,710 鲍登]是啊。所以,让我们把它 945 01:13:13,710 --> 01:13:32,360 结构列表,节点n,然后节点**吗? 946 01:13:32,360 --> 01:13:40,240 我认为正常工作。 947 01:13:40,240 --> 01:13:45,940 我们想要去的左,或let's - 在这里。 948 01:13:45,940 --> 01:13:54,350 结构列表的列表=,它会开始 949 01:13:54,350 --> 01:13:58,170 出在这个结构列表。 950 01:13:58,170 --> 01:14:04,040 *列表= NULL。所以这将是我们的链表 951 01:14:04,040 --> 01:14:08,430 子树,我们已经跳过了。 952 01:14:08,430 --> 01:14:13,800 我们要遍历现在剩下的, 953 01:14:13,800 --> 01:14:17,870 但由于我们无可避免地要回来的右侧, 954 01:14:17,870 --> 01:14:26,140 我们要保持我们的结构列表内的右侧。 955 01:14:26,140 --> 01:14:32,620 然后,我们,将有new_list或结构, 956 01:14:32,620 --> 01:14:41,080 结构列表,new_list的malloc(sizeof(列表)的)。 957 01:14:41,080 --> 01:14:44,920 我要忽略错误检查,但你应该检查,看它是否为NULL。 958 01:14:44,920 --> 01:14:50,540 New_list的节点,它的指向 - 959 01:14:50,540 --> 01:14:56,890 哦,我想这就是为什么它在这里。要指出的第二个结构列表。 960 01:14:56,890 --> 01:15:02,380 这是多么链表的工作。 961 01:15:02,380 --> 01:15:04,810 这是相同的作为一个int链表 962 01:15:04,810 --> 01:15:06,960 除了我们刚刚更换的int节点*。 963 01:15:06,960 --> 01:15:11,040 这是完全一样的。 964 01:15:11,040 --> 01:15:15,100 所以new_list,的价值我们的new_list节点, 965 01:15:15,100 --> 01:15:19,120 会是电流>右键。 966 01:15:19,120 --> 01:15:24,280 我们new_list的价值 - >明年将是我们原来的名单, 967 01:15:24,280 --> 01:15:30,760 然后我们来更新我们的列表中指向new_list的。 968 01:15:30,760 --> 01:15:33,650 >> 现在,我们需要某种方式拉的东西, 969 01:15:33,650 --> 01:15:37,020 就像我们所走过的整个左子树。 970 01:15:37,020 --> 01:15:40,480 现在我们需要把它拉出来的东西, 971 01:15:40,480 --> 01:15:43,850 如当前是空的,我们不希望只是返回false。 972 01:15:43,850 --> 01:15:50,370 我们现在要在外面拉我们新的列表。 973 01:15:50,370 --> 01:15:53,690 一种方便的方法,这样做的 - 其实,有多种方式这样做。 974 01:15:53,690 --> 01:15:56,680 任何人有建议吗? 975 01:15:56,680 --> 01:15:58,790 在哪里我应该这样做,或者我应该这样做吗? 976 01:15:58,790 --> 01:16:08,010 我们只有一两分钟,但有什么建议? 977 01:16:08,010 --> 01:16:14,750 相反 - 的一种方式,而不是我们的条件,同时, 978 01:16:14,750 --> 01:16:17,090 我们目前正在不为空, 979 01:16:17,090 --> 01:16:22,340 相反,我们要继续走,直到我们的名单本身是空的。 980 01:16:22,340 --> 01:16:25,680 因此,如果我们的列表为空, 981 01:16:25,680 --> 01:16:30,680 然后我们跑出来的东西,寻找,搜寻。 982 01:16:30,680 --> 01:16:39,860 但是,这意味着在我们的名单的第一件事,只是将第一个节点。 983 01:16:39,860 --> 01:16:49,730 的第一件事是 - 我们不再需要看到的。 984 01:16:49,730 --> 01:16:58,710 所以列表 - > n将是我们的树。 985 01:16:58,710 --> 01:17:02,860 列表 - >下一个会是空的。 986 01:17:02,860 --> 01:17:07,580 而现在名单不等于空。 987 01:17:07,580 --> 01:17:11,610 cur是要拉的东西从我们的名单。 988 01:17:11,610 --> 01:17:13,500 因此,当前要平等列表 - > N。 989 01:17:13,500 --> 01:17:20,850 ,然后列出要平等列表 - > N,或列表下。 990 01:17:20,850 --> 01:17:23,480 因此,如果当前值等于值。 991 01:17:23,480 --> 01:17:28,790 现在我们可以添加我们的权利,指针和我们的左指针 992 01:17:28,790 --> 01:17:32,900 只要他们不为空。 993 01:17:32,900 --> 01:17:36,390 到这里,我想我们应该这样做,是摆在首位。 994 01:17:36,390 --> 01:17:44,080 如果(电流>好吧!= NULL) 995 01:17:44,080 --> 01:17:56,380 那么,我们该节点将要插入到我们的名单。 996 01:17:56,380 --> 01:17:59,290 如果(电流左),这是一点点额外的工作,但它的罚款。 997 01:17:59,290 --> 01:18:02,690 如果(电流左!= NULL), 998 01:18:02,690 --> 01:18:14,310 我们要我们的链表中插入左, 999 01:18:14,310 --> 01:18:19,700 这应该是它。 1000 01:18:19,700 --> 01:18:22,670 我们遍历 - 只要我们有一些在我们的名单, 1001 01:18:22,670 --> 01:18:26,640 我们有另一个节点来看看。 1002 01:18:26,640 --> 01:18:28,920 因此,我们期待在该节点上, 1003 01:18:28,920 --> 01:18:31,390 我们推进我们的列表中的下一个。 1004 01:18:31,390 --> 01:18:34,060 如果该节点是我们正在寻找的价值,我们就可以返回true。 1005 01:18:34,060 --> 01:18:37,640 否则插入我们的左,右子树, 1006 01:18:37,640 --> 01:18:40,510 只要他们不为空,进入我们的名单 1007 01:18:40,510 --> 01:18:43,120 所以,我们不可避免地走了他们。 1008 01:18:43,120 --> 01:18:45,160 所以,如果他们不为空, 1009 01:18:45,160 --> 01:18:47,950 如果我们的根指针指向两件事情, 1010 01:18:47,950 --> 01:18:51,670 然后我们把车停在第一的东西,所以我们的列表为空。 1011 01:18:51,670 --> 01:18:56,890 然后我们把两件事情回来,所以现在我们的名单是大小为2。 1012 01:18:56,890 --> 01:19:00,030 那我们是要循环,我们只是要拉, 1013 01:19:00,030 --> 01:19:04,250 比方说,我们的根结点的左指针。 1014 01:19:04,250 --> 01:19:07,730 那将只是不断发生,我们将结束循环一切。 1015 01:19:07,730 --> 01:19:11,280 >> 请注意,这是显着更复杂 1016 01:19:11,280 --> 01:19:14,160 在递归的解决方案。 1017 01:19:14,160 --> 01:19:17,260 我已经说过多次, 1018 01:19:17,260 --> 01:19:25,120 的递归解决方案通常有很多共同之处,与迭代求解。 1019 01:19:25,120 --> 01:19:30,820 在这里,这是什么做的递归解决方案。 1020 01:19:30,820 --> 01:19:36,740 唯一的变化是,而不是隐式地使用堆栈,程序堆栈, 1021 01:19:36,740 --> 01:19:40,840 跟踪哪些节点需要访问的方式, 1022 01:19:40,840 --> 01:19:45,430 现在,你必须明确地使用链表。 1023 01:19:45,430 --> 01:19:49,070 在这两种情况下,你跟踪哪些节点仍然需要访问。 1024 01:19:49,070 --> 01:19:51,790 在递归的情况下,它只是更容易,因为堆栈 1025 01:19:51,790 --> 01:19:57,100 你的程序堆栈来实现。 1026 01:19:57,100 --> 01:19:59,550 请注意,此链接的列表,这是一个堆栈。 1027 01:19:59,550 --> 01:20:01,580 无论我们只是把在堆栈上 1028 01:20:01,580 --> 01:20:09,960 我们马上要去拉断的堆栈访问下。 1029 01:20:09,960 --> 01:20:14,380 我们没时间了,但什么问题吗? 1030 01:20:14,380 --> 01:20:23,530 [学生,不知所云] 1031 01:20:23,530 --> 01:20:27,790 鲍登]是啊。所以,如果我们有我们的链接列表, 1032 01:20:27,790 --> 01:20:30,150 当前要指向这个家伙, 1033 01:20:30,150 --> 01:20:34,690 现在我们只是推动我们的联名单专注于这家伙。 1034 01:20:34,690 --> 01:20:44,200 我们穿越过该行的链表中。 1035 01:20:44,200 --> 01:20:51,200 然后,我想我们应该帮助我们的链表之类的东西 1036 01:20:51,200 --> 01:20:53,880 前一次返回true或false,我们需要 1037 01:20:53,880 --> 01:20:57,360 我们的链表遍历,并一直在这里,我想, 1038 01:20:57,360 --> 01:21:03,900 如果我们当前不等于,添加它,所以现在我们要释放 1039 01:21:03,900 --> 01:21:09,600 电流,因为,我们完全忘了该列表?是啊。 1040 01:21:09,600 --> 01:21:12,880 所以,这就是我们想要做的。 1041 01:21:12,880 --> 01:21:16,730 指针在哪里? 1042 01:21:16,730 --> 01:21:23,320 当前是 - 我们需要一个结构列表* 10等于列表旁边。 1043 01:21:23,320 --> 01:21:29,240 免费列表,列表温度。 1044 01:21:29,240 --> 01:21:32,820 的情况下,我们返回true,我们需要遍历 1045 01:21:32,820 --> 01:21:37,050 在剩余的联系列表中解放出来的东西。 1046 01:21:37,050 --> 01:21:39,700 美好的事情被释放的递归解决方案 1047 01:21:39,700 --> 01:21:44,930 只是意味着会发生堆栈中弹出承购关闭。 1048 01:21:44,930 --> 01:21:50,720 因此,我们已经走了的东西,就像3行认为难以对代码 1049 01:21:50,720 --> 01:21:57,520 显著更多的东西,是很难认为有关的代码行。 1050 01:21:57,520 --> 01:22:00,620 还有什么问题吗? 1051 01:22:00,620 --> 01:22:08,760 好的。我们是很好的。再见! 1052 01:22:08,760 --> 01:22:11,760 [CS50.TV]