在观看本文章之前,推荐链接: 视觉算法
该辅助工具提供了对代码进行可视化的界面,帮助更能够理解
不仅仅只有排序,还有二叉树,递归,哈希表等的可视化。
冒泡排序比较简单,每一次都对相邻的两个数进行比较,前者大于后者就进行位置交换,是原地排序算法
def bubble_sort(alist):
for i in range(len(alist)):
for j in range(i+1,len(alist)-1):
if alist[j] > alist[j+1]:
alist[j],alist[j+1] = alist[j+1],alist[j]
return alist
alist = [1,2,5,3,8,4]
print(bubble_sort(alist))
插入排序更倾向于维护动态的数据有序,插入排序也是原地排序算法
def insert_sort(alist):
for i in range(1,len(alist)):
val = alist[i]
j = i-1
for j in range(i-1,0,-1):
if alist[j] > val:
alist[j+1] = alist[j]
else:
break
alist[j+1] = val
return alist
print(insert_sort(alist))
"方法2"
def insert_sort_2(alist):
for i in range(1,len(alist)):
val = alist[i]
while i > 0 and alist[i-1] > val:
alist[i] = alist[i-1]
i = i-1
alist[i] = val
return alist
print(insert_sort_2(alist))
选择排序是类似插入排序的,同样将一个数组分成两个部分,一个部分已经排序,另一个部分未排。其原理在于找到最小的数与第一个数交换,倒数第二小的数与第二个数交换,选择排序是一种不稳定算法。
def sel_sort(alist):
for i in range(len(alist)-1):
min_num = i
for j in range(i,len(alist)):
if alist[j]<alist[min_num]:
min_num = j
tem = alist[i]
alist[i] = alist[min_num]
alist[min_num] = tem
return alist
print(sel_sort(alist))
shell排序算法在最好的情况下其时间复杂度是O(n)的,其本身对数组进行间隔划分子列表,每个子列表都进行插入排序。
所有子列表的间隔一般都是n/2开始,到n/4,n/8一直到n。
def shell_sort(alist):
mid = len(alist)//2
while mid > 0:
for i in range(mid):
gap_insert_sort(alist,i,mid)
mid = mid//2
return alist
def gap_insert_sort(alist,start,gap):
for i in range(start+gap,len(alist),gap):
cur = alist[i]
pos = i
while i >= gap and alist[pos-gap] > cur:
alist[pos] = alist[pos-gap]
pos = pos-gap
alist[pos] = cur
print('shell_sort排序',sel_sort(alist))
快速排序利用了分治的思想,但它不同于归并排序算法的是,它任然是一种原地排序算法,解决了归并排序算法太耗费内存的问题。
def quick_sort(alist):
return q_sort(alist,0,len(alist)-1)
def partition(alist,first,last):
pivot = alist[first]
left = first+1
right = last
done = False
while not done:
while left <= right and alist[left] <= pivot:
left = left+1
while alist[right] > pivot and right >= left:
right = right-1
if right < left:
done = True
else:
tem = alist[left]
alist[left] = alist[right]
alist[right] = tem
temp = alist[first]
alist[first] = alist[right]
alist[right] = temp
return right
def q_sort(alist,first,last):
if first < last:
split = partition(alist,first,last)
q_sort(alist,first,split-1)
q_sort(alist,split+1,last)
return alist
print('快速',quick_sort(alist))
归并排序,其实就是分治思维和递归结合。
将一个数组不断的分解成小数组进行解决。
当然该排序方法时间复杂度为O(nlogn),也不是不需要付出代价的,它不是一个原地排序算法,它需要借助非常量级的额外储存空间,当然,内存大当我没说,哈哈哈哈
def merge_sort(alist):
if len(alist) <= 1:
return alist
mid = len(alist)//2
left = merge_sort(alist[:mid])
right = merge_sort(alist[mid:])
merge_list = []
while left and right:
if left[0] <= right[0]:
merge_list.append(left.pop(0))
else:
merge_list.append(right.pop(0))
merge_list.extend(right if right else left)
return merge_list
print(merge_sort(alist))
'''
归并排序麻烦算法
'''
def merge_sort_diff(alist):
if len(alist) > 1:
mid = len(alist)//2
left = alist[:mid]
right = alist[mid:]
#递归调用
merge_sort_diff(left)
merge_sort_diff(right)
i = j = k = 0
while i < len(left) and j <len(right):
if left[i] < right[j]:
alist[k] = left[i]
i = i+1
else:
alist[k] = right[j]
j = j+1
k = k+1
# 归并左
while i < len(left):
alist[k] = left[i]
i = i+1
k = k+1
# 归并右
while j < len(right):
alist[k] = right[j]
j = j+1
k = k+1
return alist
print(merge_sort_diff(alist))
什么是计数排序呢?
其实计数排序是桶排序中的一种,特殊情况,当排序的数据量并不大时,直接将所有的数据分到不同的桶中,每个桶放一个数据,就节省了桶内排序的时间。
关于桶排序,我推荐的大佬的博客
def count_sort(alist):
if len(alist) <= 1:
return alist
max = alist[0]
for i in range(i,len(alist)):
if max < alist[i]:
max = alist[i]
c = max+1
for j in range(max+1):
c[i] = 0
for m in range(len(alist)):
c[alist[m]] = c[alist[m]]+1
for n in range(1,max+1):
c[i] = c[i-1]+c[i]
r = len(alist)
for k in range(len(alist)-1,0,-1):
index = c[alist[i]]-1
r[index] = alist[i]
c[alist[i]] = c[alist[i]]-1
for l in range(len(alist)):
alist[i] = r[i]
return alist
print(alist)
二分查找也叫折半查找,当你搜寻一个数时,你将排序完成的数组,进行取中值进行查询,比中值大就选右边,比中值小就选左边,同时丢弃令一边,举个例子:
当你的数据量有2的32次方那么大时,这个数据有多大呢,大约是40亿,你每次查找的数据都是上一次数据的二分之一,就是n,n/2,n/3,n/4…n/(2^k),一个等比数列,所以当n/(2 ^k)=1时,得到以2为底的对数k=log2(n),所以,即使数据量达到2 ^32次方那么大时,也只是需要32次就可以得到结果,其效率是超级高的。
但其缺点也相对比较明显,虽然时间复杂度是O(logn),但二分查找是通过下标进行查询的,所以相对而说,并不适合链表,同时当数据量太大时,数据通过列表的方式进行存储显然是不合理的。所以数据太大了,也不是很好处理。
'''
二分查找
'''
def binary_search(alist,val):
first = 0
last = len(alist)-1
while first <= last:
mid = first+(last-first)//2
if alist[mid] == val:
return mid
else:
if val < alist[mid]:
last = mid-1
else:
first = mid+1
return -1
alist = [1,2,5,3,8,4]
print(binary_search(alist,8))
'''
二分查找
递归
'''
def binary_search_2(alist,n,val):
return binary_search_3(alist,0,n-1,val)
def binary_search_3(alist,first,last,val):
if first >= last:
return -1
mid = (first+last)//2
if alist[mid] < val:
return binary_search_3(alist,mid+1,last,val)
elif alist[mid] > val:
return binary_search_3(alist,first,mid-1,val)
else:
return mid
print(binary_search_2(alist,len(alist),8))