1 00:00:00,000 --> 00:00:01,000 [Powered by Google Translate] [第6条] [舒适] 2 00:00:01,000 --> 00:00:04,000 罗布·鲍登] [哈佛大学] 3 00:00:04,000 --> 00:00:09,000 这是CS50。[CS50.TV] 4 00:00:09,000 --> 00:00:11,000 >> 我们可以前往我们的部分问题。 5 00:00:11,000 --> 00:00:17,000 我的空间,然后再发送URL。 6 00:00:17,000 --> 00:00:22,000 开始部分的问题说 7 00:00:22,000 --> 00:00:26,000 显然,我并不完全unsick是一个很简单的问题 8 00:00:26,000 --> 00:00:28,000 究竟什么是Valgrind的? 9 00:00:28,000 --> 00:00:30,000 Valgrind的是什么办? 10 00:00:30,000 --> 00:00:34,000 任何人想要说什么Valgrind的吗? 11 00:00:34,000 --> 00:00:36,000 [学生]:检查内存泄漏。 12 00:00:36,000 --> 00:00:41,000 是啊,Valgrind是一个一般的内存检查。 13 00:00:41,000 --> 00:00:44,000 ,最终,它会告诉你,如果你有任何内存泄漏, 14 00:00:44,000 --> 00:00:49,000 这主要是我们正在使用它,因为如果你想 15 00:00:49,000 --> 00:00:54,000 问题集,或如果你想 16 00:00:54,000 --> 00:00:59,000 大板,你需要有任何没有内存泄漏, 17 00:00:59,000 --> 00:01:01,000 如果你有内存泄漏,你不能找到, 18 00:01:01,000 --> 00:01:04,000 也请记住,每当你打开一个文件时, 19 00:01:04,000 --> 00:01:07,000 ,如果你不关闭它,这是一个内存泄漏。 20 00:01:07,000 --> 00:01:10,000 >> 很多人都在寻找一些节点,他们不释放 21 00:01:10,000 --> 00:01:15,000 真的,他们没有关闭字典中的第一步。 22 00:01:15,000 --> 00:01:19,000 它也告诉你,如果你有任何无效的读取或写入, 23 00:01:19,000 --> 00:01:22,000 这意味着,如果你尝试设置一个值 24 00:01:22,000 --> 00:01:26,000 这超出堆的结束,它不会发生段故障 25 00:01:26,000 --> 00:01:30,000 但Valgrind的捕获它,你不应该写在那里, 26 00:01:30,000 --> 00:01:33,000 ,所以你绝对不应该有任何的那些要么。 27 00:01:33,000 --> 00:01:38,000 你如何使用Valgrind的吗? 28 00:01:38,000 --> 00:01:42,000 你如何使用Valgrind的吗? 29 00:01:42,000 --> 00:01:45,000 >> 这是一个普遍的问题 30 00:01:45,000 --> 00:01:49,000 种运行它,并期待在输出端。 31 00:01:49,000 --> 00:01:51,000 输出压倒了很多次。 32 00:01:51,000 --> 00:01:54,000 也很有趣,如果你有一些非常错误的事情的错误 33 00:01:54,000 --> 00:01:59,000 发生在一个循环中,那么它最终会说,“太多的错误。 34 00:01:59,000 --> 00:02:03,000 我要现在停止计数。“ 35 00:02:03,000 --> 00:02:08,000 它基本上是你要解析的文本输出。 36 00:02:08,000 --> 00:02:13,000 最后,它会告诉你,你有任何内存泄漏, 37 00:02:13,000 --> 00:02:16,000 有多少块,它可以是有用的,因为 38 00:02:16,000 --> 00:02:20,000 如果是1块未释放,那么它通常更容易找到 39 00:02:20,000 --> 00:02:23,000 超过1000块未释放。 40 00:02:23,000 --> 00:02:26,000 千的块未释放可能意味着你不释放 41 00:02:26,000 --> 00:02:30,000 您的链表是否恰当一些。 42 00:02:30,000 --> 00:02:32,000 这是Valgrind的。 43 00:02:32,000 --> 00:02:35,000 >> 现在,我们有我们的部分问题, 44 00:02:35,000 --> 00:02:38,000 您不需要下载。 45 00:02:38,000 --> 00:02:41,000 您可以点击我的名字和他们的空间。 46 00:02:41,000 --> 00:02:44,000 现在点击我。 47 00:02:44,000 --> 00:02:46,000 第1次修订将堆栈,这是我们正在做的第一个。 48 00:02:46,000 --> 00:02:55,000 修订2将队列中,第三次修订版将是单向链表。 49 00:02:55,000 --> 00:02:58,000 开始我们的堆栈。 50 00:02:58,000 --> 00:03:02,000 因为它说,在这里,一个堆栈是一个最基本的, 51 00:03:02,000 --> 00:03:07,000 计算机科学的基本数据结构。 52 00:03:07,000 --> 00:03:11,000 很典型的例子是 53 00:03:11,000 --> 00:03:13,000 在食堂的托盘堆。 54 00:03:13,000 --> 00:03:16,000 它基本上是只要你被介绍到堆栈, 55 00:03:16,000 --> 00:03:20,000 有人会说,“哦,就像一个堆栈的托盘。” 56 00:03:20,000 --> 00:03:22,000 您堆叠纸盘。 57 00:03:22,000 --> 00:03:24,000 然后,当你去拉一个托盘, 58 00:03:24,000 --> 00:03:31,000 第一盘,但最近拉的是放在堆栈中的最后一个。 59 00:03:31,000 --> 00:03:34,000 该协议栈也喜欢在这里说 60 00:03:34,000 --> 00:03:37,000 我们有内存段称为堆叠。 61 00:03:37,000 --> 00:03:40,000 为什么它被称为堆栈? 62 00:03:40,000 --> 00:03:42,000 >> 因为像一个堆栈的数据结构, 63 00:03:42,000 --> 00:03:46,000 它压入和弹出堆栈帧在堆栈上, 64 00:03:46,000 --> 00:03:53,000 堆栈帧像一个特定的呼叫的功能。 65 00:03:53,000 --> 00:03:57,000 就像一个堆栈,你将永远有返回 66 00:03:57,000 --> 00:04:03,000 从一个函数调用之前,你可以下降到较低的堆栈帧。 67 00:04:03,000 --> 00:04:08,000 您可以没有main调用foo调用酒吧和酒吧返回到主直接。 68 00:04:08,000 --> 00:04:14,000 它总是遵循了正确的堆栈入栈和出栈。 69 00:04:14,000 --> 00:04:18,000 就像我说的,这两个操作,push和pop。 70 00:04:18,000 --> 00:04:20,000 这些都是普及条款。 71 00:04:20,000 --> 00:04:26,000 你应该知道,在栈不管是什么方面的push和pop。 72 00:04:26,000 --> 00:04:28,000 我们会看到队列是一种不同的。 73 00:04:28,000 --> 00:04:32,000 它并没有真正有一个通用的术语,但是普遍的堆栈push和pop。 74 00:04:32,000 --> 00:04:34,000 只是在栈上推。 75 00:04:34,000 --> 00:04:37,000 流行是从堆栈中。 76 00:04:37,000 --> 00:04:43,000 我们在这里看到的,我们有我们的typedef结构栈, 77 00:04:43,000 --> 00:04:46,000 所以,我们的char *字符串。 78 00:04:46,000 --> 00:04:51,000 不要害怕任何**。 79 00:04:51,000 --> 00:04:54,000 这将是一个字符串数组 80 00:04:54,000 --> 00:04:58,000 或字符数组的指针,其中 81 00:04:58,000 --> 00:05:00,000 指向字符的指针往往是字符串。 82 00:05:00,000 --> 00:05:05,000 它没有为字符串,但在这里,他们将是字符串。 83 00:05:05,000 --> 00:05:08,000 >> 我们有一个字符串数组。 84 00:05:08,000 --> 00:05:14,000 我们有一个大小,表示目前有多少元素在栈上, 85 00:05:14,000 --> 00:05:19,000 然后我们有能力,这是可以在栈上有多少个元素。 86 00:05:19,000 --> 00:05:22,000 容量应开始大于1, 87 00:05:22,000 --> 00:05:27,000 但规模要开始为0。 88 00:05:27,000 --> 00:05:36,000 现在,基本上有三种不同的方式,你能想到的堆栈。 89 00:05:36,000 --> 00:05:39,000 嗯,有可能更多,但两种主要方式 90 00:05:39,000 --> 00:05:43,000 你可以实现使用一个数组,也可以实现使用链表。 91 00:05:43,000 --> 00:05:48,000 链表是一种微不足道的栈。 92 00:05:48,000 --> 00:05:51,000 这是很容易使一个堆栈使用链表, 93 00:05:51,000 --> 00:05:55,000 所以在这里,我们要制作堆栈使用数组, 94 00:05:55,000 --> 00:05:59,000 ,然后使用数组,有两种方式,你可以考虑一下。 95 00:05:59,000 --> 00:06:01,000 在此之前,当我说我们有能力为堆栈, 96 00:06:01,000 --> 00:06:04,000 因此,我们可以容纳一个元素在堆栈中。 97 00:06:04,000 --> 00:06:09,000 >> 它可能发生的一种方式是,一旦你打10个元素,那么你就大功告成了。 98 00:06:09,000 --> 00:06:13,000 你可能知道,有一个上限的10件事情在世界上 99 00:06:13,000 --> 00:06:16,000 你永远也不会在栈上有10个以上的东西, 100 00:06:16,000 --> 00:06:20,000 在这种情况下,你可以有你的堆栈的大小的上限。 101 00:06:20,000 --> 00:06:23,000 或者你可以有你的堆栈是无界的, 102 00:06:23,000 --> 00:06:27,000 但如果你正在做一个阵列,这意味着每一次你打10个元素, 103 00:06:27,000 --> 00:06:29,000 那么你会增长到20个元素,当你打20个元素, 104 00:06:29,000 --> 00:06:33,000 你将有增长数组的30个元素或40个元素。 105 00:06:33,000 --> 00:06:37,000 你会需要增加的能力,这是我们要在这里做什么。 106 00:06:37,000 --> 00:06:40,000 每一次我们达到我们的堆栈的最大大小, 107 00:06:40,000 --> 00:06:46,000 当我们把别的事情上,我们将需要增加的能力。 108 00:06:46,000 --> 00:06:50,000 在这里,我们推声明为布尔推(字符*海峡)。 109 00:06:50,000 --> 00:06:54,000 的char * str是字符串,我们推入堆栈, 110 00:06:54,000 --> 00:06:58,000 和bool只是说我们是否成功或失败。 111 00:06:58,000 --> 00:07:00,000 >> 我们怎能不呢? 112 00:07:00,000 --> 00:07:04,000 什么是唯一的情况下,你能想到的 113 00:07:04,000 --> 00:07:07,000 在这里,我们需要返回false? 114 00:07:07,000 --> 00:07:09,000 是啊。 115 00:07:09,000 --> 00:07:12,000 [学生]:如果它是完整的,我们使用的是有界的实现。 116 00:07:12,000 --> 00:07:17,000 是啊,所以我们定义,他说: 117 00:07:17,000 --> 00:07:23,000 如果是完整的,和我们使用的是有界的实现。 118 00:07:23,000 --> 00:07:26,000 然后,我们肯定会返回false。 119 00:07:26,000 --> 00:07:31,000 只要我们打的10件事情在数组中,我们可以不适合11,所以我们返回false。 120 00:07:31,000 --> 00:07:32,000 如果它是无界的,该怎么办?是啊。 121 00:07:32,000 --> 00:07:38,000 如果出于某种原因,你不能扩展磁盘阵列。 122 00:07:38,000 --> 00:07:43,000 是啊,所以内存是一种有限的资源, 123 00:07:43,000 --> 00:07:51,000 最终,如果我们继续推动入堆栈的事情一遍又一遍, 124 00:07:51,000 --> 00:07:54,000 我们要尝试分配一个更大的数组,以适应 125 00:07:54,000 --> 00:07:59,000 产能较大,我们正在使用的malloc或任何会返回false。 126 00:07:59,000 --> 00:08:02,000 好了,malloc将返回null。 127 00:08:02,000 --> 00:08:05,000 >> 请记住,你曾经每一次调用malloc,你应该检查,看它是否 128 00:08:05,000 --> 00:08:12,000 返回null,否则这是一个正确的扣除。 129 00:08:12,000 --> 00:08:17,000 因为我们希望有一个无限的堆栈, 130 00:08:17,000 --> 00:08:21,000 唯一的情况下,我们将要返回false,如果我们试图 131 00:08:21,000 --> 00:08:26,000 增加的容量和malloc或任何返回false。 132 00:08:26,000 --> 00:08:30,000 这时弹出不带任何参数, 133 00:08:30,000 --> 00:08:37,000 并且它返回字符串,该字符串是在堆栈的顶部。 134 00:08:37,000 --> 00:08:41,000 无论是最近被压入堆栈弹出返回, 135 00:08:41,000 --> 00:08:44,000 它也把它从栈中删除。 136 00:08:44,000 --> 00:08:50,000 发现,它返回null,如果在栈上有什么。 137 00:08:50,000 --> 00:08:53,000 它始终是可能的堆栈是空的。 138 00:08:53,000 --> 00:08:55,000 在Java中,如果你使用,或其他语言, 139 00:08:55,000 --> 00:09:01,000 试图从一个空栈中弹出,可能会导致异常或什么的。 140 00:09:01,000 --> 00:09:09,000 >> 但在C,空是种了很多的情况下,我们如何处理这些问题。 141 00:09:09,000 --> 00:09:13,000 返回null是我们要如何表示的堆栈是空的。 142 00:09:13,000 --> 00:09:16,000 我们提供的代码,将测试协议栈的功能, 143 00:09:16,000 --> 00:09:19,000 实现push和pop。 144 00:09:19,000 --> 00:09:23,000 这会不会是大量的代码。 145 00:09:23,000 --> 00:09:40,000 我会实际上,在我们这样做之前,提示,提示 146 00:09:40,000 --> 00:09:44,000 如果你还没有看到它时,malloc是不是唯一的功能 147 00:09:44,000 --> 00:09:47,000 为您的堆分配内存。 148 00:09:47,000 --> 00:09:51,000 有一个家庭的alloc函数。 149 00:09:51,000 --> 00:09:53,000 首先是malloc的,你已经习惯了。 150 00:09:53,000 --> 00:09:56,000 然后释放calloc,做同样的事情的malloc, 151 00:09:56,000 --> 00:09:59,000 但它会为零,一切为你。 152 00:09:59,000 --> 00:10:04,000 如果你曾经想将一切设置为null后mallocing的东西 153 00:10:04,000 --> 00:10:06,000 你应该只是用来释放calloc,而不是写在首位 154 00:10:06,000 --> 00:10:09,000 一个循环零出整个内存块。 155 00:10:09,000 --> 00:10:15,000 >> 如malloc和realloc是有很多的特殊情况下, 156 00:10:15,000 --> 00:10:19,000 但基本上什么realloc的是 157 00:10:19,000 --> 00:10:24,000 它需要一个已经分配的指针,该指针。 158 00:10:24,000 --> 00:10:27,000 realloc是你想要的功能,关注这里。 159 00:10:27,000 --> 00:10:31,000 它需要一个已经从malloc返回的指针。 160 00:10:31,000 --> 00:10:35,000 比方说,你从malloc要求10个字节的指针。 161 00:10:35,000 --> 00:10:38,000 后来你意识到你需要20个字节, 162 00:10:38,000 --> 00:10:42,000 所以你调用realloc的,20个字节的指针, 163 00:10:42,000 --> 00:10:47,000 和realloc会自动复制过来的一切都​​是为了你。 164 00:10:47,000 --> 00:10:51,000 如果你只是叫的malloc再次,像我有块10个字节。 165 00:10:51,000 --> 00:10:53,000 现在我需要一个20字节的块, 166 00:10:53,000 --> 00:10:58,000 因此,如果我malloc的20个字节,那么我必须手动复制10个字节的第一件事 167 00:10:58,000 --> 00:11:01,000 进入第二件事情,然后自由的第一件事。 168 00:11:01,000 --> 00:11:04,000 realloc的会为你处理。 169 00:11:04,000 --> 00:11:11,000 >> 请注意,签名会是void *, 170 00:11:11,000 --> 00:11:15,000 这是只返回一个指针,指向的内存块, 171 00:11:15,000 --> 00:11:17,000 void *的指针。 172 00:11:17,000 --> 00:11:22,000 作为一个通用的指针,你可以认为是void *。 173 00:11:22,000 --> 00:11:27,000 一般情况下,你永远不处理用void *, 174 00:11:27,000 --> 00:11:30,000 但malloc()并返回一个void *,然后它只是用来像 175 00:11:30,000 --> 00:11:34,000 这实际上是将是一个char *。 176 00:11:34,000 --> 00:11:37,000 ,以前的void * malloc返回的 177 00:11:37,000 --> 00:11:41,000 现在要通过向realloc,然后大小 178 00:11:41,000 --> 00:11:49,000 是你要分配的字节数,因此新的能力。 179 00:11:49,000 --> 00:11:57,000 我给你一两分钟,这样做在我们的空间。 180 00:11:57,000 --> 00:12:02,000 开始第1次修订。 181 00:12:16,000 --> 00:12:21,000 我会停下来后,希望能有足够的时间执行推入, 182 00:12:21,000 --> 00:12:24,000 然后,我给你做流行音乐的另一种突破。 183 00:12:24,000 --> 00:12:27,000 但它确实是没有那么多的代码在所有。 184 00:12:27,000 --> 00:12:35,000 大多数的代码可能扩大的东西,扩充产能。 185 00:12:35,000 --> 00:12:39,000 好了,没有压力,完全做到, 186 00:12:39,000 --> 00:12:47,000 但只要你觉得你是在正确的道路,这是很好的。 187 00:12:47,000 --> 00:12:53,000 >> 没有人有任何的代码,他们与我拉起来感觉很舒服吗? 188 00:12:53,000 --> 00:12:59,000 是的,我会的,但没有人有任何的代码,我可以拉起来吗? 189 00:12:59,000 --> 00:13:05,000 好了,你可以启动,保存它,不管它是什么? 190 00:13:05,000 --> 00:13:09,000 我总是忘了这一步。 191 00:13:09,000 --> 00:13:15,000 好吧,看在推, 192 00:13:15,000 --> 00:13:18,000 你要解释你的代码吗? 193 00:13:18,000 --> 00:13:24,000 [学生]:首先,我增加的大小。 194 00:13:24,000 --> 00:13:28,000 我想,也许我应该有,反正,我增加的大小, 195 00:13:28,000 --> 00:13:31,000 我看看它的容量不足。 196 00:13:31,000 --> 00:13:36,000 如果是容量不足,我添加到数组中,我们已经有了。 197 00:13:36,000 --> 00:13:42,000 而且,如果不是的话,我的能力乘以2, 198 00:13:42,000 --> 00:13:50,000 我和重新分配的字符串数组的东西,现在更大的容量大小。 199 00:13:50,000 --> 00:13:55,000 然后如果失败了,我告诉用户并返回false, 200 00:13:55,000 --> 00:14:04,000 如果它的罚款,然后我把字符串在新的位置。 201 00:14:04,000 --> 00:14:07,000 >> [罗布B.还要注意,我们这里用一个漂亮的位运算符 202 00:14:07,000 --> 00:14:09,000 乘以2。 203 00:14:09,000 --> 00:14:11,000 请记住,左移总是要乘以2。 204 00:14:11,000 --> 00:14:15,000 除以2,只要你记住,它意味着右移 205 00:14:15,000 --> 00:14:18,000 除以2除以2的整数。 206 00:14:18,000 --> 00:14:20,000 它可能会截断在这里或那里。 207 00:14:20,000 --> 00:14:26,000 但左移1总是要被乘以2, 208 00:14:26,000 --> 00:14:32,000 除非你的整数溢出边界,那么就不会是。 209 00:14:32,000 --> 00:14:34,000 A面注释。 210 00:14:34,000 --> 00:14:39,000 我喜欢做,这是不会改变的编码任何方式, 211 00:14:39,000 --> 00:14:48,000 但我喜欢做这样的事情。 212 00:14:48,000 --> 00:14:51,000 它实际上是要使其稍长。 213 00:15:04,000 --> 00:15:08,000 这也许是不完美的情况下显示, 214 00:15:08,000 --> 00:15:14,000 但我喜欢分割成块, 215 00:15:14,000 --> 00:15:17,000 好吧,如果这一点,如果发生了,那么我要做的事情, 216 00:15:17,000 --> 00:15:19,000 ,然后函数完成的。 217 00:15:19,000 --> 00:15:22,000 我不需要,然后一路向下滚动我的眼睛的功能 218 00:15:22,000 --> 00:15:25,000 看看会发生什么后,其他。 219 00:15:25,000 --> 00:15:27,000 如果这如果发生的话,我就回来。 220 00:15:27,000 --> 00:15:30,000 它也有额外的好处,一切都超出了这个漂亮的 221 00:15:30,000 --> 00:15:33,000 现在左移一次。 222 00:15:33,000 --> 00:15:40,000 我不再需要,如果你曾经冗长得可笑的近线, 223 00:15:40,000 --> 00:15:45,000 然后这4个字节可以提供帮助,也更左的东西, 224 00:15:45,000 --> 00:15:48,000 少不堪重负,你觉得如果想好了,我一定要记住 225 00:15:48,000 --> 00:15:53,000 我目前在一个while循环内的其他内的循环。 226 00:15:53,000 --> 00:15:58,000 任何地方,你可以马上做到这一点回报,我倒是很喜欢。 227 00:15:58,000 --> 00:16:05,000 这是完全可选的,并且预期不会以任何方式。 228 00:16:05,000 --> 00:16:12,000 >> [学生]:应该有一个大小 - 在故障条件? 229 00:16:12,000 --> 00:16:19,000 故障条件在这里,我们向realloc失败,所以,是的。 230 00:16:19,000 --> 00:16:22,000 请注意,在故障条件下,据推测, 231 00:16:22,000 --> 00:16:26,000 除非我们免费的东西,我们总是要失败 232 00:16:26,000 --> 00:16:29,000 无论多少次,我们试推的东西。 233 00:16:29,000 --> 00:16:32,000 如果我们继续推动我们不断递增,规模, 234 00:16:32,000 --> 00:16:36,000 即使我们不把任何东西压入堆栈。 235 00:16:36,000 --> 00:16:39,000 通常,我们不会增加的大小,直到 236 00:16:39,000 --> 00:16:43,000 之后,我们已经成功地把它放在堆栈中。 237 00:16:43,000 --> 00:16:50,000 我们将做到这一点,说,无论是在这里和这里。 238 00:16:50,000 --> 00:16:56,000 然后,不要说s.size≤能力,它的容量小于, 239 00:16:56,000 --> 00:17:01,000 只是因为我们搬到这里的一切。 240 00:17:01,000 --> 00:17:07,000 >> 请记住,唯一的地方,我们可能会返回false 241 00:17:07,000 --> 00:17:14,000 在这里,这里的realloc返回null, 242 00:17:14,000 --> 00:17:19,000 如果你碰巧要记住标准错误, 243 00:17:19,000 --> 00:17:22,000 也许你会认为这是一个情况下,你要打印一个标准的错误, 244 00:17:22,000 --> 00:17:26,000 fprintf STDERR,而不是直接打印到标准输出。 245 00:17:26,000 --> 00:17:31,000 再次,这是不是一种期望,但如果它是一个错误, 246 00:17:31,000 --> 00:17:41,000 输入输出,那么你可能希望将它打印到标准错误,而不是标准输出。 247 00:17:41,000 --> 00:17:44,000 >> 任何人还有什么要注意的吗?是。 248 00:17:44,000 --> 00:17:47,000 [学生]:你去[听不清]? 249 00:17:47,000 --> 00:17:55,000 [罗布B.]是的,或实际binariness,只是它是什么呢? 250 00:17:55,000 --> 00:17:57,000 [学生]:所以你将它乘以2? 251 00:17:57,000 --> 00:17:59,000 [罗布B.]是啊,基本上是这样。 252 00:17:59,000 --> 00:18:11,000 在二进制的土地,我们总是有一组数字。 253 00:18:11,000 --> 00:18:22,000 移此由1左侧基本上将它插入这里在右侧。 254 00:18:22,000 --> 00:18:25,000 返回到这一点,只是记住,一切以二进制 255 00:18:25,000 --> 00:18:28,000 是2的幂,所以这表示2到0, 256 00:18:28,000 --> 00:18:30,000 这2到1,这2到2。 257 00:18:30,000 --> 00:18:33,000 右侧插入一个0到现在,我们只是改变一切。 258 00:18:33,000 --> 00:18:38,000 曾经被认为是2 0现在是2到1,2 2。 259 00:18:38,000 --> 00:18:41,000 我们插入右侧, 260 00:18:41,000 --> 00:18:44,000 一定是0, 261 00:18:44,000 --> 00:18:46,000 这是有道理的。 262 00:18:46,000 --> 00:18:49,000 如果你曾经一个数字乘以2,这不是要结束了奇数, 263 00:18:49,000 --> 00:18:54,000 所以2〜0的地方应为0, 264 00:18:54,000 --> 00:18:59,000 这是什么我一半警告说,如果你之前是发生转移 265 00:18:59,000 --> 00:19:01,000 以外的一个整数中的比特数, 266 00:19:01,000 --> 00:19:04,000 那么这个1是要最终会关闭。 267 00:19:04,000 --> 00:19:10,000 这是唯一的担心,如果你碰巧要处理的非常大的能力。 268 00:19:10,000 --> 00:19:15,000 但在这一点,那么你正在处理的数组数十亿美元的东西, 269 00:19:15,000 --> 00:19:25,000 可能不适合到内存中了。 270 00:19:25,000 --> 00:19:31,000 >> 现在,我们可以得到流行,这是更容易。 271 00:19:31,000 --> 00:19:36,000 你可以不喜欢,如果你碰巧弹出一大堆, 272 00:19:36,000 --> 00:19:38,000 现在你的一半容量。 273 00:19:38,000 --> 00:19:42,000 你可以realloc的缩小的内存量, 274 00:19:42,000 --> 00:19:47,000 但你不必担心,所以只有realloc的情况下,将是 275 00:19:47,000 --> 00:19:50,000 日益增长的记忆,永远不会萎缩的内存, 276 00:19:50,000 --> 00:19:59,000 这是会弹出超级简单的。 277 00:19:59,000 --> 00:20:02,000 现在要像栈,队列, 278 00:20:02,000 --> 00:20:06,000 但顺序是相反的,你拿东西出来。 279 00:20:06,000 --> 00:20:10,000 队列中的典型例子是一条线, 280 00:20:10,000 --> 00:20:12,000 所以我想,如果你是英语,我会说 281 00:20:12,000 --> 00:20:17,000 一个典型的例子是一个队列的队列。 282 00:20:17,000 --> 00:20:22,000 因此,像一条线,如果你是行的第一人, 283 00:20:22,000 --> 00:20:24,000 您期望成为第一个出列的人。 284 00:20:24,000 --> 00:20:31,000 如果你是行的最后一个人,你会是最后一个人服务。 285 00:20:31,000 --> 00:20:35,000 我们称之为FIFO模式,而堆栈是后进先出法的模式。 286 00:20:35,000 --> 00:20:40,000 这些话是非常普遍的。 287 00:20:40,000 --> 00:20:46,000 >> 就像栈和,不像数组,队列通常不允许在中间的元素。 288 00:20:46,000 --> 00:20:50,000 在这里,我们有一个堆栈,push和pop。 289 00:20:50,000 --> 00:20:54,000 在这里,我们碰巧召他们入队和出队。 290 00:20:54,000 --> 00:20:58,000 我也听到他们叫shift和unshift。 291 00:20:58,000 --> 00:21:02,000 我已经听到有人说push和pop也适用于队列。 292 00:21:02,000 --> 00:21:05,000 我听说插入,删除, 293 00:21:05,000 --> 00:21:11,000 所以push和pop,如果你正在谈论有关栈,入栈和出栈。 294 00:21:11,000 --> 00:21:16,000 如果你说的队列,你可以选择你要使用的话 295 00:21:16,000 --> 00:21:23,000 插入和删除,是应该叫什么没有达成共识。 296 00:21:23,000 --> 00:21:27,000 但在这里,我们有入队和出队。 297 00:21:27,000 --> 00:21:37,000 现在,该结构看起来几乎相同的堆栈结构。 298 00:21:37,000 --> 00:21:40,000 但是,我们必须跟踪头。 299 00:21:40,000 --> 00:21:44,000 我想在这里说的,但为什么我们需要的头吗? 300 00:21:53,000 --> 00:21:57,000 的原型基本上是相同的push和pop。 301 00:21:57,000 --> 00:21:59,000 你可以把它看成push和pop。 302 00:21:59,000 --> 00:22:08,000 唯一的区别是弹出的返回,而不是最后的,它的第一个返回。 303 00:22:08,000 --> 00:22:12,000 2,1,3,4,或东西。 304 00:22:12,000 --> 00:22:14,000 这里的开始。 305 00:22:14,000 --> 00:22:17,000 我们的队列已经完全满了,所以有四个元素在里面。 306 00:22:17,000 --> 00:22:21,000 结束我们的队列当前为2, 307 00:22:21,000 --> 00:22:24,000 现在我们去插入别的东西。 308 00:22:24,000 --> 00:22:29,000 >> 当我们要插入其他的东西,我们所做的堆栈版本 309 00:22:29,000 --> 00:22:36,000 是我们扩大了我们的内存块。 310 00:22:36,000 --> 00:22:40,000 这个是什么问题呢? 311 00:22:40,000 --> 00:22:45,000 [学生]:你提出的2。 312 00:22:45,000 --> 00:22:51,000 我说的队列结束前, 313 00:22:51,000 --> 00:22:57,000 这没有任何意义,我们开始为1, 314 00:22:57,000 --> 00:23:01,000 然后,我们要出列1,然后出队,出队4 315 00:23:01,000 --> 00:23:05,000 然后出列,然后出列,这一个。 316 00:23:05,000 --> 00:23:08,000 我们现在不能使用realloc, 317 00:23:08,000 --> 00:23:11,000 最起码,你有,使用realloc以不同的方式。 318 00:23:11,000 --> 00:23:15,000 但你可能不应该只是使用realloc。 319 00:23:15,000 --> 00:23:18,000 你将必须手动复制你的记忆。 320 00:23:18,000 --> 00:23:21,000 >> 有两个函数复制内存。 321 00:23:21,000 --> 00:23:25,000 有存储器复制和memmove。 322 00:23:25,000 --> 00:23:29,000 我目前正在读,看看哪一个你将要使用的手册页。 323 00:23:29,000 --> 00:23:35,000 好了,存储器复制,不同的是 324 00:23:35,000 --> 00:23:38,000 存储器复制和memmove,而正确处理的情况下 325 00:23:38,000 --> 00:23:41,000 您在何处复制到一个区域发生重叠的区域 326 00:23:41,000 --> 00:23:46,000 你复制。 327 00:23:46,000 --> 00:23:50,000 存储器复制不处理。 Memmove。 328 00:23:50,000 --> 00:23:59,000 你能想到的问题, 329 00:23:59,000 --> 00:24:09,000 比方说,我要复制这个家伙, 330 00:24:09,000 --> 00:24:13,000 这四个这家伙过来。 331 00:24:13,000 --> 00:24:16,000 最后,该数组应该像 332 00:24:16,000 --> 00:24:26,000 后的副本是2,1,2,1,3,4,然后在最后的一些东西。 333 00:24:26,000 --> 00:24:29,000 但是,这是依赖于复制的顺序, 334 00:24:29,000 --> 00:24:32,000 因为如果我们不考虑该地区的事实,我们复制到 335 00:24:32,000 --> 00:24:35,000 我们复制重叠, 336 00:24:35,000 --> 00:24:46,000 然后,我们可能不喜欢开始,在这里,我们想要去的地方复制2, 337 00:24:46,000 --> 00:24:52,000 然后将指针向前发展。 338 00:24:52,000 --> 00:24:56,000 >> 现在,我们要在这里和这里,现在我们要复制 339 00:24:56,000 --> 00:25:04,000 这家伙在这个家伙的指针向前移动。 340 00:25:04,000 --> 00:25:07,000 我们将最终得到的是2,1,2,1,2,1 341 00:25:07,000 --> 00:25:10,000 而不是在适当的2,1,2,1,3,4,因为 342 00:25:10,000 --> 00:25:15,000 2,推翻了原来的3,4。 343 00:25:15,000 --> 00:25:19,000 Memmove处理是正确的。 344 00:25:19,000 --> 00:25:23,000 在这种情况下,基本上只是使用memmove 345 00:25:23,000 --> 00:25:26,000 因为它处理是正确的。 346 00:25:26,000 --> 00:25:29,000 它一般不执行任何恶化。 347 00:25:29,000 --> 00:25:32,000 我们的想法是开始,而不是从一开始就复制这种方式 348 00:25:32,000 --> 00:25:35,000 就像我们刚刚在这里做的,从去年底开始和复制, 349 00:25:35,000 --> 00:25:38,000 在这种情况下,你可以永远不会有问题。 350 00:25:38,000 --> 00:25:40,000 有没有性能上的丢失。 351 00:25:40,000 --> 00:25:47,000 请务必使用memmove。再也不用担心存储器复制。 352 00:25:47,000 --> 00:25:51,000 这就是你要去的地方有单独memmove 353 00:25:51,000 --> 00:26:01,000 包裹的部分,您的队列。 354 00:26:01,000 --> 00:26:04,000 不用担心,如果没有完全做到。 355 00:26:04,000 --> 00:26:10,000 这是更加困难比栈,推,和流行。 356 00:26:10,000 --> 00:26:15,000 >> 任何人有任何的代码,我们可以使用? 357 00:26:15,000 --> 00:26:21,000 即使完全不完整? 358 00:26:21,000 --> 00:26:23,000 [学生]:是的,这是完全不完整的,虽然。 359 00:26:23,000 --> 00:26:27,000 完全不完全是罚款,只要我们能为您节省修订? 360 00:26:27,000 --> 00:26:32,000 我忘了,每一次。 361 00:26:32,000 --> 00:26:39,000 好了,忽略了会发生什么,当我们需要调整的东西。 362 00:26:39,000 --> 00:26:42,000 完全忽略调整大小。 363 00:26:42,000 --> 00:26:49,000 解释一下这段代码。 364 00:26:49,000 --> 00:26:54,000 我首先检查如果尺寸小于首先复印 365 00:26:54,000 --> 00:27:01,000 ,然后在那之后,我将我头+大小, 366 00:27:01,000 --> 00:27:05,000 我要确保它环绕的数组的容量, 367 00:27:05,000 --> 00:27:08,000 我在该位置插入新的字符串。 368 00:27:08,000 --> 00:27:12,000 然后我增加的大小,并返回true。 369 00:27:12,000 --> 00:27:22,000 >> 罗布B.]这是肯定的情况下,你会希望使用的模之一。 370 00:27:22,000 --> 00:27:25,000 任何一种情况下,你已经环绕着,如果你认为周围包裹, 371 00:27:25,000 --> 00:27:29,000 马上想到的应该是MOD。 372 00:27:29,000 --> 00:27:36,000 作为一个快速优化/较短的一行代码, 373 00:27:36,000 --> 00:27:42,000 您发现该行紧随 374 00:27:42,000 --> 00:27:53,000 只是大小+ +,所以你合并入这行,大小+ +。 375 00:27:53,000 --> 00:27:58,000 在这里,我们的情况下, 376 00:27:58,000 --> 00:28:01,000 我们没有足够的内存, 377 00:28:01,000 --> 00:28:05,000 所以我们提高我们的能力,2。 378 00:28:05,000 --> 00:28:09,000 我想你可以在这里有同样的问题,但现在我们可以忽略它, 379 00:28:09,000 --> 00:28:13,000 其中,如果你没有提高你的能力, 380 00:28:13,000 --> 00:28:18,000 然后,你会想,以减少你的能力,2。 381 00:28:18,000 --> 00:28:24,000 另一个短值得注意的是,就像你可以做+ =, 382 00:28:24,000 --> 00:28:30,000 你也可以做<< =。 383 00:28:30,000 --> 00:28:43,000 前平等,几乎什么都可以去,+ =,| =,&=,<< =。 384 00:28:43,000 --> 00:28:52,000 新的char *是我们的新的内存块。 385 00:28:52,000 --> 00:28:55,000 哦,在这里。 386 00:28:55,000 --> 00:29:02,000 >> 人怎么看我们的新的内存块的类型吗? 387 00:29:02,000 --> 00:29:06,000 [学生]:应该是char **。 388 00:29:06,000 --> 00:29:12,000 回想我们的结构在这里, 389 00:29:12,000 --> 00:29:14,000 字符串是什么,我们重新分配。 390 00:29:14,000 --> 00:29:21,000 我们正在一个全新的动态存储在队列中的元素。 391 00:29:21,000 --> 00:29:25,000 我们要分配给你的字符串就是我们mallocing的,现在, 392 00:29:25,000 --> 00:29:30,000 等新的将是一个char **。 393 00:29:30,000 --> 00:29:34,000 这将是一个字符串数组。 394 00:29:34,000 --> 00:29:38,000 那么,是什么的情况下,我们要返回false? 395 00:29:38,000 --> 00:29:41,000 [学生]:我们应该做的char *? 396 00:29:41,000 --> 00:29:44,000 罗布B.]是的,良好的通话。 397 00:29:44,000 --> 00:29:46,000 [学生]:那是什么? 398 00:29:46,000 --> 00:29:49,000 [罗布B.我们想要做的char *的大小,因为我们不再是 399 00:29:49,000 --> 00:29:53,000 这实际上是一个很大的问题,因为大小(字符)将是1。 400 00:29:53,000 --> 00:29:55,000 SIZEOF的char * 4, 401 00:29:55,000 --> 00:29:58,000 所以很多时候,你正在处理int类型, 402 00:29:58,000 --> 00:30:01,000 你会得到它,因为尺寸大小的int * int和 403 00:30:01,000 --> 00:30:04,000 在32位的系统将是同样的事情。 404 00:30:04,000 --> 00:30:09,000 但在这里,大小(字符)和sizeof(CHAR *)现在将是同样的事情。 405 00:30:09,000 --> 00:30:15,000 >> 在我们返回false是什么情况? 406 00:30:15,000 --> 00:30:17,000 [学生]是空的。 407 00:30:17,000 --> 00:30:23,000 是的,如果新为空,则返回FALSE, 408 00:30:23,000 --> 00:30:34,000 我要在这里摔倒 409 00:30:34,000 --> 00:30:37,000 [学生] [听不清] 410 00:30:37,000 --> 00:30:39,000 罗布B.]是啊,这是好的。 411 00:30:39,000 --> 00:30:46,000 你既可以做2次,容量或容量移1,然后将其设置或任何。 412 00:30:46,000 --> 00:30:52,000 我们会做到这一点,因为我们有它。 413 00:30:52,000 --> 00:30:56,000 容量>> = 1。 414 00:30:56,000 --> 00:31:08,000 你永远不会有担心失去的地方 415 00:31:08,000 --> 00:31:12,000 因为你左移1,所以1的地方必然是一个0, 416 00:31:12,000 --> 00:31:16,000 所以右移1,你仍然会好起来的。 417 00:31:16,000 --> 00:31:19,000 [学生]:你需要做的是在返回之前? 418 00:31:19,000 --> 00:31:29,000 罗布B.是的,这使得完全没有意义。 419 00:31:29,000 --> 00:31:36,000 >> 现在假设我们要最终结束返回true。 420 00:31:36,000 --> 00:31:39,000 方式我们要做这些memmoves的, 421 00:31:39,000 --> 00:31:45,000 我们必须要小心我们如何做。 422 00:31:45,000 --> 00:31:50,000 没有任何人有任何建议,我们如何做? 423 00:32:17,000 --> 00:32:21,000 下面是我们的开始。 424 00:32:21,000 --> 00:32:28,000 不可避免的是,我们要再次从头开始 425 00:32:28,000 --> 00:32:35,000 和从那里复制的东西,1,3,4,2。 426 00:32:35,000 --> 00:32:41,000 你是怎么做到的呢? 427 00:32:41,000 --> 00:32:52,000 首先,我必须看的手册页memmove。 428 00:32:52,000 --> 00:32:57,000 memmove,而参数的顺序是非常重要的。 429 00:32:57,000 --> 00:33:01,000 我们希望我们的目标首先,源第二,规模第三。 430 00:33:01,000 --> 00:33:06,000 有很多扭转源和目标的功能。 431 00:33:06,000 --> 00:33:11,000 目标,源往往有些是一致的。 432 00:33:17,000 --> 00:33:21,000 移动,它返回的是什么? 433 00:33:21,000 --> 00:33:27,000 它返回一个指针到目的地,不管是什么原因,你可能想。 434 00:33:27,000 --> 00:33:32,000 我能想象读它,但我们要进入我们的目的地。 435 00:33:32,000 --> 00:33:35,000 >> 什么是我们的目标又如何呢? 436 00:33:35,000 --> 00:33:37,000 [学生]。 437 00:33:37,000 --> 00:33:39,000 罗布B.是的,和我们复制的呢? 438 00:33:39,000 --> 00:33:43,000 我们要复印的第一件事情是这样的1,3,4。 439 00:33:43,000 --> 00:33:50,000 这是-1,3,4。 440 00:33:50,000 --> 00:33:55,000 这地址是什么? 441 00:33:55,000 --> 00:33:58,000 这1的地址是什么? 442 00:33:58,000 --> 00:34:01,000 [学生] [听不清] 443 00:34:01,000 --> 00:34:03,000 [罗布B.]头+的第一个元素的地址。 444 00:34:03,000 --> 00:34:05,000 我们怎样才能在数组的第一个元素? 445 00:34:05,000 --> 00:34:10,000 [学生]:队列中。 446 00:34:10,000 --> 00:34:15,000 罗布B.]是的,q.strings。 447 00:34:15,000 --> 00:34:20,000 请记住,在这里,我们的头是1。 448 00:34:20,000 --> 00:34:24,000 织补它。我只是觉得这是奇迹般地 449 00:34:24,000 --> 00:34:29,000 在这里,我们的头是1。我要改变我的颜色。 450 00:34:29,000 --> 00:34:36,000 这里是字符串。 451 00:34:36,000 --> 00:34:41,000 这一点,我们可以把它写在这里我们做了 452 00:34:41,000 --> 00:34:43,000 用头+ q.strings。 453 00:34:43,000 --> 00:34:51,000 很多人也写它与q.strings的头。 454 00:34:51,000 --> 00:34:55,000 这是不是真的任何效率不高。 455 00:34:55,000 --> 00:34:58,000 你可能会认为它为您提领,然后得到的地址, 456 00:34:58,000 --> 00:35:04,000 但编译器将它翻译成我们以前的事,反正,q.strings +头。 457 00:35:04,000 --> 00:35:06,000 无论哪种方式,你要考虑它。 458 00:35:06,000 --> 00:35:11,000 >> 我们要复制多少字节? 459 00:35:11,000 --> 00:35:15,000 [学生]:能力 - 头。 460 00:35:15,000 --> 00:35:18,000 能力 - 头。 461 00:35:18,000 --> 00:35:21,000 然后你就可以一直写的一个例子 462 00:35:21,000 --> 00:35:23,000 搞清楚,如果这是正确的。 463 00:35:23,000 --> 00:35:26,000 [学生]:它需要除以2,然后。 464 00:35:26,000 --> 00:35:30,000 是啊,所以我想我们可以使用大小。 465 00:35:30,000 --> 00:35:35,000 我们仍然有大小, 466 00:35:35,000 --> 00:35:39,000 使用大小,我们有大小等于4。 467 00:35:39,000 --> 00:35:42,000 我们的规模是4。我们的头是1。 468 00:35:42,000 --> 00:35:46,000 我们要复制这3个元素。 469 00:35:46,000 --> 00:35:54,000 这就是合理性检查,尺寸 - 是正确的3头。 470 00:35:54,000 --> 00:35:58,000 回来这里,就像我们之前说的, 471 00:35:58,000 --> 00:36:00,000 如果我们使用的能力,那么我们就必须除以2 472 00:36:00,000 --> 00:36:04,000 因为我们已经长大了我们的能力,所以不是,我们会使用大小。 473 00:36:11,000 --> 00:36:13,000 副本的那部分。 474 00:36:13,000 --> 00:36:18,000 现在,我们需要复制的其他部分,剩下的部分开始。 475 00:36:18,000 --> 00:36:28,000 >> 这是怎么回事memmove到什么位置? 476 00:36:28,000 --> 00:36:32,000 [学生]:加上大小 - 头。 477 00:36:32,000 --> 00:36:38,000 是的,所以我们已经复制的大小 - 头字节, 478 00:36:38,000 --> 00:36:43,000 ,所以在这里我们要复制剩余的字节是新的 479 00:36:43,000 --> 00:36:48,000 然后大小负好,我们的字节数已经复制英寸 480 00:36:48,000 --> 00:36:52,000 然后我们复制的呢? 481 00:36:52,000 --> 00:36:54,000 [学生]:Q.strings [0]。 482 00:36:54,000 --> 00:36:56,000 罗布B.]是的,q.strings。 483 00:36:56,000 --> 00:37:02,000 我们可以做和的q.strings [0]。 484 00:37:02,000 --> 00:37:05,000 这是比这明显不太常见。 485 00:37:05,000 --> 00:37:14,000 如果它只是为0,然后你会倾向于看q.strings。 486 00:37:14,000 --> 00:37:16,000 这就是我们正在复制。 487 00:37:16,000 --> 00:37:18,000 多少个字节我们还剩下复制?>> [学生]:10。 488 00:37:18,000 --> 00:37:20,000 右。 489 00:37:20,000 --> 00:37:25,000 [学生]:我们要乘5 - 10倍的大小的字节或什么的? 490 00:37:25,000 --> 00:37:30,000 是啊,所以这是究竟是什么,我们复制吗? 491 00:37:30,000 --> 00:37:32,000 [学生] [听不清] 492 00:37:32,000 --> 00:37:34,000 我们在复制的东西的类型是什么呢? 493 00:37:34,000 --> 00:37:36,000 [学生] [听不清] 494 00:37:36,000 --> 00:37:41,000 是啊,这样的char *,我们复制,我们不知道那些来自。 495 00:37:41,000 --> 00:37:47,000 好了,他们指着,像琴弦,我们最终将其推到队列中 496 00:37:47,000 --> 00:37:49,000 或到队列中进行排队。 497 00:37:49,000 --> 00:37:51,000 如果这些都来自我们不知道。 498 00:37:51,000 --> 00:37:56,000 我们只需要跟踪的char *自己。 499 00:37:56,000 --> 00:38:00,000 我们不希望复制的大小 - 头字节。 500 00:38:00,000 --> 00:38:03,000 我们要复制的大小 - 头的char *, 501 00:38:03,000 --> 00:38:11,000 所以,我们要乘这个大小(char *)的。 502 00:38:11,000 --> 00:38:17,000 在这里,头*大小(CHAR *)。 503 00:38:17,000 --> 00:38:24,000 >> [学生]:怎么样[听不见的? 504 00:38:24,000 --> 00:38:26,000 这项权利在这里吗? 505 00:38:26,000 --> 00:38:28,000 [学生],下面的大小 - 头。 506 00:38:28,000 --> 00:38:30,000 罗布B.这项权利在这里吗? 507 00:38:30,000 --> 00:38:32,000 指针的算术运算。 508 00:38:32,000 --> 00:38:35,000 指针运算是如何去上班 509 00:38:35,000 --> 00:38:40,000 它会自动将的类型,我们正在处理的大小。 510 00:38:40,000 --> 00:38:46,000 就像在这里,新+(大小 - 头) 511 00:38:46,000 --> 00:38:56,000 是完全等同于和新的大小 - 头] 512 00:38:56,000 --> 00:39:00,000 直到我们预计正常工作, 513 00:39:00,000 --> 00:39:04,000 因为如果我们要处理的一个int数组,然后我们不要索引的INT- 514 00:39:04,000 --> 00:39:07,000 如果它的大小为5,和你想的第4个元素,然后我们索引 515 00:39:07,000 --> 00:39:10,000 int数组[4]。 516 00:39:10,000 --> 00:39:14,000 你不 - [4] *大小的int。 517 00:39:14,000 --> 00:39:21,000 来处理它,这种情况下自动 518 00:39:21,000 --> 00:39:29,000 简直是等同的,所以括号的语法 519 00:39:29,000 --> 00:39:34,000 只是要转换为只要你编译。 520 00:39:34,000 --> 00:39:38,000 这件事情你需要小心 521 00:39:38,000 --> 00:39:42,000 当你加入的大小 - 头 522 00:39:42,000 --> 00:39:45,000 你是不是一个字节。 523 00:39:45,000 --> 00:39:53,000 您要添加一个char *,它可以是一个字节或什么的。 524 00:39:53,000 --> 00:39:56,000 >> 其他问题吗? 525 00:39:56,000 --> 00:40:04,000 好了,出队会更容易。 526 00:40:04,000 --> 00:40:11,000 我给你一分钟的时间来实现。 527 00:40:11,000 --> 00:40:18,000 哦,我想这也是同样的情况 528 00:40:18,000 --> 00:40:21,000 排队的情况下,如果我们入队空, 529 00:40:21,000 --> 00:40:24,000 也许我们要处理它,也许我们不这样做。 530 00:40:24,000 --> 00:40:27,000 我们不会再在这里,但我们的堆栈情况下相同。 531 00:40:27,000 --> 00:40:34,000 如果我们加入队列为空,我们可能要忽略它。 532 00:40:34,000 --> 00:40:40,000 任何人有一些代码,我可以拉起来吗? 533 00:40:40,000 --> 00:40:45,000 [学生]:我只是出队。 534 00:40:45,000 --> 00:40:56,000 第2版​​是没事。 535 00:40:56,000 --> 00:40:59,000 你想说明什么? 536 00:40:59,000 --> 00:41:01,000 [学生]:首先,你要确定有什么东西在队列中 537 00:41:01,000 --> 00:41:07,000 而且其大小是由1。 538 00:41:07,000 --> 00:41:11,000 你需要做的,然后返回头 539 00:41:11,000 --> 00:41:13,000 然后将头1。 540 00:41:13,000 --> 00:41:19,000 好了,所以我们必须考虑的一个角落的情况。是啊。 541 00:41:19,000 --> 00:41:24,000 [学生]:如果你的头是在最后一个元素, 542 00:41:24,000 --> 00:41:26,000 然后,你不想头指向阵列外。 543 00:41:26,000 --> 00:41:29,000 >> 是啊,所以只要头打我们的阵列, 544 00:41:29,000 --> 00:41:35,000 我们出列的时候,我们的头被改装为0。 545 00:41:35,000 --> 00:41:40,000 不幸的是,我们不能做到这一点的一个步骤。 546 00:41:40,000 --> 00:41:44,000 我想我可能会解决它是 547 00:41:44,000 --> 00:41:52,000 这是怎么回事,我们正在返回,是一个char * 548 00:41:52,000 --> 00:41:55,000 无论你的变量名要。 549 00:41:55,000 --> 00:42:02,000 然后,我们希望我们的能力,国防部头 550 00:42:02,000 --> 00:42:10,000 然后返回沤。 551 00:42:10,000 --> 00:42:14,000 很多人在这里,他们可能会做 552 00:42:14,000 --> 00:42:19,000 这种情况下,您看人家做头 553 00:42:19,000 --> 00:42:29,000 大于产能,做头 - 能力。 554 00:42:29,000 --> 00:42:36,000 而这仅仅是解决mod是什么。 555 00:42:36,000 --> 00:42:41,000 头模能力是干净多了 556 00:42:41,000 --> 00:42:51,000 一个周围环绕的比大于容量头 - 能力,如果头。 557 00:42:51,000 --> 00:42:56,000 >> 有问题吗? 558 00:42:56,000 --> 00:43:02,000 好了,我们剩下的最后一件事是我们的链表。 559 00:43:02,000 --> 00:43:07,000 你可能会使用一些链表行为,如果你没有 560 00:43:07,000 --> 00:43:11,000 在哈希表,链表,如果你做了一个哈希表。 561 00:43:11,000 --> 00:43:15,000 我强烈建议做一个哈希表。 562 00:43:15,000 --> 00:43:17,000 您可能已经做了特里, 563 00:43:17,000 --> 00:43:23,000 但尝试都比较困难。 564 00:43:23,000 --> 00:43:27,000 从理论上讲,他们是渐近更好。 565 00:43:27,000 --> 00:43:30,000 但就在大板, 566 00:43:30,000 --> 00:43:35,000 并尝试从来没有做的更好,,他们占用更多的内存。 567 00:43:35,000 --> 00:43:43,000 一切有关尝试最终被更多的工作差。 568 00:43:43,000 --> 00:43:49,000 这是大卫·马兰的解决方案始终是 569 00:43:49,000 --> 00:43:56,000 是他的帖子他的特里的解决方案,让我们来看看他目前是。 570 00:43:56,000 --> 00:44:00,000 他是干什么的“,DAVID J? 571 00:44:00,000 --> 00:44:06,000 他是第18,所以这不是差得要命, 572 00:44:06,000 --> 00:44:09,000 ,这将是一个最好的尝试,你能想到的 573 00:44:09,000 --> 00:44:17,000 或一个最好的尝试的线索。 574 00:44:17,000 --> 00:44:23,000 这难道不是他原来的解决方案吗? 575 00:44:23,000 --> 00:44:29,000 我觉得,像特里解决方案更倾向于在此范围内的内存使用。 576 00:44:29,000 --> 00:44:33,000 >> 你下到最高层,和RAM的使用是在个位数。 577 00:44:33,000 --> 00:44:36,000 向下朝下方,然后你开始看到试图 578 00:44:36,000 --> 00:44:41,000 你在哪里得到绝对使用大量的RAM, 579 00:44:41,000 --> 00:44:45,000 尝试都比较困难。 580 00:44:45,000 --> 00:44:53,000 不完全是值得的,但教育经验,如果你没有一个。 581 00:44:53,000 --> 00:44:56,000 最后一点是我们的链接列表, 582 00:44:56,000 --> 00:45:04,000 ,这三个东西,栈,队列,链表, 583 00:45:04,000 --> 00:45:09,000 你做的任何未来的事情在计算机科学 584 00:45:09,000 --> 00:45:12,000 假设你熟悉这些东西。 585 00:45:12,000 --> 00:45:19,000 他们只不过是一切的根本。 586 00:45:19,000 --> 00:45:25,000 >> 链接列表,在这里我们有一个单链表,将是我们实现。 587 00:45:25,000 --> 00:45:34,000 什么是单链表,双向链表的意思,而不是?是。 588 00:45:34,000 --> 00:45:37,000 [学生]:只点到下一个指针,而不是指针, 589 00:45:37,000 --> 00:45:39,000 像一个前它和它的一前一后。 590 00:45:39,000 --> 00:45:44,000 是啊,所以在图片格式上,我只是做吗? 591 00:45:44,000 --> 00:45:48,000 我有两件事。我有图片,图片。 592 00:45:48,000 --> 00:45:51,000 在图片格式上,我们的单链表, 593 00:45:51,000 --> 00:45:57,000 不可避免地,我们有我们的列表的头指针种, 594 00:45:57,000 --> 00:46:02,000 然后在我们的名单,我们只是有三分球, 595 00:46:02,000 --> 00:46:05,000 也许这点为空。 596 00:46:05,000 --> 00:46:08,000 这将是一个单向链表的典型示意图。 597 00:46:08,000 --> 00:46:14,000 一个双向链表,你可以倒着走。 598 00:46:14,000 --> 00:46:19,000 如果我给你列表中的任何一个节点,那么你就一定能获得 599 00:46:19,000 --> 00:46:23,000 列表中的任何其他节点,如果它是一个双向链表。 600 00:46:23,000 --> 00:46:27,000 但是,如果我让你在列表中的第三个节点,这是一个单向链表, 601 00:46:27,000 --> 00:46:30,000 没有办法,你对你将要得到的第一个和第二个节点。 602 00:46:30,000 --> 00:46:34,000 有利弊,一个明显的例子 603 00:46:34,000 --> 00:46:42,000 是你采取了更多的大小,和你有这些东西现在都指向跟踪。 604 00:46:42,000 --> 00:46:49,000 但是,我们只关心单链表的。 605 00:46:49,000 --> 00:46:53,000 >> 有几件事情,我们将不得不实行。 606 00:46:53,000 --> 00:47:00,000 你的typedef结构节点,INT I:结构节点下;节点。 607 00:47:00,000 --> 00:47:09,000 该typedef应烧入你的心。 608 00:47:09,000 --> 00:47:14,000 测验1应该是这样的一个typedef一个链表节点, 609 00:47:14,000 --> 00:47:18,000 你应该能够立即潦草下来 610 00:47:18,000 --> 00:47:22,000 甚至没有考虑它。 611 00:47:22,000 --> 00:47:27,000 我猜一对夫妇的问题,为什么我们需要结构的吗? 612 00:47:27,000 --> 00:47:32,000 我们为什么不能说的节点*? 613 00:47:32,000 --> 00:47:35,000 [学生] [听不清] 614 00:47:35,000 --> 00:47:38,000 是啊。 615 00:47:38,000 --> 00:47:44,000 定义了一个节点的唯一的事情 616 00:47:44,000 --> 00:47:47,000 是typedef本身。 617 00:47:47,000 --> 00:47:55,000 但是这一点,当我们种的解析通过这个结构节点定义, 618 00:47:55,000 --> 00:48:01,000 我们还没有完成我们的typedef,因为typedef还没有完成, 619 00:48:01,000 --> 00:48:05,000 节点不存在。 620 00:48:05,000 --> 00:48:12,000 但结构节点呢,这个节点在这里, 621 00:48:12,000 --> 00:48:14,000 这也可以被称为什么都重要。 622 00:48:14,000 --> 00:48:16,000 这可以被称为n。 623 00:48:16,000 --> 00:48:19,000 它可以被称为链表的节点。 624 00:48:19,000 --> 00:48:21,000 它可以被称为什么。 625 00:48:21,000 --> 00:48:26,000 但是,这需要调用同样的事情,这个结构节点结构节点。 626 00:48:26,000 --> 00:48:29,000 你也可以在这里, 627 00:48:29,000 --> 00:48:32,000 等还回答了第二点的问题 628 00:48:32,000 --> 00:48:37,000 这就是为什么有很多的时候,你看到的结构和类型定义的结构体, 629 00:48:37,000 --> 00:48:42,000 你会看到匿名结构的话,你会看到typedef结构, 630 00:48:42,000 --> 00:48:47,000 实施结构,字典,或其他。 631 00:48:47,000 --> 00:48:51,000 >> 为什么我们在这里需要说的节点? 632 00:48:51,000 --> 00:48:54,000 为什么不能是一个匿名的结构? 633 00:48:54,000 --> 00:48:56,000 这几乎是同样的回答。 634 00:48:56,000 --> 00:48:58,000 [学生]:您需要在struct来引用它。 635 00:48:58,000 --> 00:49:04,000 是啊,在结构,你需要参考的结构本身。 636 00:49:04,000 --> 00:49:10,000 如果你不给结构体的名称,如果它是一个匿名的结构,你可以不引用它。 637 00:49:10,000 --> 00:49:17,000 最后,但并非最不重要的,这些都应该是有些简单的, 638 00:49:17,000 --> 00:49:20,000 他们应该帮助你实现,如果你写下来 639 00:49:20,000 --> 00:49:24,000 你做错了什么,如果这些事情是没有意义的。 640 00:49:24,000 --> 00:49:28,000 最后但并非最不重要的一点是,为什么会发生这种结构节点*? 641 00:49:28,000 --> 00:49:34,000 为什么它不能只是结构的节点吗? 642 00:49:34,000 --> 00:49:37,000 [学生]:到下一个结构体的指针。 643 00:49:37,000 --> 00:49:39,000 这是不可避免的,我们想要的东西。 644 00:49:39,000 --> 00:49:42,000 为什么它永远不会是结构节点下? 645 00:49:42,000 --> 00:49:50,000 为什么有是结构节点下的吗?是啊。 646 00:49:50,000 --> 00:49:53,000 [学生]:这是一个无限循环。 647 00:49:53,000 --> 00:49:55,000 是啊。 648 00:49:55,000 --> 00:49:57,000 [学生]:这将是中的一​​个。 649 00:49:57,000 --> 00:50:02,000 是啊,就认为我们将如何做大小或东西。 650 00:50:02,000 --> 00:50:08,000 一个结构的大小基本上是+或 - 在这里或那里一些模式。 651 00:50:08,000 --> 00:50:15,000 它基本上是要的事情,在结构尺寸的总和。 652 00:50:15,000 --> 00:50:18,000 不改变任何东西,在这里,大小是一件容易的事。 653 00:50:18,000 --> 00:50:24,000 结构节点的大小将是大小的i +尺寸的未来。 654 00:50:24,000 --> 00:50:27,000 的i的大小将是4。下次的大小将是4。 655 00:50:27,000 --> 00:50:30,000 结构节点的大小将是8。 656 00:50:30,000 --> 00:50:34,000 如果我们不*,思维的sizeof 657 00:50:34,000 --> 00:50:37,000 然后大小(ⅰ)将是4。 658 00:50:37,000 --> 00:50:43,000 结构节点的大小未来将是结构节点下的大小为I +大小 659 00:50:43,000 --> 00:50:46,000 +我+尺寸的结构节点下的大小。 660 00:50:46,000 --> 00:50:55,000 这将是一个无限递归的节点。 661 00:50:55,000 --> 00:51:00,000 这就是为什么这是怎么会事必须的。 662 00:51:00,000 --> 00:51:03,000 >> 再次,一定记住, 663 00:51:03,000 --> 00:51:06,000 或至少​​理解不够,你可以可以 664 00:51:06,000 --> 00:51:12,000 通过它看起来应该像什么原因。 665 00:51:12,000 --> 00:51:14,000 我们将要实现的事情。 666 00:51:14,000 --> 00:51:18,000 如果列表长度 667 00:51:18,000 --> 00:51:21,000 你可以欺骗,并保持周围 668 00:51:21,000 --> 00:51:24,000 全球的长度或东西,但我们不打算这样做。 669 00:51:24,000 --> 00:51:28,000 我们要算列表的长度。 670 00:51:28,000 --> 00:51:34,000 我们已经包含,所以这基本上是一样的搜索, 671 00:51:34,000 --> 00:51:41,000 所以我们有一个链表的整数,如果这个整数链表中。 672 00:51:41,000 --> 00:51:44,000 前面加上要插入在列表的开头。 673 00:51:44,000 --> 00:51:46,000 附加将要插入的结束。 674 00:51:46,000 --> 00:51:53,000 Insert_sorted要插入排序列表中的位置。 675 00:51:53,000 --> 00:52:01,000 Insert_sorted种假设你从来没有使用前置或附加在恶劣的方式。 676 00:52:01,000 --> 00:52:09,000 >> 当你实施Insert_sorted insert_sorted - 677 00:52:09,000 --> 00:52:13,000 比方说,我们有我们的链表。 678 00:52:13,000 --> 00:52:18,000 这是它目前看起来,2,4,5。 679 00:52:18,000 --> 00:52:24,000 我想插入3个,所以只要已排序的列表本身, 680 00:52:24,000 --> 00:52:27,000 可以很容易地发现其中3属于。 681 00:52:27,000 --> 00:52:29,000 我从2开始。 682 00:52:29,000 --> 00:52:32,000 好了,3是大于2的,所以我想继续下去。 683 00:52:32,000 --> 00:52:35,000 哦,是太大了,所以我知道要在2至4, 684 00:52:35,000 --> 00:52:39,000 我有固定的指针和所有的东西。 685 00:52:39,000 --> 00:52:43,000 但是,如果我们没有严格使用insert_sorted, 686 00:52:43,000 --> 00:52:50,000 喜欢让我们只想说,我在前面加上6, 687 00:52:50,000 --> 00:52:55,000 我的链接列表将成为这个。 688 00:52:55,000 --> 00:53:01,000 现在,它没有任何意义,所以的insert_sorted,你可以假设 689 00:53:01,000 --> 00:53:04,000 是对列表进行排序,即使操作 690 00:53:04,000 --> 00:53:09,000 这可能会导致不进行排序,就是这样。 691 00:53:09,000 --> 00:53:20,000 找到一个有用的插件,所以这些都是主要的事情,你将不得不实行。 692 00:53:20,000 --> 00:53:24,000 >> 现在,花一分钟的长度和包含, 693 00:53:24,000 --> 00:53:30,000 这些应该是比较快的。 694 00:53:41,000 --> 00:53:48,000 接近关门时间,所以任何人有任何长度或包含? 695 00:53:48,000 --> 00:53:50,000 他们将是几乎相同的。 696 00:53:50,000 --> 00:53:57,000 [学生]:长度。 697 00:53:57,000 --> 00:54:01,000 让我们来看看,修订工作。 698 00:54:01,000 --> 00:54:04,000 好吧。 699 00:54:12,000 --> 00:54:15,000 你想说明什么? 700 00:54:15,000 --> 00:54:21,000 [学生]:我只是创建一个的指针节点,并把它初始化为第一,这是我们的全局变量, 701 00:54:21,000 --> 00:54:27,000 然后我检查,看它是否为null,所以我没有得到段故障,并返回0,如果是这样的话。 702 00:54:27,000 --> 00:54:34,000 否则,我遍历,跟踪的内的整数 703 00:54:34,000 --> 00:54:38,000 多少次,我已经访问列表中的下一个元素 704 00:54:38,000 --> 00:54:43,000 和在相同的增量操作也访问该实际元素, 705 00:54:43,000 --> 00:54:47,000 然后我不断地检查,看它是否为NULL, 706 00:54:47,000 --> 00:54:56,000 ,如果它是空的,那么它中止,只是返回我访问过的元素。 707 00:54:56,000 --> 00:55:01,000 >> [罗布B.]有没有人有任何意见什么? 708 00:55:01,000 --> 00:55:06,000 这看起来精细的正确性明智的。 709 00:55:06,000 --> 00:55:10,000 [学生]:我不认为你需要的节点== NULL。 710 00:55:10,000 --> 00:55:13,000 是啊,所以如果节点== null返回0。 711 00:55:13,000 --> 00:55:18,000 但如果节点== NULL,那么这个,哦,有一个正确的问题。 712 00:55:18,000 --> 00:55:23,000 这只是你回到我的,但它现在不在范围之内。 713 00:55:23,000 --> 00:55:30,000 你只需要我,所以我= 0。 714 00:55:30,000 --> 00:55:34,000 但是,如果节点是空的,那么我仍然为0, 715 00:55:34,000 --> 00:55:39,000 我们将返回0,所以这种情况是相同的。 716 00:55:39,000 --> 00:55:48,000 另一种常见的是要保持的声明 717 00:55:48,000 --> 00:55:51,000 节点内的for循环。 718 00:55:51,000 --> 00:55:54,000 你可能会说,哦,不。 719 00:55:54,000 --> 00:55:56,000 让我们保持它,因为这。 720 00:55:56,000 --> 00:55:59,000 我可能会放INT I = 0在这里, 721 00:55:59,000 --> 00:56:05,000 然后节点节点第一次在这里。 722 00:56:05,000 --> 00:56:11,000 这可能是如何摆脱现在的这种。 723 00:56:11,000 --> 00:56:14,000 这可能是我会怎么写。 724 00:56:14,000 --> 00:56:21,000 你也可以看它是这样的。 725 00:56:21,000 --> 00:56:25,000 在这里循环结构,这 726 00:56:25,000 --> 00:56:30,000 应该是几乎一样自然地为int i = 0 727 00:56:30,000 --> 00:56:33,000 i是小于数组的长度一+ +。 728 00:56:33,000 --> 00:56:38,000 如果这就是你如何遍历一个数组,你这是怎么遍历一个链表。 729 00:56:38,000 --> 00:56:45,000 >> 在某些时候,这应该是第二自然。 730 00:56:45,000 --> 00:56:50,000 考虑到这一点,这将是几乎同样的事情。 731 00:56:50,000 --> 00:56:57,000 你将要遍历一个链表。 732 00:56:57,000 --> 00:57:02,000 如果节点的价值是什么,我不知道。 733 00:57:02,000 --> 00:57:04,000 节点i。 734 00:57:04,000 --> 00:57:15,000 如果该节点的值=返回true,这就是它。 735 00:57:15,000 --> 00:57:18,000 请注意,只有这样,我们永远返回false 736 00:57:18,000 --> 00:57:23,000 的是,如果我们遍历整个链表,永不返回true, 737 00:57:23,000 --> 00:57:29,000 所以,这是什么做的。 738 00:57:29,000 --> 00:57:36,000 作为一个方面说明,我们可能不会得到要前插或追加。 739 00:57:36,000 --> 00:57:39,000 >> 快速最后一个音符。 740 00:57:39,000 --> 00:57:52,000 如果你看到了static关键字,所以让我们说静态诠释计数= 0, 741 00:57:52,000 --> 00:57:56,000 然后我们做数+ +中,你可以基本上认为它作为一个全局变量, 742 00:57:56,000 --> 00:58:00,000 即使我只是说,这不是我们要如何落实长度。 743 00:58:00,000 --> 00:58:06,000 我这样做是在这里,再算上+ +。 744 00:58:06,000 --> 00:58:11,000 任何方式,我们就可以进入到我们的链接列表,我们正在增加我们的计算节点。 745 00:58:11,000 --> 00:58:15,000 这点是static关键字意味着什么。 746 00:58:15,000 --> 00:58:20,000 如果我刚做了诠释计数= 0,这将是一个普通的老全局变量。 747 00:58:20,000 --> 00:58:25,000 静态诠释计数装置是什么,它​​是一个全局变量,这个文件。 748 00:58:25,000 --> 00:58:28,000 这是不可能的其他一些文件, 749 00:58:28,000 --> 00:58:34,000 想到的pset 5,如果你已经开始。 750 00:58:34,000 --> 00:58:39,000 你有都speller.c,和你有dictionary.c, 751 00:58:39,000 --> 00:58:42,000 和,如果你只是全球申报的事情,那么在speller.c 752 00:58:42,000 --> 00:58:45,000 可以访问在dictionary.c,反之亦然。 753 00:58:45,000 --> 00:58:48,000 全局变量。c文件的任何访问, 754 00:58:48,000 --> 00:58:54,000 但静态变量只能在文件本身, 755 00:58:54,000 --> 00:59:01,000 所以里面的法术检查或内部dictionary.c的, 756 00:59:01,000 --> 00:59:06,000 这是我的数组的大小如何,我会宣布我的变量 757 00:59:06,000 --> 00:59:10,000 我在字典中的单词数的大小。 758 00:59:10,000 --> 00:59:15,000 因为我不希望声明一个全局变量,任何人都可以访问, 759 00:59:15,000 --> 00:59:18,000 我真的只关心我自己的目的。 760 00:59:18,000 --> 00:59:21,000 >> 好的事情也整个名称冲突的东西。 761 00:59:21,000 --> 00:59:27,000 如果有其他文件试图使用一个全局变量数,事情会变得非常,非常错误的, 762 00:59:27,000 --> 00:59:33,000 所以这很好地保持安全起见,只有你可以访问它, 763 00:59:33,000 --> 00:59:38,000 并没有其他人就可以了,如果有人声明了一个全局变量数, 764 00:59:38,000 --> 00:59:43,000 然后,它不会干扰您的静态变量数。 765 00:59:43,000 --> 00:59:47,000 这是静态的。它是一个文件的全局变量。 766 00:59:47,000 --> 00:59:52,000 >> 问题什么呢? 767 00:59:52,000 --> 00:59:59,000 所有的设置。再见。 768 00:59:59,000 --> 01:00:03,000 [CS50.TV]