目录
背景
油管印度老师 Harsha Suryanarayana 的数据结构课程,听说是最强最清晰的数据结构课程,遂听听看并做笔记。大学数据结构真的很阴影,不知道会不会在这个课程中改观。(就是下图吸引我开始看这个课程的)
原教程视频油管地址:Data Structureshttps://www.youtube.com/watch?v=92S4zgXN17o&list=PL2_aWCzGMAwI3W_JlcBbtYTwiQSsOTa6P
语言:C,C++
本文使用说明
标题一 层级的序号对应视频序号,标题为翻译后的小节视频名称。
没篇文章记录整数个视频内容,不会把同一个视频笔记分在两篇。如有需要查看特定小节视频笔记可以在评论区使个眼色,后期做一个集合文档方便大家查找序号所在文章和跳转。
笔记偏向直接记录重点概念,课程胜在表达方式。文末会对文中提到小节中比较有趣进行简单的讲法总结和推荐。
1、数据结构介绍
英文原名:Introduction to data structure
A data structure is a way to store and organize data in a computer, so that it can be used efficiently.(数据结构是计算机中存储和组织数据的一种方式,以便有效地使用数据。)
2、数据结构:作为抽象数据类型的列表
英文原名:Data Structure: List as abstract data type
设列表名为 A,长度为 n。
2.1 在 List(列表)类型中可做的操作有
- 当变量 n=-1 时,可以调用一个空的列表
- Insert:在列表中特定位置插入元素(但是需要其他所有元素一个一个挪动)
- Delete:可移触某元素(其后所有的元素会自动向前挪)
- Count:可数出列表元素的个数为 (n+1) 个,需要 +1 是因为列表的第一位对应序号为 0。如,列表 A 的第一位写为 A[0] 。
- Access / Modify:可读取/修改特定位置的元素
- 可定义特殊数组类型。
数据结构不仅仅是研究 这些操作的操作 和 这些操作的实现,还要考虑 这些操作的成本(运算时间)。
2.2 List(列表)内各种操作的时间复杂度
- Access / 写入:直接访问位置,或直接在列尾写上,都是单位时间内可以完成的,故时间复杂度为 O(1)。
- Insert:插入一个特定元素,根据列表的长度决定,插入后其后每一个数都需要在位次上后移一位,故时间复杂度为 O(n)。
- Delete:同插入,时间复杂度为 O(n)。
- 增加内容:看情况,有空位的话就是 O(1) ;列表已满的话需要把新建更长的列表,把所有内容复制进去再写入,此时时间复杂度为 O(n)。(第 3 节会详细讲)
List(列表)的优点是访问和写入时时间复杂度仅为 O(1) ,但是组内数据必须连在一起有点呆板,有没有更好的利用内存/时间的数据结构呢?
下一节讲 Linked List(链表)
3、链表介绍
英文原名:Introduction to linked list
List(列表)的内存不是最高效的,使用 Arrays(数组)时会有一些限制,为了更好地理解后面链表解决的问题,这里需要先详解这些限制。
3.1 使用 List(列表)的局限
当已在内存上占有固定大小的数组,采取了数据结构 List 存储为 A[4] 时,此时在其后位置上恰好有一个 x 填入记录(如上图),则无法直接将其扩展为 A[5] ,如果有需求需要扩展 List,增加数组位数为 5,此时的解决方案为:
- 申请一个更长的 List 块
- 将 A[4] 的内容信息复制进去
- 增加第 5 位信息
- 再将原来的 A[4] 删掉。
可以说是非常麻烦,并且仍不能完全解决问题:
申请一个“更长”的 List,需要多长就是打赌,很多情况在开始时都无法准确预测,申请长了浪费空间资源,申请短了会需要更大规模的复制迁移浪费算力和时间成本。
3.2 Linked List(链表)的实现逻辑
上图为 Linked List(链表)的记录原理,即随机为数组各位信息分配位置,并在其后记录下一个数的位置作为指针。图中相同颜色挨着的两模块,前者为 数据域,后者为 指针域。
结束指针
如上图紫色模块,在指针域填写 0 表示该数据域内容为 Linked List(链表)的结尾,即可结束数组。
单次请求
在建立链表时,实现方式为,单词请求 2 个块,一个块存信息(4 bytes),一个块存下一块的位置即指针(4bytes)
typedef struct Node {
int data; //4bytes
struct Node* next; //4bytes
} Node;
所以对于链表来说,知道了头节点的地址就相当于可以访问整个链表。
3.3 链表内增加一位的实现流程
如上图,252 为新增数组信息
- 请求增加一位
- 新的信息获得一个内存位置块
- 此位置信息会填入之前最后一位的指针域,而新信息的指针域为 0 或 null 表达为新的结尾
链表优点
没有使用额外的内存(虽然严格来说,需要申请指针域也是多占用内存,但是可以按照需求灵活地创建/释放)
3.4 链表时间复杂度
Access:访问,元素访问时不能像列表一样,在恒定常数时间内访问任一元素,在链表中需要从第一位开始遍历链表,直到所需访问位,故时间复杂度为 O(n)。
Insert:插入,虽不用像列表一样一位一位移动,但是因为需要遍历链表找到插入位置,时间复杂度也为 O(n)。
Delete:删除,与插入同理需要遍历,故时间复杂度为 O(n)。
总结推荐
第 3 个视频《链表介绍》用小故事形式讲的,比较生动,新手易懂。