📜  查找导致最坏情况的合并排序的排列

📅  最后修改于: 2021-05-04 20:20:42             🧑  作者: Mango

给定一组元素,找出这些元素的哪些排列会导致合并排序的最坏情况。
渐近地,合并排序总是需要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 [])

  1. 左右创建两个辅助数组,并在其中存储备用数组元素。
  2. 为左子数组调用GenerateWorstCase:GenerateWorstCase(左)
  3. 为正确的子数组调用GenerateWorstCase:GenerateWorstCase(正确)
  4. 将左右子数组的所有元素复制回原始数组。

以下是实施思路

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