class Sort(object):
# 八大排序算法
def bubble_sort(self, nums):
"""
采用冒泡排序:依次将最大值冒泡到最后一个位置,经过两轮循环实现
:param nums: 待排序的数组
"""
length = len(nums)
if length <= 1:
return nums
for i in range(0, length):
for j in range(0, length - i - 1):
if nums[j] > nums[j + 1]:
nums[j], nums[j + 1] = nums[j + 1], nums[j]
return nums
def select_sort(self, nums):
"""
插入排序法:从a[0, n-1]寻找最小值和a[0]交换,从a[1, n-1]寻找最小值和a[1]交换,循环遍历
直到经过第(n-1)轮交换,将a[n-1, n-2]中最小值与a[n-2]交换,完成排序。
:param nums: 待排序的数组
"""
n = len(nums)
if n <= 1:
return nums
for i in range(0, n - 1):
for j in range(i + 1, n):
if nums[j] < nums[i]:
nums[i], nums[j] = nums[j], nums[i]
return nums
def insert_sort(self, nums):
"""
将待排序的数组看成两部分:有序表和无序表,有序表为nums[0]
无序表为nums[1, n-1],从无序表中取出数据插入到有序表中,直到插完为止。
就是将要插入的数字和下标记录下来,和挨个和前边的比较,
如果大于前边的或者前边已经没有数了,那就插入到这个位置
:param nums: 待排序的数组
"""
n = len(nums)
if n <= 1:
return nums
for i in range(1, n):
in_num = nums[i]
index = i
while i - 1 >= 0 and in_num < nums[i - 1]:
nums[i] = nums[i - 1]
i -= 1
nums[i] = in_num
return nums
def shell_sort(self, nums):
"""
插入排序的高效版,也称缩小增量排序。按增量分组,对每组使用插入排序
随着增量减少,每组包含的个数增多,直到增量为1时,完成排序。
插入标准:前边没数了,或者大于前边的了
shell排序第一步就好似把一个数组分成n分,然后进行n个插入排序,这样大大的减少了遍历次数
:param nums:待排序的数组
"""
n = len(nums)
if n <= 1:
return nums
gap = n // 2
while gap >= 1:
for i in range(gap, n):
in_index = i
in_val = nums[i]
while i - gap >= 0 and in_val < nums[i - gap]:
nums[i] = nums[i - gap]
i -= gap
nums[i] = in_val
gap //= 2
return nums
def fast_sort(self, nums, start, end):
"""
快速排序就是选一个值,将比他大的都放在他的右边,比他小的都放在他的左边
他变换的方式是两个指针分别从右左开始遍历,右边遇到小的停下来,然后左边遇到大的
停下来,让后两个数交换,这样两个指针最终会直到一块内存上,即索引值相同,
这时候你会明白,从右边先开始遍历就可以保证最终指向的这个数他是小于或等于开始选的那个值的。
这一点可以细细品味,然后将这个索引值和基准值进行交换,这样一个数组就可以看做两部分,
基准值的左边都比他小,右边都比他大,当然这只是看做两个部分,他一直都只是一个数组没有拆分
仅仅是在操作指针在变化。经过这些操作基准值在数组中的位置就确定下来了,剩下的用递归来完成
直到所有的基准值找到自己在数组中的位置。
这个操作就好像为每个数找自己的位置,只要这个位置前边的数都小于自己,后边的数都大于自己
那这个位置就是自己的。
:param nums:待排序数组
:param left:数组的起始索引
:param right:数组的最后值索引
"""
if start >= end:
return nums
piv = nums[start]
left = start
right = end
while left < right:
while right > left and nums[right] >= piv:
right -= 1
while left < right and nums[left] <= piv:
left += 1
nums[right], nums[left] = nums[left], nums[right]
nums[start], nums[right] = nums[right], nums[start]
self.fast_sort(nums, start, right - 1)
self.fast_sort(nums, right + 1, end)
return nums
def merge_sort(self, nums):
n = len(nums)
if n <= 1:
return
mid = n // 2
s1 = nums[0 : mid]
s2 = nums[mid : n]
self.merge_sort(s1)
self.merge_sort(s2)
self.merge(s1, s2, nums)
return nums
def merge(self, s1, s2, s):
i = j = 0
while i + j < len(s):
if j == len(s2) or (i < len(s1) and s1[i] < s2[j]):
s[i + j] = s1[i]
i += 1
else:
s[i + j] = s2[j]
j += 1
def radix_sort(self, nums):
"""
基数排序(桶排序)
这个算法暂时只适用于正数排序
1、找出最大值 2、测出最大值的位数 3、创建10个桶分别存放0-9
4、分别遍历数的各位一位,按照数存到相应的桶里,这样保证前面的位数都相同时,小的可以放在前面
5、清空数组,遍历桶将里边的数存到数组里循环 4 步骤遍历十位、百位等。
:param nums: 待排序的数组
:return: 排序完毕的数组
"""
n = len(nums)
if n < 2:
return
max_nums = max(nums)
max_len = len(str(max_nums))
i = 0
while i < max_len:
list = [[] for _ in range(10)]
for x in nums:
list[int((x / 10 ** i) % 10)].append(x)
nums.clear()
for j in list:
for a in j:
nums.append(a)
i += 1
return nums
def heap_sort(self, nums):
n = len(nums)
if n < 2:
return
x = n // 2 - 1
# TODO 将待排序数组构建成一个大顶堆
for i in range(x, -1, -1):
self.adjustheap(nums, i, n)
print(nums)
# TODO 将大顶堆的根节点与最后一个叶子结点交换,使得最大最放在最后
# TODO 将剩下的节点构建成一个大顶堆,重复上一步骤,直到剩余个数为0
for j in range(n - 1, 0, -1):
nums[j], nums[0] = nums[0], nums[j]
self.adjustheap(nums, 0, j)
return nums
def adjustheap(self, nums, i, lenght):
while (2 * i + 1) < lenght:
temp = 2 * i + 1
if temp + 1 < lenght and nums[temp + 1] > nums[temp]:
temp = temp + 1
if nums[i] < nums[temp]:
nums[i], nums[temp] = nums[temp], nums[i]
i = temp
def main():
nums = [5, 6, 2, 3, -8, 7, 5, -1, 6, 21]
sort = Sort()
result = sort.merge_sort(nums)
print(result)
if __name__ == "__main__":
main()