1.算法原理
归并排序(Merge sort)是一种经典的分治算法,它的主要思想是将待排序的数组递归地分成较小的子数组,然后对子数组进行排序,最后再将已排序的子数组合并,直到整个数组有序。
算法的工作原理如下:
分割:将待排序的数组递归地分成较小的子数组,直到子数组只剩下一个元素或为空。
排序:对每个子数组进行排序。可以使用递归地调用归并排序算法进行排序,也可以使用其他排序算法。
合并:将已排序的子数组进行合并,得到完全有序的数组。
2.代码实现(python)
def merge_sort(list):
if len(list)==1:
return list
# 分裂成子列表
else:
mid = len(list) // 2
#左半部分
left = list[0:mid]
#右半部分
right = list[mid:]
#递归分列合并
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))
#print(result)
return result
#测试用例
if __name__ == '__main__':
lst1 = [1, -2, 234, 23, 56, 23, 12, 324, -2, 0, 321, 38, 239, 89]
lst2 =[1,2,3,4,5,6,7,8,9,10]
lst3 =[9, 4, 2, 7, 1, 5, 8, 3, 6]
print("归并排序")
print(merge_sort(lst1))
print(merge_sort(lst2))
print(merge_sort(lst3))
运行结果
这个地方合并的过程,因为是python语言,就比较简便,没有用指针索引的方式来写,两种写法都可以,其原理都是一样的,看个人习惯吧,我把用下标索引来写的函数代码也给出来,方便理解。
def mergeSort(alist):
if len(alist) > 1:
mid = len(alist) // 2
lefthalf = alist[:mid]
righthalf = alist[mid:]
#递归调用自身
mergeSort(lefthalf)
mergeSort(righthalf)
#指针索引
i = j = k = 0
while i < len(lefthalf) and j < len(righthalf):
if lefthalf[i] < righthalf[j]:
alist[k] = lefthalf[i]
i += 1
else:
alist[k] = righthalf[j]
j += 1
k += 1
while i < len(lefthalf):
alist[k] = lefthalf[i]
i += 1
k += 1
while j < len(righthalf):
alist[k] = righthalf[j]
j += 1
k += 1
#测试用例
if __name__ == '__main__':
alist = [9, 4, 2, 7, 1, 5, 8, 3, 6]
mergeSort(alist)
print(alist)
具体示例
如上图所示,把待排序数组一次次分割,直到只剩下一个数为一组;
然后,一一比较再合并,最终变得有序。
对于这个示例,最后具体合并的过程,如上图:其余的合并过程也是类似的,这样结合起来看代码也就更容易懂了。
3.时空复杂度
时间复杂度:
归并排序的时间复杂度最好、最坏、平均情况都为O(nlogn),其中n是待排序数组的长度。具体分析如下:
分割阶段的时间复杂度是O(logn),因为每次对数组进行二分分割,需要进行logn次递归。
排序阶段的时间复杂度是O(n),因为需要对n个元素进行比较和交换操作。
合并阶段的时间复杂度是O(n),因为需要将n个元素依次合并到一个数组中。
空间复杂度:
归并排序的空间复杂度为O(n),主要是由于需要额外的空间来存储临时数组和递归调用栈。
4.归并排序特点
稳定性
归并排序是一种稳定的排序算法,不会改变数值相同元素之间的相对位置。
优缺点
适用于链表:归并排序对于链表的排序也很有效,因为它的合并操作只需要调整指针,不需要移动元素。
然而,归并排序也有一些缺点:
需要额外的空间:归并排序需要额外的空间来存储临时数组,在排序过程中会增加空间的使用。
需要递归调用:归并排序需要使用递归来分割和合并数组,递归调用可能会增加运行时的开销。
与其他算法比较
与其他排序算法相比,归并排序的主要优势是在最坏情况下具有稳定的O(nlogn)时间复杂度。与快速排序相比,归并排序更加稳定,但是在实际应用中可能会有较高的空间需求。与 插入排序 和 冒泡排序 相比,归并排序的时间复杂度更优,但是空间复杂度较高。
总结起来,归并排序是一种高效、稳定的排序算法,时间复杂度为O(nlogn),适用于各种数据类型和数据规模。它的主要缺点是需要额外的空间和递归调用。
文章有不对的地方还请大佬们指正!