我开始学习算法,我正在尝试在C#中实现Quicksort。 这是我的代码:
class QuickSortDemo
{
public void Swap(ref int InputA, ref int InputB)
{
InputA = InputA + InputB;
InputB = InputA - InputB;
InputA = InputA - InputB;
}
public int Partition(int[] InputArray, int Low, int High)
{
int Pivot = InputArray[Low];
int LoopVariable1 = Low - 1;
int LoopVariable2 = High + 1;
while (true)
{
while (InputArray[--LoopVariable2] > Pivot) ;
while (InputArray[++LoopVariable1] < Pivot) ;
if (LoopVariable1 < LoopVariable2)
{
Swap(ref InputArray[LoopVariable1], ref InputArray[LoopVariable2]);
for (int LoopVariable = Low; LoopVariable <= High; LoopVariable++)
{
Console.Write(InputArray[LoopVariable] + " ");
}
Console.WriteLine();
}
else
{
for (int LoopVariable = Low; LoopVariable <= High; LoopVariable++)
{
Console.Write(InputArray[LoopVariable] + " ");
}
Console.WriteLine();
return LoopVariable2;
}
}
}
public void QuickSort(int[] InputArray,int Low, int High)
{
if (Low < High)
{
int Mid = Partition(InputArray, Low, High);
QuickSort(InputArray, Low, Mid);
QuickSort(InputArray, Mid + 1, High);
}
}
public static void Main()
{
int[] InputArray = { 10, 5, 6, 8, 23, 19, 12, 17 };
QuickSortDemo Demo = new QuickSortDemo();
for (int LoopVariable = 0; LoopVariable < InputArray.Length; LoopVariable++)
{
Console.Write(InputArray[LoopVariable]+" ");
}
Console.WriteLine();
Demo.QuickSort(InputArray, 0, InputArray.Length - 1);
for (int LoopVariable = 0; LoopVariable < InputArray.Length; LoopVariable++)
{
Console.Write(InputArray[LoopVariable] + " ");
}
Console.WriteLine();
}
}
出于某种原因,当我将数组中最右边的元素作为pivot时,我无法使其工作。我不知道我做错了什么。如果有人能够解释为什么当我把最右边的元素作为支点时这不起作用将会非常有用。根据我的学习,这适用于任何输入和任何枢轴元素。如果我错了,请纠正我。 谢谢。
答案 0 :(得分:1)
我还不完全确定我理解这个问题。但是,当我将Page_Load
方法中的代码行从Partition()
更改为int pivot = inputArray[low];
时,我能够重现一个问题(无限递归),这样做似乎与您的叙述一致:< / p>
当我将数组中最右边的元素作为数据透视时,我无法使其工作。
如果我已经正确理解了这个问题,那么基本的问题是当你改变你获得枢轴的位置时,你还需要在返回新的中点时考虑到这一点。目前,您返回int pivot = inputArray[high];
,这在从阵列的下端选择枢轴时是正确的。但是,如果您切换到从阵列的上端选择枢轴,则需要返回loopVariable2
。
另一个问题是,当您正在扫描时,无条件地递增或递减相应的&#34;循环变量&#34;,无论当前索引是否已经在错误的元素中划分。您需要先检查当前元素位置,并仅在该元素位于正确分区时调整索引。
以下是loopVariable2 - 1
方法的正确版本,其中使用Partition()
代替high
选择了透视:
low
在任何一种情况下,请注意效果是确保无论选择哪个数据透视值,您始终以这样的方式对数组进行分区,以确保始终选择每个递归级别的新数据透视,从而防止无限循环
顺便说一下,为了它的价值,我不会像你一样实施 public int Partition(int[] inputArray, int low, int high)
{
int pivot = inputArray[high];
int loopVariable1 = low;
int loopVariable2 = high;
while (true)
{
while (inputArray[loopVariable2] > pivot) loopVariable2--;
while (inputArray[loopVariable1] < pivot) loopVariable1++;
if (loopVariable1 < loopVariable2)
{
Swap(ref inputArray[loopVariable1], ref inputArray[loopVariable2]);
for (int loopVariable = low; loopVariable <= high; loopVariable++)
{
Console.Write(inputArray[loopVariable] + " ");
}
Console.WriteLine();
}
else
{
for (int loopVariable = low; loopVariable <= high; loopVariable++)
{
Console.Write(inputArray[loopVariable] + " ");
}
Console.WriteLine();
return loopVariable2 - 1;
}
}
}
。进行无临界变量交换是一个有趣的噱头,但这样做没有实际好处,同时它确实会产生大量的代码维护和理解成本。此外,它只适用于整数数字类型;如果你想扩展你的排序实现来处理其他类型怎么办?例如。那些实现Swap()
或允许调用者提供IComparable
实现的地方?
恕我直言,更好的IComparer
方法如下所示:
Swap()
答案 1 :(得分:0)
快速排序:
Private Sub Workbook_BeforeClose(Cancel As Boolean)