快速排序程序停止工作

Quick Sort program stopped working

本文关键字:停止工作 程序 快速排序      更新时间:2023-10-16

我试图解决快速排序-2 Hackerrank上的2挑战。它说,我们必须反复调用分区,直到整个阵列分类为止。我的程序适用于某些测试用例,但对于某些测试用例,"快速排序-2.EXE已停止工作"。我找不到为什么会发生的原因。数组/子阵列的第一个元素每次都被视为枢轴元素。

#include <iostream>
#include <conio.h>
using namespace std;
void swap(int arr[], int a, int b)
{
    int c = arr[a];
    arr[a] = arr[b];
    arr[b] = c;
}
void qsort(int arr[], int m, int n)    //m - lower limit, n - upper limit
{
    if (n - m == 1)
    {
        return;
    }
    int p = arr[m], i, j, t;           //p - pivot element, t - temporary
    //partition
    for (int i = m+1; i < n; i++)
    {
        j = i;
        if (arr[j] < p)
        {
            t = arr[j];
            while (arr[j] != p)
            {
                arr[j] = arr[j-1];
                j--;
            }
            arr[j] = t;                //pivot is at j and j+1
        }
    }
    //check if sorted
    int f = 1;
    while (arr[f] > arr[f-1])
    {
        if (f == n-1)
        {
            f = -1;
            break;
        }
        f++;
    }
    if (f == -1)
    {
        cout << "Sub Array Sortedn";
    }
    else
    {
        if (p == arr[m])               //pivot is the smallest in sub array
        {
            qsort(arr, m+1, n);        //sort right sub array
        }
        else
        {
            qsort(arr, m, j+1);        //sort left sub array
            qsort(arr, j+1, n);        //sort right sub array
        }
    }
}
int main()
{
    int n;
    cin >> n;
    int arr[n];
    for (int i = 0; i < n; i++)
    {
        cin >> arr[i];
    }
    qsort(arr, 0, n);
    for (int i = 0; i < n; i++)
    {
        cout << arr[i] << " ";
    }
    return 0;
}

您的索引超出了范围问题。

这不会为您提供解决方案,但它可能会帮助您找到程序失败的原因。

我已经修改了您的程序,因此它使用intvector而不是int的原始数组,当您运行此程序时,您会获得索引以外的范围异常。

触发问题的序列4 3 7 1 6 4是硬编码的,因此您无需每次键入它。

#include <iostream>
#include <vector>
using namespace std;
void swap(vector<int> & arr, int a, int b)
{
  int c = arr[a];
  arr[a] = arr[b];
  arr[b] = c;
}
void qsort(vector<int> & arr, int m, int n)    //m - lower limit, n - upper limit
{
  if (n - m == 1)
  {
    return;
  }
  int p = arr[m], j, t;           //p - pivot element, t - temporary
                                     //partition
  for (int i = m + 1; i < n; i++)
  {
    j = i;
    if (arr[j] < p)
    {
      t = arr[j];
      while (arr[j] != p)
      {
        arr[j] = arr[j - 1];
        j--;
      }
      arr[j] = t;                //pivot is at j and j+1
    }
  }
  //check if sorted
  int f = 1;
  while (arr[f] > arr[f - 1])
  {
    if (f == n - 1)
    {
      f = -1;
      break;
    }
    f++;
  }
  if (f == -1)
  {
    cout << "Sub Array Sortedn";
  }
  else
  {
    if (p == arr[m])               //pivot is the smallest in sub array
    {
      qsort(arr, m + 1, n);        //sort right sub array
    }
    else
    {
      qsort(arr, m, j + 1);        //sort left sub array
      qsort(arr, j + 1, n);        //sort right sub array
    }
  }
}
int main()
{
  vector<int> arr = { 4,3,7,1,6,4 };
  qsort(arr, 0, arr.size());
  for (unsigned int i = 0; i < arr.size(); i++)
  {
    cout << arr[i] << " ";
  }
  return 0;
}

首先,您所做的不是快速排序,而是分隔框架分区和插入排序的某种组合。

典型的QuickSort从阵列的下部(P)和上部(Q)边界分别进行跳过元素ARR [P] m。然后,它将ARR [P]与ARR [Q]交换,增量/减少并检查p> = q。冲洗并重复直到p> = q。然后在子分区上拨打电话。这样,P或Q具有枢轴位置,子电池很明显。

但是您正在做不同的方式:您将元素从子阵列的右侧插入到左侧。这样的东西可以产生一个迭代的O(n^2)时间复杂性。例如,考虑1,0,1,0,1,0,1,0,1,0,1,0,例如序列。这可能会增加O(n^2)的最坏情况。

止于时间复杂性...您功能的问题在于假设J在子电池中保持枢轴位置:

qsort(arr, m, j+1);        //sort left sub array
qsort(arr, j+1, n);        //sort right sub array

实际上,j在您的主循环中一次又一次地等于i。如果最后一个元素相等或大于枢轴,则最终会以j = n-1,您调用qsort(arr,n,n)和第一行检查(sic!),因为n-n!=1。p>要解决此问题,您应该做两件事:

1)重新排列后直接找到枢轴位置:

for (int i = m; i < n; i++)
    if (p == arr[i])
    {
        j = i;
        break;
    }

或在不同变量中初始化它,在此行之后进行更新:

arr[j] = t;                //pivot is at j and j+1

和更新使用新变量而不是j

的递归调用

2)在功能开始时进行更防弹检查:

if (n - m <= 1)

后者足以获得一些结果,但是在最坏的情况下,它比您当前的想法的效率要少得多。