选择排序
核心思想:给定一个数组,如何将这个数组进行排序得到一个有序的序列。
常规的选择最小值,放置,最终有序的过程
【3,2,11,-9,0,12】
1. -9 【-9,3,2,11,0,12】
2. 0 【-9,0,3,2,11,12】
3. 。。。。。
选择排序的排序过程
【3,2,11,-9,0,12】
1. 选择数组从索引0-(length-1)中最小的元素的索引,和第一个元素(索引为0)交换位置 ------>【-9,2,11,3,0,12】
2.选择数组从索引1-(length-1)中最小的元素的索引,和第二个元素(索引为1)交换位置------>【-9,0,11,3,2,12】
3.选择数组从索引2-(length-1)中最小的元素的索引,和第三个元素(索引为2)交换位置------>【-9,0,2,3,11,12】
4。。。。
结论:
1. 选择的次数为len(arr)
2. 选择的序列是逐渐缩短的
#时间复杂度分析:
[1-n)------>n-1
[2-n]------>n-2
[3-n)------>n-3
…
n-1+n-2+n-3+…1------>(n2-n)/2
n-1+n-2+n-3+…1=(n2-n)/2------>O(n22)
#稳定性 [-129893,-9,2,2,12,12,0,-9,0,20]------>不稳定
#代码实现:
def selectSort(arr):
# 1. 选择的次数为len(arr)
# 2. 选择的序列是逐渐缩短的
length = len(arr)
for i in range(length):#选择多少次
min_value_index = i#假定最小元素的索引为i
#找数组中最小元素的索引
for j in range(i+1,length):
if arr[j]<arr[min_value_index]:
min_value_index = j
#放置到对应的位置
arr[i],arr[min_value_index] = arr[min_value_index],arr[i]
return arr
arr = [-9,9,2,2,12,12,0,129893,0,20]
print(selectSort(arr))
堆排序
满二叉树:除最后一层无任何子节点外,每一层上的所有结点都有两个子结点的二叉树
堆的特点:
定义任意节点的索引为i
左子节点索引2i+1
右子节点的索引2i+2
对于一个大顶堆来说最大的元素必然是堆顶的元素
堆排序的算法核心思想:
1. 建堆(保证了最大元素是堆顶)
2. 把堆顶元素和最后一个元素交换(最大的元素就是在最后一个位置了)
3.调整堆结构,使堆满足堆的条件(注意点,调整的时候不再考虑最后一个元素了)
4.调整以后,堆又满足了堆的条件
5. 此时将堆顶元素和倒数第二个元素交换。。。
6. 调整。。。。交换。。。调整。。。。交换
考虑实现过程:
1. 如何让我们的数组满足堆的定义------>解决方案:建堆
-构建堆的过程:
(1) 先从堆的最后一个非叶子节点开始,进行调整
对于一个长度为n的数组来说,映射到堆的定义上来说,最后一个非叶子节点的索引为n//2-1
(2)找到第二个非叶子节点进行调整
(3) 。。。。
(4) 一直找到最后一个非叶子节点进行调整
2. 堆顶和最后一个元素进行交换(换完了以后堆的结构被破坏了,但是最后一个元素可以确定是最大的元素)
3.调整堆的过程的时候,交换位置可能导致子节点为跟的堆被破坏结构,这个时候要继续坚持以该节点为根的结构是否满足堆结构,不满足,则需要交换
4.-调整完了以后,继续换堆顶元素和倒数第二个元素的位置(此时保证了最大元素和倒数第二大的元素在最后2个位置)
-缩小堆的规模,继续调整堆
-换位置
-缩小堆的规模,继续调整堆
-换位置
-缩小堆的规模,继续调整堆
-换位置
-缩小堆的规模,继续调整堆
-换位置。。。。
#代码实现
def heapify(arr,action_node_index,length):
"""
arr :传入的数组
action_node_index:待调整的堆的节点索引
length:是堆的规模
"""
left_child_index = 2*action_node_index+1
right_child_index = 2*action_node_index+2
max_value_index = action_node_index
#分别和左右子节点进行比较,找到最大的值对应的index
if left_child_index<length and arr[left_child_index]>arr[max_value_index]:
max_value_index = left_child_index
if right_child_index<length and arr[right_child_index]>arr[max_value_index]:
max_value_index = right_child_index
#如果最大值的索引发生了变化
if max_value_index!=action_node_index:
arr[action_node_index],arr[max_value_index]=arr[max_value_index],arr[action_node_index]
#因为位置交换可能导致被交换的地方的堆不满足堆的结构,因此继续调整基于该节点为根的堆结构
heapify(arr,max_value_index,length)
def buildheapify(arr):
#先从堆的最后一个非叶子节点开始,进行调整
for i in range(len(arr)//2-1,-1,-1):
heapify(arr,i,len(arr))
return arr
def heapifySort(arr):
length = len(arr)
buildheapify(arr)
for i in range(length):
#做交换
arr[0],arr[length-1-i] = arr[length-1-i],arr[0]
#调整堆结构
heapify(arr,0,length-1-i)
return arr
#arr = [1,39,21,1,12,2,0]
arr = [-129893,-9,2,2,12,12,0,-9,0,20]
print(heapifySort(arr))