尝试实现快速排序算法。我认为问题在于递归,但我不知道应该怎么做才能修复它。每次运行程序时程序都会继续崩溃,我无法理解为什么。这是代码:
#include<iostream>
using namespace std;
int pIndex;
int Partition(int *A,int start,int end){
int pivot;
int pIndex;
if(start<end){
int pivot=A[end];
int pIndex=start;
for(int x=0;x<end;x++){
if(A[x]<A[end]){
swap(A[x],A[pIndex]);
pIndex=pIndex+1;
}
}
swap(A[pIndex],A[end]);
}
//cout<<pIndex<<endl;
swap(A[pIndex],A[end]);
return pIndex;
};
void QuickSort(int *A, int start,int end){
if(start<end)
{
pIndex=Partition(A,start,end);
QuickSort(A,pIndex+1,end);
QuickSort(A,start,pIndex-1);
}
};
int main(){
int A[10]{4,23,1,43,2,10};
//Partition(A,0,9);
QuickSort(A,0,5);
for(int x=0;x<10;x++){
cout<< A[x]<<" ";
}
}
答案 0 :(得分:3)
您的分区算法大约是它需要的代码的两倍。您似乎总是在序列的序列中选择 last 元素,虽然不可取,但它可用于学术演示。
您的崩溃
您定义了两个pIndex
值,其中只有一个实际上是确定性的。您还声明了两个pivot
变量,但这不会导致崩溃(第一个永远不会被使用)。它应该尽可能地清理,但你的代码中的丧钟是重复pIndex
int pivot;
int pIndex; // HERE
if(start<end){
int pivot=A[end];
int pIndex=start; // HERE AGAIN
for(int x=0;x<end;x++){
if(A[x]<A[end]){
swap(A[x],A[pIndex]);
pIndex=pIndex+1;
}
}
swap(A[pIndex],A[end]);
}
swap(A[pIndex],A[end]); // uses non-determined pIndex
return pIndex; // returns non-determined pIndex
将int pIndex=start;
更改为pIndex=start;
将解决您的崩溃问题,但您的分区方法仍需要...帮助。
“扫描”分区方法
对于假定为右尾的数据透视值,分区的“扫描”方法通常是这样做的,并且你很难让这更简单(不能调用std::partition
):< / p>
size_t Partition(int *A, size_t len)
{
if (len < 2)
return 0;
size_t pvt = 0;
for (size_t i=0; i<end; ++i)
{
if (A[i] < a[len-1])
std::swap(A[i], A[pvt++])
}
std::swap(A[pvt], a[len-1]);
return pvt;
};
上述算法仅包括分区所需的必需品:序列迭代器(在您的情况下为指针)和序列长度。其他一切都是基于这两个项目的确定性。下面是一个关于其工作原理的快速示例程序,其中特意放置了5个透视值:
#include <iostream>
size_t Partition(int *A, size_t len)
{
if (len < 2)
return 0;
size_t pvt = 0;
for (size_t i=0; i<len-1; ++i)
{
if (A[i] < A[len-1])
std::swap(A[i], A[pvt++]);
}
std::swap(A[pvt], A[len-1]);
return pvt;
};
int main()
{
int arr[] = { 4, 8, 7, 3, 9, 2, 1, 6, 5 };
size_t n = Partition(arr, sizeof(arr)/sizeof(*arr));
std::cout << "Partition : " << n << '\n';
for (auto x : arr)
std::cout << x << ' ';
std::cout << '\n';
}
<强>输出强>
Partition : 4
4 3 2 1 5 7 8 6 9
如何从QuickSort调用
在quicksort中调用分区会设置枢轴位置,该位置成为底部线段的“结束”迭代点,以及顶部线段的一个BEFORE迭代点。 严重在递归时,Partition()
调用返回的数据透视位置不应包含在 子序列中。
void QuickSort(int *A, size_t len)
{
if (len < 2)
return;
size_t pvt = Partition(A, len);
QuickSort(A, pvt++); // NOTE: post increment...
QuickSort(A+pvt, len-pvt); // ...which makes this skip the pivot
}
是的,指针算术摇滚,你不觉得吗?
全部放在一起
以下程序包含 Partition
和QuickSort
:
#include <iostream>
size_t Partition(int *A, size_t len)
{
if (len < 2)
return 0;
size_t pvt = 0;
for (size_t i=0; i<len-1; ++i)
{
if (A[i] < A[len-1])
std::swap(A[i], A[pvt++]);
}
std::swap(A[pvt], A[len-1]);
return pvt;
};
void QuickSort(int *A, size_t len)
{
if (len < 2)
return;
size_t pvt = Partition(A, len);
QuickSort(A, pvt++); // NOTE: post increment
QuickSort(A+pvt, len-pvt);
}
int main()
{
int arr[] = { 4, 8, 7, 3, 9, 2, 1, 6, 5 };
QuickSort(arr, sizeof(arr)/sizeof(*arr));
for (auto x : arr)
std::cout << x << ' ';
std::cout << '\n';
}
<强>输出强>
1 2 3 4 5 6 7 8 9
我希望它有所帮助。
答案 1 :(得分:1)
在这部分:
int pivot;
int pIndex;
if(start<end){
int pivot=A[end];
int pIndex=start;
您正在定义两个枢轴,以及两个pIndex&#39。您根本没有使用数据透视表,而在最后一次交换时,您使用的是未初始化的pIndex。这应该有效:
int Partition(int *A,int start,int end){
int pIndex = start;
if(start<end){
for(int x=0;x<end;x++){
if(A[x]<A[end]){
swap(A[x],A[pIndex]);
pIndex=pIndex+1;
}
}
swap(A[pIndex],A[end]);
}
swap(A[pIndex],A[end]);
return pIndex;
}
答案 2 :(得分:1)
我也是一个C ++新手,但我发现自己对开始&gt; =结束时会发生什么感到好奇。您的分区功能看起来仍然会返回pIndex值,但我不知道您在哪里定义它。如果(我怀疑)它返回驻留在内存中的任何值,那么当你使用A [pIndex]
时,你很可能最终会引用一些未定义的内存位置