一、快速排序(用得最多)
1.1 算法思路
有一个游标Low和游标High,分别指向第一个元素和最后一个元素,先取一个Mid_value = 第一个值,然后Low指向的数据和Mid_value比较一下,如果Low < Mid_value, 那么Low +=1 , 因为小的值是排在左边的,否则,Low不动,High指向的数据和Mid_value比较一下,如果High < Mid_value, 那么High -= 1, 因为大的值是排在右边的。当High和Low重合的时候,则停止,把Mid_value的值放到这里来。然后,达到目标:Mid_value左边的值都比Mid_value小,右边的值都比Mid_value大,然后对于左边和右边,继续做一样的操作,直到左边/右边只剩下一个数,就停止(递归方式)
1.2 代码实现:
def quick_sort(alist
):
"""快速排序"""
n
= len(alist
)
mid_value
= alist
[0]
low
= o
high
= n
-1
while low
< 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
]
alist
[low
] = mid_value
1.3 修改(引入first、last):
def quick_sort(alist,first
,last
):
"""快速排序"""
if first
>= last
:
return
mid_value
= alist
[0]
low
= first
high
= last
while low
< 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
]
alist
[low
] = mid_value
quick_sort
(alist,first
,low
-1)
quick_sort
(alist
,low
+1,last
)
if __name__
== "__main__":
alist
= [54,26,93,17,77,31,44,55,20]
quick_sort
(alist
,0,len(alist
)-1)
print(alist
)
1.4 时间复杂度
最优时间复杂度:O(nlogn) 最坏时间复杂度:O(n^2) 稳定性:不稳定
二、归并排序
2.1 算法思路:
拿上面例子举例,先对半分,每组再对半分,每组再对半分,直到分成每组只有一个值为止。然后开始归并,就是同样的过程反过来来一遍:组成两个为一组,组成四个为一组
归并的时候有两个游标,一个left,一个right, left指的值和right指的值比较,具体流程如下:
以这个为例
比较left指的小还是right指的小,left指的小,所以拿出来,left再右移一位
比较left指的小还是right指的小,right指的小,所以拿出来,right再左移一位
最后把77放在最右边
2.2 代码实现
def merge_sort(alist
):
"""归并排序"""
n
= len(alist
)
if n
<= 1:
return alist
mid
= n
//2
left_li
= merge_sort
(alist
[:num
])
right_li
= merge_sort
(alist
[num
:])
merge
(left
,right
)
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_pionter
])
else:
result
.append
(right_li
[right_pointer
])
right_pointer
+= 1
result
+= left_li
(left_pointer
)
result
+= right_li
(right_pointer
)
return result
if __name__
== "__main__":
li
= [54,26,93,17,77,31,44,55,20]
print(li
)
sorted_li
= merge_sort
(li
)
print(li
)
print(sorted_li
)
2.3 时间复杂度
最优时间复杂度:O(nlogn) 最坏时间复杂度:O(nlogn) 稳定性:稳定
三、搜索
搜索是在一个项目集合中找到一个特定项目的算法过程。搜索通常的答案是真的或假的,因为该项目是否存在。 搜索的几种常见方法:顺序查找、二分法查找、二叉树查找、哈希查找
四、二分查找
二分查找又称折半查找,优点是比较次数少,查找速度快,平均性能好;其缺点是要求待查表为有序表,且插入删除困难。因此,折半查找方法适用于不经常变动而查找频繁的有序列表。首先,假设表中元素是按升序排列,将表中间位置记录的关键字与查找关键字比较,如果两者相等,则查找成功;否则利用中间位置记录将表分成前、后两个子表,如果中间位置记录的关键字大于查找关键字,则进一步查找前一子表,否则进一步查找后一子表。重复以上过程,直到找到满足条件的记录,使查找成功,或直到子表不存在为止,此时查找不成功。
4.1 代码实现
前提是,已经排序,并且每个数据都相邻存储
4.1.1递归版本
def binary_search(alist
, item
):
if len(alist
) == 0:
return False
else:
midpoint
= len(alist
)//2
if alist
[midpoint
]==item
:
return True
else:
if item
<alist
[midpoint
]:
return binary_search
(alist
[:midpoint
],item
)
else:
return binary_search
(alist
[midpoint
+1:],item
)
if __name__
== "__main__":
testlist
= [0, 1, 2, 8, 13, 17, 19, 32, 42,]
print(binary_search
(testlist
, 3))
print(binary_search
(testlist
, 13))
4.1.2非递归版本(划分查找范围)
def binary_search(alist
, item
):
first
= 0
last
= len(alist
)-1
while first
<=last
:
midpoint
= (first
+ last
)/2
if alist
[midpoint
] == item
:
return True
elif item
< alist
[midpoint
]:
last
= midpoint
-1
else:
first
= midpoint
+1
return False
if __name__
== "__main__":
testlist
= [0, 1, 2, 8, 13, 17, 19, 32, 42,]
print(binary_search
(testlist
, 3))
print(binary_search
(testlist
, 13))
4.2 时间复杂度
最优时间复杂度:O(1) 最坏时间复杂度:O(logn)