python实现几种常见的排序算法
2019-01-20 本文已影响56人
米兔妮妮
以下排序算法均按照从小到大排序N个元素:
'''
1、冒泡排序
基本思想:
遍历元素列表,比较相邻的元素,如果第一个比第二个大,则交换其位置,经过第一轮比较,最大的元素将恰好被放置到最后一个;
第二轮不再比较最后的元素,只比较前面的N-1个元素,则经过第二轮比较之后,我们可以确定第二大的元素;
依次类推,第i轮比较能够确定第i大的元素,可知经过N-1轮比较后我们能够确定所有元素的位置(为什么不是N轮比较?——因为前N-1个大的元素确定了,还剩最后一个,自然就是最小的,无需再比较)
'''
def bubble_sort(nums):
if nums is not None: # 注意判空,不要用=或者!=判空
for i in range(1, len(nums)): # 一共进行1到N-1轮比较,N即列表长度len(nums)
is_sorted = True # 用来判断是否已经排好序
for j in range(len(nums) - i): # 第i轮比较中需要比较第0,1,…,(N-i-1)个元素与其后面一个位置上的元素的大小
if nums[j] > nums[j + 1]:
is_sorted = False # 如果没有发生交换,则说明已经排好序,无需进行下一轮比较
nums[j], nums[j + 1] = nums[j + 1], nums[j]
if is_sorted:
break
return nums
'''
2、选择排序
基本思想:
遍历元素,记录下最小的元素所在的位置,然后把最小的元素和位置0上的元素互换;
一共进行N-1轮遍历:
第一轮确定第1小的元素,放在位置0;
第二轮确定第2小的元素,放在位置1;x
…
第i轮确定第i小的元素,放在位置i;
N-1轮遍历之后可以确定所有元素的正确位置。
'''
def select_sort(nums):
if nums is not None: # 注意判空
for i in range(0, len(nums) - 1): # 一共进行0到N-2共N-1轮选择,N即列表长度len(nums)
min_index = i # 先初始化每轮选择中最小的元素的位置为每轮遍历的第一个元素
for j in range(i + 1, len(nums)): # 从第一个元素的下一个位置开始与记录的最小元素做比较
if nums[j] < nums[min_index]:
min_index = j
if i != min_index:
nums[i], nums[min_index] = nums[min_index], nums[i]
'''
3、快速排序
基本思想:采用分而治之的思想,选取nums中的一个数作为基准点,把要排序的数据分成两部分,一部分比基准点小,一部分比基准点大;
然后再对这两部分数据分别采用分而治之的方法进行排序;
最后再把这几部分数据连接到一起。
'''
def quick_sort(nums):
if len(nums) <= 1:
return nums
pivot = nums[len(nums) // 2]
left = [x for x in nums if x < pivot]
middle = [x for x in nums if x == pivot]
right = [x for x in nums if x > pivot]
return quick_sort(left) + middle + quick_sort(right)
'''
4、插入排序
基本思想:插入排序的原理类似于打扑克牌,把待排序数据分成两部分,一部分是已排好序的有序数据,一部分是乱序数据,
开始时默认第一个数有序,然后再将后面的数逐个插入,插入操作具体包括:
1、与有序数据比较,确定插入位置,
2、在每次比较中将比待插入数据大的数据后移,给待插入数据腾位置
'''
def insert_sort(nums):
for i in range(len(nums)):
preIndex = i-1 # 0到i-1的数据为已经排好序的有序数据
curnum = nums[i] # 记录下一个要插入到有序数据中的数
# 遍历有序数据,找到curnum应插入的位置
while preIndex >= 0 and nums[preIndex] > curnum: # 注意不要漏掉preIndex等于0
nums[preIndex+1] = nums[preIndex] # 比curnum大的数往后挪
preIndex -= 1
nums[preIndex+1] = curnum
return nums
l = [-1, 5, 3, 8, 1, -8]
insert_sort(l)
print(l)
'''
5、希尔排序
基本思想:希尔排序是直接插入排序的升级版,减少插入排序的移动次数
插入排序在每次插入一个数据的过程中,凑要大量移动数据,
希尔排序将序列按固定间隔划分为多个子序列,在子序列中简单插入排序,先做远距离移动使序列基本有序;
逐渐缩小间隔重复操作,最后间隔为1时即简单插入排序。
'''
def shell_insert(nums, d):
n = len(nums)
for i in range(d, n):
j = i - d
temp = nums[i] # 记录要插入的数
while j >= 0 and nums[j] > temp: # 从后向前,找到比其小的数的位置
nums[j + d] = nums[j] # 向后挪动
j -= d
if j != i - d:
nums[j + d] = temp
def shell_sort(nums):
n = len(nums)
if n <= 1:
return nums
d = n//2
while d >= 1:
shell_insert(nums, d)
d = d//2
return nums
'''
6、归并排序
基本思想:归并排序运用分治递归思想:将大问题分为较小的子问题,分而治之;递归调用同样的方法解决子问题。
最终将序列的排序问题分治为一个数的排序问题,关键在于如何将子问题答案合并为问题答案。
两个有序序列合并为一个有序序列,借助一个暂存数组(列表),两个序列元素依次比较填入暂存列表,形成一个有序序列。
归并排序划分子问题采用二分法,共需O(logn)次划分,当然需要相当次合并;每次合并遍历比较O(n)。时间复杂度O(nlogn)。
'''
def merge_sort(nums):
import math
if len(nums) < 2:
return nums
middle = math.floor(len(nums)/2)
left, right = nums[0:middle], nums[middle:]
return merge(merge_sort(left), merge_sort(right))
def merge(left, right):
result = []
while left and right:
if left[0] <= right[0]:
result.append(left.pop(0))
else:
result.append(right.pop(0))
while left:
result.append(left.pop(0))
while right:
result.append(right.pop(0))
return result
参考:
https://blog.csdn.net/aiya_aiya_/article/details/79846380#1.%E5%86%92%E6%B3%A1%E6%8E%92%E5%BA%8F
https://www.cnblogs.com/wuxinyan/p/8615127.html