数组与链表
当我们需要将数据存储到内存中时,我们需要请求计算机提供内存空间,而如果我们需要存储多项数据时,我们通常会采用两种方式:
- 数组
- 列表
使用数组则意味计算机会为我们开辟一连串的内存空间用于存储数据,假设我们知道需要存储的数据的总量是多少,我们则可以在生成数组变量的时候进行声明来让计算机开辟制定大小的内存空间,但是倘若我们并不知道需要存储的数据的总量是多少,则意味着会出现需要存储的数据多于了我们开辟的内存空间的情况,而紧邻着我们的开辟的数组的内存空间的内存空间可能出现已经被占用的情况,在这样的情况之下,我们需要开辟一个新的内存空间来转移和存储原有的数据和新的数据。
对此的一个解决方法是,在开辟内存空间的时候让计算机开辟一个大于我们现阶段所需要的内存空间来为之后可能需要存储的数据提供“预留座位”。比如说我们现在只需要存储3个数据,但是我们开辟一个可以存储10个数据的内存空间,来为之后可能需要存储的数据作出预留。
但是这样的方法存在着两个缺点:
- 预留的内存空间没有用上,于是出现了浪费内存的情况
- 后续出现的需要存储的数据大于了我们预留的内存空间,于是我们不得不开辟新的内存空间来进行转移
对此的解决方案则是使用链表。
链表的每一个元素中都存储了下一个元素的内存地址,所以不连贯的/随机的内存空间都可以被串联在一起。
但是也因为链表的这一个特性,如果我们需要知道链表中的最后一个元素,我们不能够直接读取,而是必须通过链表中的第一个元素所提供的内存地址找到第二个元素,再通过第二个元素所提供的内存地址找到第三个元素,以此类推来找到最后一个元素。如果是要遍历链表中的所有元素,链表不失为一种效率很高的选择,但是如果需要跳跃,链表的效率则非常的低。与之相反的,数组中的每一个元素的地址都是确定的,所以可以随机的读取任意一个指定元素。
下表为对数组和链表进行插入或者读取时候所需要的运行时间:
数组会先在内存中分配空间,插入和删除元素,都会造成其它元素的重新排列,因为这会导致之后元素的前移或者后移,或者需要开辟一个新的内存空间来存储数组。
链表会在内存中存入元素和指向下一个存储内存的地址,可以分布在内存任意地址,只需要修改前一个元素的内存地址,和让插入数据包含有指向下一个元素的内存地址便可以了。
选择排序
选择排序的思路非常的简单,在未排序的序列中找到最大(或者最小)的元素,存放到排序序列的启示位置,然后再从剩余未排序元素中继续寻找最大(或者最小)的元素,然后放到以排序序列的末尾,以此类推直到所有元素均排列完毕。
找出列表中最大(或者最小)的元素所需要的时间为O(n),而该步骤需要执行n次,所以总的需要的时间为O(n*n),也就是O(n^2)。
假设我们有一个数组,并且要求将数组中的元素按照从小到大的顺序进行排列。
首先,我们可以写一个查找最小值的函数:
def findSmallest(arr):
#首先我们声明一个变量用来存储最小值
#该表量的初始值可以是第一个元素的值
smallest = arr[0]
#存储最小元素的索引位置
smallest_index = 0
#这里从第二个元素开始,因为smallest已经是第一个元素的值了
for i in range (1, len(arr)):
#如果该元素小于了既有的smallest元素,则替换
if arr[i] < smallest:
smallest = arr[i]
#同样的索引的位置也会发生改变
smallest_index = i
#返回索引位置
return smallest_index
接着再使用这个函数来写一个选择排序函数:
def selectionSort(arr):
# 首先要生成一个新的数组
newArr = []
for i in range(len(arr)):
#找到最小的变量
smallest = findSmallest(arr)
#将该变量从原先的数组中弹出并且加入到新建的数组中
newArr.append(arr.pop(smallest))
return newArr
我们可以进行一个简单的测试:
print (selectionSort([1,3,9,8,7]))
运行结果为:
[1, 3, 7, 8, 9]