定义:首先,归并排序是一种基于分治思想的排序算法,其目的是将一个大问题分解成一些小问题,然后将其解决并归并子问题的结果以解决初始问题。具体做法是将待排序的序列分成若干个子序列,每个子序列都是有序的,然后再将这些有序的子序列合并成一个有序的序列。
实例详解
假设有一组NBA球员数据,包括姓名、得分和场均出手次数。我们要按照得分从高到低的顺序对这些球员进行排序。
步骤如下:
-
将球员数据分成两组。
-
分别对这两组数据进行排序。
-
合并排好序的两组数据。
-
重复执行步骤 1 到步骤 3 直到所有数据排序完成。
现在,我们以Kobe Bryant、LeBron James和Stephen Curry三名球员为例,他们的得分分别是81、69和62,我们来演示一下递归调用过程:
-
将Kobe Bryant和LeBron James分成两组;
-
对第一组(Kobe Bryant)进行递归排序,返回已排序的单独元素Kobe Bryant。
-
对第二组(LeBron James)进行递归排序,返回已排序的单独元素LeBron James。
-
将已排序的两个子数组(Kobe Bryant和LeBron James)合并成一个数组,按照得分从高到低排序。
-
将Stephen Curry和已排序的整个数组分成两组。
-
对得到的第一组数据(Stephen Curry)进行递归排序,返回已排序的单独元素Stephen Curry。
-
对第二组数据(已排序的整个数组)进行递归排序,返回已排序的整个数组(Kobe Bryant、LeBron James)。
-
将已排序的两个子数组(Stephen Curry和已排序的整个数组)合并成一个数组,按照得分从高到低排序。
-
返回已排序的最终数组(Kobe Bryant、LeBron James、Stephen Curry)。
这个过程可以重复,直到最终排序完成。
def merge_sort(arr):
if len(arr) > 1:
mid = len(arr) // 2
L = arr[:mid]
R = arr[mid:]
merge_sort(L)
merge_sort(R)
i = j = k = 0
while i < len(L) and j < len(R):
if L[i][1] > R[j][1]:
arr[k] = L[i]
i += 1
else:
arr[k] = R[j]
j += 1
k += 1
while i < len(L):
arr[k] = L[i]
i += 1
k += 1
while j < len(R):
arr[k] = R[j]
j += 1
k += 1
# 定义一个存储球员数据的数组
players = [("Kobe Bryant", 81, 28), ("LeBron James", 69, 20), ("Stephen Curry", 62, 22)]
merge_sort(players)
# 按照得分从高到低排序输出结果
print("按得分排序后的球员数据:")
for i in range(len(players)):
print("{0}: {1} 分,场均 {2} 出手次数".format(players[i][0], players[i][1], players[i][2]))
对比:
归并排序的时间复杂度是O(n log n),相对于冒泡排序、选择排序和插入排序,它的效率更高并且更适合处理大型数据集。冒泡排序的时间复杂度是O(n^2),插入排序的时间复杂度是O(n^2),而选择排序的时间复杂度是O(n^2)。
相比于插入排序和快速排序,归并排序的主要优势是稳定性,即只要两个相等的元素在排序前和排序后的相对位置是一样的,归并排序就能保证它们的相对位置依然不变。
在场景上,归并排序常用于文件排序,归并文件等高端业务。而在实际应用中,当排序列表非常大,内存不够用时,可以将列表按照一定大小分为多个块,将块分别排序,然后再进行块间归并排序即可。
相比于其他排序算法,归并排序在数据量较大,要求相对有序,或者要求稳定性等场景下有着更好的应用效果。
实战解析:
最后,关于实战解析,归并排序可以在诸如排序算法竞赛等各种场景中使用。在比赛中,除了考察算法本身之外,还会考察其速度和内存占用,因此,选择高效的排序算法尤为重要。而在实际工作场景中,当你需要高效地对数量庞大的数据集进行排序时,也可以使用归并排序来提高效率。当你需要对数百万条订单进行排序时,归并排序就非常适合。