一、算法概念
1、Algorithm:一个计算的过程,解决问题的方法
汉诺塔问题
def hanoi(n, a, b, c):
if n > 0:
hanoi(n-1, a, c, b)
asd = '从%s到%s' % (a, c)
list1.append(asd)
hanoi(n-1, b, a, c)
return len(list1)
二、查找
一、在一些数据元素中,通过一定的方法找出与给定关键字相同的数据元素的过程。
1、计算程序运行时间的装饰器
def cal_time(func):
def wrapper(*args, **kwargs):
t1 = time.time()
result = func(*args, **kwargs)
t2 = time.time()
print('%s running time : %s secs.' %(func.__name__, (t2 - t1)))
return result
return wrapper
@cal_time
def linear_search(li,val):
for ind, v in enumerate(li):
if v == val:
return ind
else:
return None
#二分查找函数
@cal_time
def binary_search(li,val):
left = 0
right = len(li) - 1
while left <= right:
mid = (left + right) // 2
if li[mid] == val:
return mid
elif li[mid] > val:
right = mid - 1
else:
left = mid + 1
else:
return None
调用比较
list2 = list(range(1000000))
linear_search(list2, 288888)
binary_search(list2, 288888)
三、一般排序
一、概念:将一组无序的记录调整为有序的记录
1、冒泡排序
def bubble_sort(li):
for i in range(len(li)-1):
exchage = False
for k in range(len(li)-i-1):
if li[k] > li[k+1]:
li[k], li[k+1] = li[k+1], li[k]
exchage = True
if not exchage:
return li
return li
li = [6,2,12,1,32,34,24,3,4,134]
print(bubble_sort(li))
2、选择排序
def select_sort(li):
for i in range(len(li)-1):
min_loc = i
for j in range(i+1,len(li)):
if li[j] < li[min_loc]:
min_loc = j
if min_loc != i :
li[min_loc],li[i] = li[i],li[min_loc]
return li
li = [6,2,12,1,32,34,24,3,4,134]
print(select_sort(li))
3、插入排序法
#插入排序法
def insert_sort(li):
for i in range(1, len(li)): #摸到的牌的下标
tmp = li[i]
j = i-1
while j >= 0 and tmp < li[j]:
li[j+1] = li[j]
j -= 1
li[j+1] = tmp
return li
li = [6,2,12,1,32,34,24,3,4,134]
print(insert_sort(li))
四、快速排序
一、快速排序
#第一次取中间值,左边小,右边大
def partition(li, left, right):
tmp = li[left]
while left < right:
while li[right] > tmp and left < right:
right -= 1
li[left] = li[right]
while li[left] < tmp and left < right:
left += 1
li[right] = li[left]
li[left] = tmp
return left
#快速排序框架,左边、右边分别调用,
def _quick_sort(li, left, right):
if left < right:
mid = partition(li, left, right)
_quick_sort(li, left, mid-1)
_quick_sort(li, mid+1, right)
#装饰器不能用在递归函数上,所以再写一个函数
@cal_time
def quick_sort(li):
_quick_sort(li, 0, len(li)-1)
#创建一个乱序列表,调用看时间
li = list(range(10000))
random.shuffle(li)
quick_sort(li)
二、堆排序
1、堆:一种特殊的完全二叉树结构
大根堆:任一节点都比孩子节点大
小根堆:任一节点都比孩子节点小
2、堆排序:
堆的向下调整性质:假设:节点的左右子树都是堆,但自身不是堆。
当根节点的左右子树都是堆时,可以通过一次向下调整来将其变换成一个堆。
3、堆排序的过程:
(1)建立堆
(2)得到堆顶元素,为最大元素
(3)去掉堆顶,将堆最后一个元素,放到堆顶。此时可以通过一次向下调整重新使堆有序。
(4)堆顶元素为第二大元素
(5)重复步骤3,知道堆变空
4、构造堆(农村包围城市)
从最后一个非叶子节点开始调整,倒着走,把大的往上调,就可以构造一个堆。
5、代码实现
def sift(li, low, high):
"""
堆的向下调整性质:假设:节点的左右子树都是堆,但自身不是堆,这个函数把它变成堆
:param li: 列表
:param low: 堆的根节点下标,不是堆的位置
:param high: 堆的最后一个元素的下标
:return:
"""
i = low # i最开始指向根节点
j = 2*i+1 # j开始是左孩子
tmp = li[low] # 把堆顶存起来
while j <= high: # j没有超出堆的个数
if j+1 <= high and li[j+1] > li[j]: # 右边有孩子且比左边的大
j = j+1 # 把j指向大孩子
if li[j] > tmp: # 把大孩子与父亲比较,大孩子比父亲大
li[i] = li[j] # 大孩子顶上去
i = j # 往下走一层
j = 2*i+1
else:
li[i] = tmp # 大孩子比父亲小,直接让父亲坐上去
break
else:
li[i] = tmp # j超出堆的个数,说明堆顶就是叶子节点,就直接坐上去
@cal_time
def heap_sort(li):
n = len(li)
for i in range((n-2)//2, -1, -1): # 循环建堆,从最后一个非叶子节点开始,循环到根
sift(li, i, n-1) # 向下调整,建堆的方法,建堆完成
for i in range(n-1, -1, -1):
li[0], li[i] = li[i], li[0]
sift(li, 0, i-1) # i-1是新的high
li1 = list(range(10000))
random.shuffle(li1)
heap_sort(li1)
6、堆排序的应用,计算topk(排行榜前几)
思路:将一组列表前k组成一个小根堆,遍历剩下的元素,打的元素替换掉小根堆的根,然后向下调整建堆,直到所有元素比较完。然后这个堆就是前k大元素,然后出数。
import random
def sift(li, low, high):
"""
堆的向下调整性质:假设:节点的左右子树都是堆,但自身不是堆,这个函数把它变成堆
:param li: 列表
:param low: 堆的根节点下标,不是堆的位置
:param high: 堆的最后一个元素的下标
:return:
"""
i = low # i最开始指向根节点
j = 2*i+1 # j开始是左孩子
tmp = li[low] # 把堆顶存起来
while j <= high: # j没有超出堆的个数
if j+1 <= high and li[j+1] < li[j]: # 右边有孩子且比左边的大
j = j+1 # 把j指向大孩子
if li[j] < tmp: # 把大孩子与父亲比较,大孩子比父亲大
li[i] = li[j] # 大孩子顶上去
i = j # 往下走一层
j = 2*i+1
else:
li[i] = tmp # 大孩子比父亲小,直接让父亲坐上去
break
else:
li[i] = tmp # j超出堆的个数,说明堆顶就是叶子节点,就直接坐上去
def topk(li, k):
heap = li[0:k]
for i in range((k-2)//2, -1, -1): # 循环建堆,从最后一个非叶子节点开始,循环到根
sift(heap, i, k-1) # 向下调整,建堆的方法,建堆完成
for i in range(k, len(li)-1): # 遍历k后面的,与小根堆的根比较大小,把小的换下来
if li[i] > heap[0]:
heap[0] = li[i]
sift(heap, 0, k-1)
for i in range(k-1, -1, -1): # 出数
heap[0], heap[i] = heap[i], heap[0]
sift(heap, 0, i-1) # i-1是新的high
return heap
li1 = list(range(1000))
random.shuffle(li1)
print(topk(li1, 10))
三、归并排序
思路:将一组列表分成只有一个或零个元素的列表,然后归并
代码实现
import random
def merge(li, low, mid, high):
i = low
j = mid +1
ltmp = []
while i <= mid and j <= high:
if li[i] < li[j]:
ltmp.append(li[i])
i += 1
else:
ltmp.append(li[j])
j += 1
# while 执行完,肯定有一部分没数了
while i <= mid:
ltmp.append(li[i])
i += 1
while j <=high:
ltmp.append(li[j])
j += 1
li[low:high+1] = ltmp
def merge_sort(li, low, high):
if low < high:
mid = (low + high) // 2
merge_sort(li, low, mid)
merge_sort(li, mid+1, high)
merge(li, low, mid, high)
li1 = list(range(100))
random.shuffle(li1)
merge_sort(li1, 0, len(li1)-1)
print(li1)