排序算法

排序算法的稳定性:让原本相等的键值维持的纪录维持相对次序

冒泡排序(BUbble Sort)

从头往后走,每次比较相邻的两个数字,一次循环将最大(最小)的数字放在最后,经过n-1次冒泡完成排序。

冒泡:每次将最大的值往后移到相应的位置(第一次最大,第二次次大,依次往后)

关键代码

for i in range(n-1):
flag = 0
for j in range(n-1-j):
if bubble[j] > bubble[j+1]:
bubble[j], bubble[j+1] = bubble[j+1], bubble[j]
flag = 1
if flag == 0: #该序列不需要进行排序
return bubble

时间复杂度:O(n2)

稳定性:稳定

选择排序

从未排序的序列中选择一个次小的让前面去放

关键代码

n = len(alist)
for j in range(n-1):
min_index = j
for i in range(j+1, n):
if alist[min_index] > alist[i]:
min_index = i
alist[j], alist[min_index] = alist[min_index], alist[j]

时间复杂度:O(n2)

稳定性:不稳定

插入算法

把后面序列的数字插入到前面序列合适的位置

关键代码

for i in range(1, n):
while i > 0:
if alist[i] < alist[i-1]:
alist[i], alist[i-1] = alist[i-1], alist[i]
i -= 1
else:
break

时间复杂度:O(n2)

稳定性:稳定

希尔排序

对插入算法的改进。其基本思想是:先比较距离远的元素,而不是像简单交换排序算法那样先比较相邻的元素,这样可以快速减少大量的无序情况,从而减轻后续的工作。被比较的元素之间的距离逐步减少,直到减少为1,这时的排序变成了相邻元素的互换。

关键代码实现

def shell_sort(alist):
"""希尔排序"""
n = len(alist)
gap = n//2

while gap > 0:
for j in range(gap, n):
i = j
while i > 0:
if alist[i] < alist[i-gap]:
alist[i], alist[i-gap] = alist[i-gap], alist[i]
i -= gap
else:
break
gap //= 2

最坏时间复杂度:O(n2)

稳定性:不稳定

快速排序

基本思想:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。

关键代码

def quick_sort(alist, first, last):
if first == last:
return
mid_value = alist[0]
low = firsst
high = last

while low < high:
#high左移
while low < high and alist[high] >= mid_value:
high -= 1
alist[low] = alist[high]

while low < high and alist[low] < mid_value:
low += 1
alist[high] = alist[low]
#从循环退出,low==high
alist[low] = mid_value

对low左边进行快速排序

quick_sort(alist, first, low-1)
#对low右边的列表进行快速排序
quick_sort(alist, low+1, last)

最优时间复杂度: O(nlogn) (经过多少次对半折分可以拆到1,nlog2n)

最坏时间复杂度:O(n2)

稳定性:不稳定

归并算法

基本思想:先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,即二路归并

关键代码

def merge_sort(alist):
"""归并排序"""
n = len(alist)
if n <= 1
return alist
mid == n//2

left采用归并排序后形成的有序的新的列表

left_li = merge_sort(alist[:mid])

right采用归并排序后形成的有序的新的列表

right_li = merge_sort(alist[mid:])

left_pointer, right_pointer = 0, 0
result = []

while left_pointer < len(left_li) and right_pointer < len(right_li):
if left_li[left_pointer] <= right_li[right_pointer]:
result.append(left_li[left_pointer])
left_pointer += 1
elif:
result.append(right_li[right_pointer])
right_pointer += 1

result += left_li[left_pointer:]
result += right_li[right_pointer:]
return result

最优时间复杂度:O(nlogn) (理解:纵向是logn级序列拆分,横向进行n次比较)

最坏时间复杂度:O(nlogn)

稳定性:稳定

时间上是最小的,但是空间上,需要额外的开销,前面的算法是在原有的列表上进行排序的。

搜索算法——二分查找

二分查找,又称为折半查找。查找对象:有序的顺序表。

def binary_search(alist, item):
"""二分查找"""
n = len(alist)
if n > 0:
mid = n//2
if alist[mid] == item:
return True
elif item < alist[mid]:
return binary_search(alist[:mid], item)
else:
return binary_search(alist[mid:], item)
return False

非递归

def binary_search(alist, item):
"""二分查找,非递归"""
n = len(alist)
first = 0
last = n-1
while first <= last:
mid = (first + last)//2
if alist[mid] == item:
return True
elif alist[mid] > item:
last = mid -1
else:
first = mid + 1
return False

最坏时间复杂度:O(logn) (普通遍历查找时间复杂度是O(n))

最优时间复杂度:O(1)

posted @ 2018-05-15 15:09  wemo  阅读(208)  评论(0)    收藏  举报