给定一组元素,找出这些元素的哪些排列会导致合并排序的最坏情况。
渐近地,合并排序总是需要O(n Log n)的时间,但是需要更多比较的情况在实践中通常会花费更多的时间。我们基本上需要找到一种输入元素的排列,当使用典型的“合并排序”算法进行排序时,这将导致最大数量的比较。
例子:
Consider the below set of elements
{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
13, 14, 15, 16}
Below permutation of the set causes 153
comparisons.
{1, 9, 5, 13, 3, 11, 7, 15, 2, 10, 6,
14, 4, 12, 8, 16}
And an already sorted permutation causes
30 comparisons.
See this for a program that counts
comparisons and shows above results.
现在如何获取最坏情况的输入,以便对输入集进行合并排序?
让我们尝试以自下而上的方式构建数组
令排序后的数组为{1,2,3,4,5,6,7,8}。
为了生成合并排序的最坏情况,导致上述排序数组的合并操作应产生最大的比较。为此,合并操作中涉及的左右子数组应存储排序数组的备用元素。即,左子数组应为{1,3,5,7},右子数组应为{2,4,6,8}。现在,将对数组的每个元素至少进行一次比较,这将导致最大程度的比较。我们对左和右子数组也应用相同的逻辑。对于数组{1,3,5,7},最坏的情况是当数组的左和右子数组分别为{1,5}和{3,7}时,对于数组{2,4,6,8} {2,4}和{6,8}会发生最坏的情况。
完整算法–
GenerateWorstCase(arr [])
- 左右创建两个辅助数组,并在其中存储备用数组元素。
- 为左子数组调用GenerateWorstCase:GenerateWorstCase(左)
- 为正确的子数组调用GenerateWorstCase:GenerateWorstCase(正确)
- 将左右子数组的所有元素复制回原始数组。
以下是实施思路
C++
// C++ program to generate Worst Case
// of Merge Sort
#include
using namespace std;
// Function to print an array
void printArray(int A[], int size)
{
for(int i = 0; i < size; i++)
{
cout << A[i] << " ";
}
cout << endl;
}
// Function to join left and right subarray
int join(int arr[], int left[], int right[],
int l, int m, int r)
{
int i;
for(i = 0; i <= m - l; i++)
arr[i] = left[i];
for(int j = 0; j < r - m; j++)
{
arr[i + j] = right[j];
}
}
// Function to store alternate elemets in
// left and right subarray
int split(int arr[], int left[], int right[],
int l, int m, int r)
{
for(int i = 0; i <= m - l; i++)
left[i] = arr[i * 2];
for(int i = 0; i < r - m; i++)
right[i] = arr[i * 2 + 1];
}
// Function to generate Worst Case
// of Merge Sort
int generateWorstCase(int arr[], int l,
int r)
{
if (l < r)
{
int m = l + (r - l) / 2;
// Create two auxiliary arrays
int left[m - l + 1];
int right[r - m];
// Store alternate array elements
// in left and right subarray
split(arr, left, right, l, m, r);
// Recurse first and second halves
generateWorstCase(left, l, m);
generateWorstCase(right, m + 1, r);
// Join left and right subarray
join(arr, left, right, l, m, r);
}
}
// Driver code
int main()
{
// Sorted array
int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9,
10, 11, 12, 13, 14, 15, 16 };
int n = sizeof(arr) / sizeof(arr[0]);
cout << "Sorted array is \n";
printArray(arr, n);
// Generate Worst Case of Merge Sort
generateWorstCase(arr, 0, n - 1);
cout << "\nInput array that will result "
<< "in worst case of merge sort is \n";
printArray(arr, n);
return 0;
}
// This code is contributed by Mayank Tyagi
C
// C program to generate Worst Case of Merge Sort
#include
#include
// Function to print an array
void printArray(int A[], int size)
{
for (int i = 0; i < size; i++)
printf("%d ", A[i]);
printf("\n");
}
// Function to join left and right subarray
int join(int arr[], int left[], int right[],
int l, int m, int r)
{
int i; // Used in second loop
for (i = 0; i <= m - l; i++)
arr[i] = left[i];
for (int j = 0; j < r - m; j++)
arr[i + j] = right[j];
}
// Function to store alternate elemets in left
// and right subarray
int split(int arr[], int left[], int right[],
int l, int m, int r)
{
for (int i = 0; i <= m - l; i++)
left[i] = arr[i * 2];
for (int i = 0; i < r - m; i++)
right[i] = arr[i * 2 + 1];
}
// Function to generate Worst Case of Merge Sort
int generateWorstCase(int arr[], int l, int r)
{
if (l < r)
{
int m = l + (r - l) / 2;
// create two auxiliary arrays
int left[m - l + 1];
int right[r - m];
// Store alternate array elements in left
// and right subarray
split(arr, left, right, l, m, r);
// Recurse first and second halves
generateWorstCase(left, l, m);
generateWorstCase(right, m + 1, r);
// join left and right subarray
join(arr, left, right, l, m, r);
}
}
// Driver code
int main()
{
// Sorted array
int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9,
10, 11, 12, 13, 14, 15, 16 };
int n = sizeof(arr) / sizeof(arr[0]);
printf("Sorted array is \n");
printArray(arr, n);
// generate Worst Case of Merge Sort
generateWorstCase(arr, 0, n - 1);
printf("\nInput array that will result in "
"worst case of merge sort is \n");
printArray(arr, n);
return 0;
}
Java
// Java program to generate Worst Case of Merge Sort
import java.util.Arrays;
class GFG
{
// Function to join left and right subarray
static void join(int arr[], int left[], int right[],
int l, int m, int r)
{
int i;
for (i = 0; i <= m - l; i++)
arr[i] = left[i];
for (int j = 0; j < r - m; j++)
arr[i + j] = right[j];
}
// Function to store alternate elemets in left
// and right subarray
static void split(int arr[], int left[], int right[],
int l, int m, int r)
{
for (int i = 0; i <= m - l; i++)
left[i] = arr[i * 2];
for (int i = 0; i < r - m; i++)
right[i] = arr[i * 2 + 1];
}
// Function to generate Worst Case of Merge Sort
static void generateWorstCase(int arr[], int l, int r)
{
if (l < r)
{
int m = l + (r - l) / 2;
// create two auxiliary arrays
int[] left = new int[m - l + 1];
int[] right = new int[r - m];
// Store alternate array elements in left
// and right subarray
split(arr, left, right, l, m, r);
// Recurse first and second halves
generateWorstCase(left, l, m);
generateWorstCase(right, m + 1, r);
// join left and right subarray
join(arr, left, right, l, m, r);
}
}
// driver program
public static void main (String[] args)
{
// sorted array
int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9,
10, 11, 12, 13, 14, 15, 16 };
int n = arr.length;
System.out.println("Sorted array is");
System.out.println(Arrays.toString(arr));
// generate Worst Case of Merge Sort
generateWorstCase(arr, 0, n - 1);
System.out.println("\nInput array that will result in \n"+
"worst case of merge sort is \n");
System.out.println(Arrays.toString(arr));
}
}
// Contributed by Pramod Kumar
C#
// C# program to generate Worst Case of
// Merge Sort
using System;
class GFG {
// Function to join left and right subarray
static void join(int []arr, int []left,
int []right, int l, int m, int r)
{
int i;
for (i = 0; i <= m - l; i++)
arr[i] = left[i];
for (int j = 0; j < r - m; j++)
arr[i + j] = right[j];
}
// Function to store alternate elemets in
// left and right subarray
static void split(int []arr, int []left,
int []right, int l, int m, int r)
{
for (int i = 0; i <= m - l; i++)
left[i] = arr[i * 2];
for (int i = 0; i < r - m; i++)
right[i] = arr[i * 2 + 1];
}
// Function to generate Worst Case of
// Merge Sort
static void generateWorstCase(int []arr,
int l, int r)
{
if (l < r)
{
int m = l + (r - l) / 2;
// create two auxiliary arrays
int[] left = new int[m - l + 1];
int[] right = new int[r - m];
// Store alternate array elements
// in left and right subarray
split(arr, left, right, l, m, r);
// Recurse first and second halves
generateWorstCase(left, l, m);
generateWorstCase(right, m + 1, r);
// join left and right subarray
join(arr, left, right, l, m, r);
}
}
// driver program
public static void Main ()
{
// sorted array
int []arr = { 1, 2, 3, 4, 5, 6, 7, 8, 9,
10, 11, 12, 13, 14, 15, 16 };
int n = arr.Length;
Console.Write("Sorted array is\n");
for(int i = 0; i < n; i++)
Console.Write(arr[i] + " ");
// generate Worst Case of Merge Sort
generateWorstCase(arr, 0, n - 1);
Console.Write("\nInput array that will "
+ "result in \n worst case of"
+ " merge sort is \n");
for(int i = 0; i < n; i++)
Console.Write(arr[i] + " ");
}
}
// This code is contributed by Smitha
输出:
Sorted array is
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
Input array that will result in worst
case of merge sort is
1 9 5 13 3 11 7 15 2 10 6 14 4 12 8 16