前提条件–合并排序
合并排序包括将数组递归拆分为两部分,进行排序并最终合并它们。合并排序的一种变体称为3向合并排序,其中不是将数组拆分为2部分,而是将其拆分为3部分。
合并排序以递归方式将数组分解为大小为一半的子数组。同样,三向合并排序会将数组分解为大小为三分之一的子数组。例子:
Input : 45, -2, -45, 78, 30, -42, 10, 19 , 73, 93
Output : -45 -42 -2 10 19 30 45 73 78 93
Input : 23, -19
Output : -19 23
C++
// C++ Program to perform 3 way Merge Sort
#include
using namespace std;
/* Merge the sorted ranges [low, mid1), [mid1,mid2)
and [mid2, high) mid1 is first midpoint
index in overall range to merge mid2 is second
midpoint index in overall range to merge*/
void merge(int gArray[], int low, int mid1,
int mid2, int high, int destArray[])
{
int i = low, j = mid1, k = mid2, l = low;
// choose smaller of the smallest in the three ranges
while ((i < mid1) && (j < mid2) && (k < high))
{
if(gArray[i] < gArray[j])
{
if(gArray[i] < gArray[k])
{
destArray[l++] = gArray[i++];
}
else
{
destArray[l++] = gArray[k++];
}
}
else
{
if(gArray[j] < gArray[k])
{
destArray[l++] = gArray[j++];
}
else
{
destArray[l++] = gArray[k++];
}
}
}
// case where first and second ranges
// have remaining values
while ((i < mid1) && (j < mid2))
{
if(gArray[i] < gArray[j])
{
destArray[l++] = gArray[i++];
}
else
{
destArray[l++] = gArray[j++];
}
}
// case where second and third ranges
// have remaining values
while ((j < mid2) && (k < high))
{
if(gArray[j] < gArray[k])
{
destArray[l++] = gArray[j++];
}
else
{
destArray[l++] = gArray[k++];
}
}
// case where first and third ranges have
// remaining values
while ((i < mid1) && (k < high))
{
if(gArray[i] < gArray[k])
{
destArray[l++] = gArray[i++];
}
else
{
destArray[l++] = gArray[k++];
}
}
// copy remaining values from the first range
while (i < mid1)
destArray[l++] = gArray[i++];
// copy remaining values from the second range
while (j < mid2)
destArray[l++] = gArray[j++];
// copy remaining values from the third range
while (k < high)
destArray[l++] = gArray[k++];
}
/* Performing the merge sort algorithm on the
given array of values in the rangeof indices
[low, high). low is minimum index, high is
maximum index (exclusive) */
void mergeSort3WayRec(int gArray[], int low,
int high, int destArray[])
{
// If array size is 1 then do nothing
if (high - low < 2)
return;
// Splitting array into 3 parts
int mid1 = low + ((high - low) / 3);
int mid2 = low + 2 * ((high - low) / 3) + 1;
// Sorting 3 arrays recursively
mergeSort3WayRec(destArray, low, mid1, gArray);
mergeSort3WayRec(destArray, mid1, mid2, gArray);
mergeSort3WayRec(destArray, mid2, high, gArray);
// Merging the sorted arrays
merge(destArray, low, mid1, mid2, high, gArray);
}
void mergeSort3Way(int gArray[], int n)
{
// if array size is zero return null
if (n == 0)
return;
// creating duplicate of given array
int fArray[n];
// copying alements of given array into
// duplicate array
for (int i = 0; i < n; i++)
fArray[i] = gArray[i];
// sort function
mergeSort3WayRec(fArray, 0, n, gArray);
// copy back elements of duplicate array
// to given array
for (int i = 0; i < n; i++)
gArray[i] = fArray[i];
}
// Driver Code
int main()
{
int data[] = {45, -2, -45, 78, 30,
-42, 10, 19, 73, 93};
mergeSort3Way(data,10);
cout << "After 3 way merge sort: ";
for (int i = 0; i < 10; i++)
{
cout << data[i] << " ";
}
return 0;
}
// This code is contributed by Rashmi Kumari
Java
// Java program to perform 3 way Merge Sort
import java.util.*;
public class MergeSort3Way
{
// Function for 3-way merge sort process
public static void mergeSort3Way(Integer[] gArray)
{
// if array of size is zero returns null
if (gArray == null)
return;
// creating duplicate of given array
Integer[] fArray = new Integer[gArray.length];
// copying alements of given array into
// duplicate array
for (int i = 0; i < fArray.length; i++)
fArray[i] = gArray[i];
// sort function
mergeSort3WayRec(fArray, 0, gArray.length, gArray);
// copy back elements of duplicate array
// to given array
for (int i = 0; i < fArray.length; i++)
gArray[i] = fArray[i];
}
/* Performing the merge sort algorithm on the
given array of values in the rangeof indices
[low, high). low is minimum index, high is
maximum index (exclusive) */
public static void mergeSort3WayRec(Integer[] gArray,
int low, int high, Integer[] destArray)
{
// If array size is 1 then do nothing
if (high - low < 2)
return;
// Splitting array into 3 parts
int mid1 = low + ((high - low) / 3);
int mid2 = low + 2 * ((high - low) / 3) + 1;
// Sorting 3 arrays recursively
mergeSort3WayRec(destArray, low, mid1, gArray);
mergeSort3WayRec(destArray, mid1, mid2, gArray);
mergeSort3WayRec(destArray, mid2, high, gArray);
// Merging the sorted arrays
merge(destArray, low, mid1, mid2, high, gArray);
}
/* Merge the sorted ranges [low, mid1), [mid1,
mid2) and [mid2, high) mid1 is first midpoint
index in overall range to merge mid2 is second
midpoint index in overall range to merge*/
public static void merge(Integer[] gArray, int low,
int mid1, int mid2, int high,
Integer[] destArray)
{
int i = low, j = mid1, k = mid2, l = low;
// choose smaller of the smallest in the three ranges
while ((i < mid1) && (j < mid2) && (k < high))
{
if (gArray[i].compareTo(gArray[j]) < 0)
{
if (gArray[i].compareTo(gArray[k]) < 0)
destArray[l++] = gArray[i++];
else
destArray[l++] = gArray[k++];
}
else
{
if (gArray[j].compareTo(gArray[k]) < 0)
destArray[l++] = gArray[j++];
else
destArray[l++] = gArray[k++];
}
}
// case where first and second ranges have
// remaining values
while ((i < mid1) && (j < mid2))
{
if (gArray[i].compareTo(gArray[j]) < 0)
destArray[l++] = gArray[i++];
else
destArray[l++] = gArray[j++];
}
// case where second and third ranges have
// remaining values
while ((j < mid2) && (k < high))
{
if (gArray[j].compareTo(gArray[k]) < 0)
destArray[l++] = gArray[j++];
else
destArray[l++] = gArray[k++];
}
// case where first and third ranges have
// remaining values
while ((i < mid1) && (k < high))
{
if (gArray[i].compareTo(gArray[k]) < 0)
destArray[l++] = gArray[i++];
else
destArray[l++] = gArray[k++];
}
// copy remaining values from the first range
while (i < mid1)
destArray[l++] = gArray[i++];
// copy remaining values from the second range
while (j < mid2)
destArray[l++] = gArray[j++];
// copy remaining values from the third range
while (k < high)
destArray[l++] = gArray[k++];
}
// Driver function
public static void main(String args[])
{
// test case of values
Integer[] data = new Integer[] {45, -2, -45, 78,
30, -42, 10, 19, 73, 93};
mergeSort3Way(data);
System.out.println("After 3 way merge sort: ");
for (int i = 0; i < data.length; i++)
System.out.print(data[i] + " ");
}
}
输出:
After 3 way merge sort:
-45 -42 -2 10 19 30 45 73 78 93
在这里,我们首先将数据数组的内容复制到另一个名为fArray的数组。然后,通过找到将数组分为三部分的中点对数组进行排序,并分别在每个数组上调用sort函数。递归的基本情况是当array的大小为1且从函数返回时。然后开始合并数组,最后将排序后的数组放入fArray中,然后将其复制回gArray。
时间复杂度:对于2路合并排序,我们得到以下公式:T(n)= 2T(n / 2)+ O(n)
类似地,在三向合并排序的情况下,我们得到以下等式:T(n)= 3T(n / 3)+ O(n)
通过使用Master方法求解它,我们得到它的复杂度为O(n log 3 n)。 。尽管与2种方式进行合并排序相比,时间复杂度看起来要小一些,但由于合并函数的比较次数会增加,因此实际花费的时间可能会更长。请参阅为什么二元搜索优于三元搜索?有关详细信息。
类似文章:
3种快速排序