算法图解第二章笔记与习题(选择排序)
文章目录
2.2 数组和链表
2.2.1 链表
- 链表在内存中通过每个元素存储下一个元素的地址,使得一系列随机的内存地址串在一起。
想要在链表中插入新的元素,只需要随机在内存中获取地址即可。
想要在链表中删除一个元素,只需要修改前一个元素指向的地址,使其跳过要删除的元素即可。
因此,链表易于插入删除,而不易于读取。
2.2.2 数组
- 数组在内存中直接获取一块连续的地址,来存储数据。当数据量超过已有地址时,将无法继续存储,需要搬迁整个数组。
由于数组的内存地址是连续的,所以十分易于读取。但并不容易插入和删除。
2.2.3 数组和链表的读取、插入和删除操作的时间复杂度
- | 数组 | 链表 |
---|---|---|
读取 | ||
插入 | ||
删除 |
2.3 选择排序
# 找出数组中的最小元素
def findSmallest(arr):
# 存储最小的值
smallest = arr[0]
# 存储最小元素的索引
smallest_index = 0
for i in range(1, len(arr)):
if arr[i] < smallest:
smallest_index = i
smallest = arr[i]
return smallest_index
# 排序算法
def selectionSort(arr):
newArr = []
for i in range(len(arr)):
# 找出数组中最小的元素,并将其加入到新的数组中
smallest = findSmallest(arr)
newArr.append(arr.pop(smallest))
return newArr
2.4 小结
- 需要存储多个元素时,可使用数组或链表。
- 数组的元素都是连在一起的,就像一节节车厢。
- 链表的元素是分散开的,其中每个元素都存储了下一个元素的地址。
- 数组的读取速度很快。
- 链表的插入和删除的速度很快。
- 在同一个数组中,所有元素的类型都必须相同(都为int、double等)。
练习
习题2.1
- 假设你要编写一个记账的应用程序。你每天都将所有支出记录下来,并在月底统计支出,算算当月花了多少钱。因此,你执行的插入操作很多,但读取操作很少。该使用数组还是链表呢?
插入操作很多,但读取操作很少。因此更适合用链表。
习题2.2
- 假设你要为饭店创建一个接受顾客点菜单的应用程序。这个应用程序存储一系列点菜单。服务员添加点菜单,而厨师去除点菜单并制作菜肴。这是一个点菜单队列:服务员在队尾添加点菜单,厨师取出队列开头的点菜单并制作菜肴。
- 你使用数组还是链表来实现这个队列呢?(提示:链表擅长插入和删除,而数组擅长随机访问。在这个应用程序中,你要执行的是哪些操作呢?)
链表,在这个应用程序中,使用的更多是插入和删除,因此选择链表。
习题2.3
- 我们来做一个思考实验。假设Facebook记录一系列用户名,每当有用户试图登录Facebook时,都查找其用户名,如果找到就允许用户登录。由于经常有用户登录Facebook,因此需要执行大量的用户名查找操作。假设Facebook使用二分查找算法,而这种算法要求能随机访问——立即获取中间的用户名。考虑到这一点,应使用数组还是链表来存储用户名呢?
数组,在这个思考实验中,需求是能够随机访问。而数组相比起链表来说,更易于查询。
习题2.4
- 经常有用户在Facebook注册。假设你已决定使用数组来存储用户名,在插入方面数组有何缺点呢?具体地说,在数组中添加新用户将出现什么情况?
在插入方面,数组容易内存不足,需要的操作也比较复杂,时间复杂度为 。
具体地说,在数组中添加新用户时,首先需要判断剩余的内存空间是否富足,如果不足,则需要整体搬迁数组在内存中的地址,其次需要查找元素在数组中的位置,并将在它后面的所有元素后移一位,最多需要移动 位,这也是为什么在数组中添加新用户时其时间复杂度位 的原因。
习题2.5
- 实际上,Facebook存储用户信息使用的既不是数组也不是链表。假设Facebook使用的是一种混合数据:链表数组。这个数组包含有26个元素,每个元素都指向一个链表。例如,该数组的第一个元素指向的链表包含所有以A打头的用户名,第二个元素指向的链表包含所有以B打头的用户名,以此类推。
- 假设Adit B在Facebook注册,而你需要将其加入前述的数据结构中。因此,你访问数组的第一个元素,在访问该元素指向的链表,并将Adit B添加到这个链表的结尾。现在你要查找Zakhir H。因此你访问第26个元素,再在它指向的链表(该链表包含所有以z打头的用户名)中查找Zahkir H。
- 请问,相比于数组和链表,这种混合数据结构的查找和插入速度更慢还是更快?你不必给出大 运行时间,只需指出这种新数据结构的查找和插入速度更快还是更慢。
插入为常数时间 ,实际为 (在两个链表中插入)。因此比数组 快,比链表$O(1) $稍慢,但区别不大。
查询为 ,但实际上是 ,因此比数组 慢,但比链表 快。