(根据Lintcode用户@aiahwang的题解总结的10大排序算法)
描述
给一组整数,按照升序排序,使用选择排序,冒泡排序,插入排序或者任何
O
(
n
2
)
O(n^2)
O(n2) 的排序算法。
样例
样例 1:
输入: [3, 2, 1, 4, 5]
输出: [1, 2, 3, 4, 5]
样例解释:
返回排序后的数组。
样例 2:
输入: [1, 1, 2, 1, 1]
输出: [1, 1, 1, 1, 2]
样例解释:
返回排好序的数组。
1.冒泡排序
(1)比较相邻的元素。如果第一个比第二个大,就交换他们两个。
(2)对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。
(3)针对所有的元素重复以上的步骤,除了最后一个。
(4)持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
[5,4,3,2,1,0]->
[4,5,3,2,1,0]->[4,3,5,2,1,0]->[4,3,2,5,1,0]->[4,3,2,1,5,0]->[4,3,2,1,0,5]->
[3,4,2,1,0,5]->[3,2,4,1,0,5]->[3,2,1,4,0,5]->[3,2,1,0,4,5]->
[2,3,1,0,4,5]->[2,1,3,0,4,5]->[2,1,0,3,4,5]->
[1,2,0,3,4,5]->[1,0,2,3,4,5]->
[0,1,2,3,4,5]
class Solution:
"""
@param A: an integer array
@return: nothing
"""
# Bubble sort 冒泡排序
def sortIntegers(self, A):
# write your code here
if A==None or len(A)==0:
return
for i in range(len(A)):
for j in range(len(A)-1-i):
if A[j] > A[j+1]:
A[j],A[j+1] = A[j+1],A[j]
2.选择排序
第一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,然后再从剩余的未排序元素中寻找到最小(大)元素,然后放到已排序的序列的末尾。以此类推,直到全部待排序的数据元素的个数为零。
[5,4,3,2,1,0]->
[0,4,3,2,1,5]->
[0,1,3,2,4,5]->
[0,1,2,3,4,5]
class Solution:
"""
@param A: an integer array
@return: nothing
"""
# Selection Sort 选择排序
def sortIntegers(self, A):
# write your code here
if A==None or len(A)==0:
return
for i in range(len(A)):
tmp = i
for j in range(i+1, len(A)):
if A[j] < A[tmp]:
tmp = j
A[i],A[tmp] = A[tmp],A[i]
3.插入排序
在其实现过程使用双层循环,外层循环对除了第一个元素之外的所有元素,内层循环对当前元素前面有序表进行待插入位置查找,并进行移动。
[5,4,3,2,1,0]->
[4,5,3,2,1,0]->
[4,3,5,2,1,0]->[3,4,5,2,1,0]->
[3,4,2,5,1,0]->[3,2,4,5,1,0]->[2,3,4,5,1,0]->
[2,3,4,1,5,0]->[2,3,1,4,5,0]->[2,1,3,4,5,0]->[1,2,3,4,5,0]->
[1,2,3,4,0,5]->[1,2,3,0,4,5]->[1,2,0,3,4,5]->[1,0,2,3,4,5]->[0,1,2,3,4,5]
class Solution:
"""
@param A: an integer array
@return: nothing
"""
# Insertion Sort 插入排序
def sortIntegers(self, A):
# write your code here
if A==None or len(A)==0:
return # return后面什么也不加,表示没有返回值,运行完就结束
for i in range(len(A)):
for j in range(i-1,-1,-1):
if A[i] < A[j]:
A[i],A[j] = A[j],A[i]
i = j
else:
break
4.希尔排序
由于插入排序中当前元素每次只能向前移动一步,像[5,4,3,2,1,0]中0要想移到首位需要一步一步地向前置换,导致效率低下。因此希尔排序是对它的改进,希尔排序又称“缩小增量排序”。设置一个增量dk,按下标的一定增量分为几组,对每组使用直接插入排序算法排序。随着增量越来越少,每组包含的元素越来越多,当增量为1时,恰好分为1组。因此,增量dk的设置是关键,一般{n/2,(n/2)/2,…,1}称为增量序列。
class Solution:
"""
@param A: an integer array
@return: nothing
"""
# Shell Sort 希尔插序
def sortIntegers(self, A):
# write your code here
if A==None or len(A)==0:
return
dk = len(A) // 2 # 整数除法 向下取整
while dk>=1 :
self.InsertSort(A,dk)
dk = dk // 2
def InsertSort(self,A,dk):
for i in range(dk):
for j in range(i,len(A),dk):
for k in range(j-1,-1,-dk):
if A[j] < A[k]:
A[j],A[k] = A[k],A[j]
j = k
else:
break
6.快速排序
是对冒泡排序算法的一种改进,通过多次比较和交换来实现排序:
(1)首先设定一个分界值,通过该分界值将数组分成左右两部分。
(2)将
≥
\geq
≥ 分界值的数据集中到数组右边,
<
<
<分界值的数据集中到数组的左边。此时,左边部分中各元素都
≤
\leq
≤分界值,而右边部分中各元素都
≥
\geq
≥分界值。
(3)然后,左边和右边的数据可以独立排序。对于左侧的数组数据,又可以取一个分界值,将该部分数据分成左右两部分,同样在左边放置较小值,右边放置较大值。右侧的数组数据也可以做类似处理。
(4)重复上述过程,可以看出,这是一个递归定义。通过递归将左侧部分排好序后,再递归排好右侧部分的顺序。当左、右两个部分各数据排序完成后,整个数组的排序也就完成了。
# Quick Sort
class Solution:
def sortIntegers(self, A):
if A == None or len(A) == 0:
return
self.quickSort(A, 0, len(A) - 1)
def quickSort(self, A, start, end):
if start >= end:
return
left = start
right = end
pivot = A[(start+end)//2]
while left <= right:
while left <= right and A[left] < pivot:
left += 1
while left <= right and A[right] > pivot:
right -= 1
if left <= right:
A[left], A[right] = A[right], A[left]
left += 1
right -= 1
self.quickSort(A, start, right)
self.quickSort(A, left, end)