1. Sequential Search
遍历一遍数组,发现相等则返回:
复杂度 = O(n), 平均时间为 n/2
2. Binary Search
每次通过比较target和中间值List[middle]的大小关系改变start指针和end指针,每次都丢弃剩余数组的1/2。
复杂度O(logN)
while Start < End:
if 中间值==target 则返回
elif: target小于中间值,说明middle到end的所有值都大于target,舍弃后半部分(end = middle - 1)
else: target大于中间值,说明start到middle的所有值都小于target,舍弃前半部分(start = middle + 1)
def binarySearch(orderedList, target):
#初始首位指针的位置
start = 0
end = len(orderedList) - 1
while start < end: # 最差在start == end的时候停止(最好情况在middle值 == target停止)
middle = (start + end) // 2 #地板除
if target == orderedList[middle]:
return
else:
if target < orderedList[middle]:
end = middle - 1 #一定要-1,防止无限循环,下同 ([1,2] 当target = 2 时,middle 永远指向1,因为是地板除)
else:
start = middle + 1
print("no result")
3.Bubble Sort
两个for循环,外层循环表示运行N次,内层循环遍历每个值,依据大小顺序对当前值和下一个值进行顺序的调换。
想象啤酒冒泡
复杂度O(n^2)
4.Selection Sort
从小到大(从大到小),每次选择最小(最大)的值放到相应的位置:
for i in range(len(list)):
for j in range(i + 1, len(list) - 1):
寻找最小值
最小值与i调换位置
复杂度O(n^2)
5. Insertion Sort
将前1个排好序
将第二个值算入,找到它的位置
将第三个值算入,找到它的位置
...
将第N个值算入,找到它的位置
具体找位置的方法是,从右往左,在寻找第N个值的插入位置同时,不断的将大的数向后移动一位,空出位置
def InsertionSort(List):
for i in range(1, len(List)):
temp = List[i] #保存待插入的值
j = i
while j > 0 and temp < List[j-1]: #直到循环到j = 0或者提前找到插入位置
List[j] = List[j-1]
j -= 1
List[j] = temp
return List
复杂度:O(n^2)
6. Shell Sort
按照length // 2来分组,每组进行injection sort
def shellSort(list):
step = len(list) // 2
while step > 0: # step不断除以2,直到为0停止
for i in range(step, len(list)): #从step开始一直往后进行插入排序
j = i
temp = list[i]
while i - step >= 0 and temp < list[i-step]: #注意一步是step不是1
list[i] = list[i-step]
i -= step
list[i] = temp
step = step // 2
复杂度:O(n) - O(n^2)
7.Merge Sort
归并排序,通过先将数组不断拆分成成不能再拆分,然后对两两数组进行合并,所以称为归并排序。
通过递归的方法可以很简单的实现这个方式,首先对当前数组进行拆分,拆成left 和 right两个数组,并且对这俩数组调用本身,将他们排好序,接着对这两个数组做归并操作,返回归并后的数组
def merge(left, right): #合并左右数组的操作
i = j = 0
result = []
while i < len(left) and j < len(right):
if left[i] < right[j]:
result.append(left[i])
i += 1
else:
result.append(right[j])
j += 1
if i < len(left): #当其中一个数组已经取完后,将另一个数组剩下的元素接到result后
result = result + left[i:]
if j < len(right): #同上
result = result + right[j:]
return result
def MergeSort(list):
if len(list) == 1: # exit
return list
middle = len(list) // 2
left = MergeSort(list[:middle])
right = MergeSort(list[middle:])
return merge(left, right)
8.Quick Sort
仍然是"分而治之"的思想的一种排序方法。我们需要实现一种方法:可以通过运行一次,将数组分成两部分:left, base,right。需要保证left数组里的所有值都小于base这个分隔值,right数组里的所有值都大于base这个分隔值,但不要求left和right是有序的。
具体实现方法:
1. 首先我们规定 list[0] 是我们的分隔值,也就是base。
2. 使用两个指针,分别是i, j = 0, len(list) -1 指向数组的首尾
3. j--, 从右往左,找第一个小于base的值
4. i++, 从左往右,找第一个大于base的值
5. 将i,j指向的值变换位置
6. 重复3,4步骤直到i,j相遇停止, 将base值和i,j指向的值互换位置
7. 最后对left和right分别进行quicksort操作,直到不能拆分停止
举例:
list = [6, 1, 2, 7, 9, 3, 4, 5, 10, 8]
6 1 2 7 9 3 4 5 10 8
将 7 和 5 变换位置
6 1 2 5 9 3 4 7 10 8
将 9 和 4 变换位置
6 1 2 5 4 3 9 7 10 8
在 3 停止, 将 base和 3 交换位置
3 1 2 5 4 6 9 7 10 8
第一次quicksort执行完毕,我们将 数组分成了 小于6的left和大于6的right两部分
然后对left 和 right分别进行quicksort操作,直到不能继续拆分为止。
def QuickSort(List):
if len(List) <= 1: #特殊情况1
return List
if len(List) == 2: #特殊情况2
if List[1] < List[0]:
List = List[-1::-1]
return List
i = 0 #左边的指针
j = len(List) - 1 #右边的指针
base = 0 #保存分隔位置
while i < j:
while i < j and List[j] >= List[0]: #从右向左找第一个比base小的
j -= 1
while i < j and List[i] <= List[0]: #从左往右找第一个比base大的
i += 1
if i == j: # 找到base的位置
temp = List[0]
List[0] = List[i]
List[i] = temp
base = i
else: #交换ij位置
temp = List[i]
List[i] = List[j]
List[j] = temp
#返回 left + base + right
left = QuickSort(List[0:base])
right = QuickSort(List[base+1:])
left.append(List[base])
return left + right
使用in-place的方法来操作list:
def quickSort(List, start, end):
if end - start <= 0: # exit here
return
ii = start
jj = end
while start < end:
while List[end] >= List[ii] and start < end:
end -=1
while List[start] <= List[ii] and start < end:
start +=1
List[start], List[end] = List[end], List[start]
base = start
List[ii], List[base] = List[base], List[ii]
quickSort(List, ii, base -1)
quickSort(List, base+1, jj)
8.2 Quick Select
使用Quick select 来得到一个无序数组中第K大的值:其实就是通过partition的特质,我们找到第K的位置的值它的前面都是比它小的,她的右边都是比它大的。
a = [200,1,20,80]
k = 4
def quickSelect(list1, left, right, K):
print(list1)
storeLeft = left
storeRight = right
piviot = list1[left]
while left < right:
while left < right and list1[right] >= piviot:
right -=1
while left < right and list1[left] <= piviot:
left += 1
list1[left], list1[right] = list1[right], list1[left]
list1[storeLeft], list1[right] = list1[right], list1[storeLeft]
#print(list1[storeLeft])
if left == K:
pass
elif left < K:
quickSelect(list1, left + 1, storeRight, K)
else: # left > K
quickSelect(list1, storeLeft, left -1, 1)
quickSelect(a, 0, len(a) - 1, k-1)
print(a[k-1])
9. Heap Sort
1. 对每一个非叶子节点,进行sink()操作: 从 i = N /2 开始
Sink:如果父节点小于子节点,则将父节点与最大子节点进行交换。
2.对所有节点进行remove操作:
Remove: 将最小值(数组最后一个值与根节点互换,然后进行sink操作)