一,分治
分治算法的基本思想是将一个规模为N的问题分解为K个规模较小的子问题,这些子问题相互独立且与原问题性质相同。求出子问题的解,就可得到原问题的解。
如果这些子问题还较大,难以解决,可以再把它们分成几个更小的子问题,以此类推,直至可以直接求出解为止。这就是分治策略的基本思想。
即一种分目标完成程序算法,简单问题可用二分法完成。
二,生活案例
1,找出伪币
16枚硬币,不同面值,有可能有一枚假币,假币比真币轻。有一架天平,用最少称量次数确定有没有假币,若有的话,假币是哪一枚?
分治策略思路:将同面值硬币分类,称量。结果为无假币或者确定假币的一面值 。再均分,称量。
三,解题步骤
(1)分解。将要解决的问题划分成若干规模较小的同类问题;
(2)求解。当子问题划分得足够小时,用较简单的方法解决;
(3)合并。按原问题的要求,将子问题的解逐层合并构成原问题的解。
四,归并排序
手动演算
代码实现
def Merge(s1, s2, s):
i = j = 0 # 两段数组放在起始位置的指针
while (i + j) < len(s): # 双指针长度小于该s总长度就一直进行
if j == len(s2) or (i < len(s1) and s1[i] < s2[j]): # 如果i指针指向数小于j指针指向数且i没走到头,或者j走到头了
s[j + i] = s1[i] # 那么将s1数赋给s
i += 1 # i往后走一位
else: # 其他情况(i走到头了,或者j没走到头情况下j指向的数小于i指向的数)
s[i + j] = s2[j] # s2数赋给s
j += 1 # j往后走一位
def Merge_Sort(s): # 将数组拆分
n = len(s)
if n < 2: # 数组长度是1时,不拆分直接返回
return
mid = n // 2
s1 = s[0:mid] # 将数组拆分为两段
s2 = s[mid:n]
Merge_Sort(s1) # 递归,将两段数组再分别进行拆分
Merge_Sort(s2)
Merge(s1, s2, s) # 将拆分好的数组组合
if __name__ == "__main__":
s = [1, 4, 2, 9, 6, 77]
Merge_Sort(s)
print(s) # 输出
五,快速排序
手动演算
代码
def Quick_Sort(a, start, end):
if start >= end: # 退出递归的条件
return
pivot = a[start] # 设起始基准元素
left = start #左指针
right = end #右指针
while left < right: #右指针大于基准数条件向右扫描
while a[right] > pivot:
right -= 1
a[left] = a[right] #右指针小于基准数和左指针数交换
while a[left] < pivot: #左指针小于基准数向左扫描
left += 1
a[right] = a[left] #左指针大于基准数和右指针数交换
a[right] = pivot #当指针相遇时,基准数填入指针所指的空缺位置中
Quick_Sort(a, start, left - 1) #将基准数之前的数再排列
Quick_Sort(a, left + 1, end) #将基准数之后的数再排列
if __name__ == "__main__": #告诉程序在main中进行
a = [5, 4, 7, 2, 9, 1, 77]
Quick_Sort(a, 0, len(a) - 1)
print(a)