C# 快速排序未正确排序

C# 快速排序未正确排序,c#,quicksort,C#,Quicksort,试图从快速排序的实现中学习,我无法找到它不能正确排序的原因 使用此顺序: 6,7,12,5,9,8,65,3 它返回以下内容: 3,5,7,8,9,65,12,6 这似乎有些道理,但不是全部。我错过了什么 这是我的密码: static void Main(string[] args) { QuickSort qs = new QuickSort(); int[] arr = new int[] { 6, 7, 12, 5, 9,

试图从快速排序的实现中学习,我无法找到它不能正确排序的原因

使用此顺序:

6,7,12,5,9,8,65,3

它返回以下内容:

3,5,7,8,9,65,12,6

这似乎有些道理,但不是全部。我错过了什么

这是我的密码:

 static void Main(string[] args)
        {
            QuickSort qs = new QuickSort();

           int[] arr = new int[] { 6, 7, 12, 5, 9, 8, 65, 3 };

            foreach (int l in arr)
            {
                Console.Write(l + ", ");
            }

            int left = 0;
            int right = arr.Count() - 1;

            int[] arrr = qs.DoQuickSort(ref arr, left, right);
            Console.WriteLine("Sorted List: ");
            foreach (int i in arrr)
            {
                Console.Write(i + " ");
            }



            Console.ReadLine();
        }

   public int Partition(int[] array, int left, int right, int PivotIndex)
    {
    int pivValue = array[PivotIndex];

    array = Swap(ref array, PivotIndex, right);

    int storeIndex = left;

    for (int i = PivotIndex; i < right-1; i++)
    {
        if (array[i] <= pivValue)
        {
            array = Swap(ref array, i, storeIndex);
            storeIndex = storeIndex + 1;
        }
    }

    array = Swap(ref array, storeIndex, right);

    return storeIndex;
}

public int[] Swap(ref int[] arr, int first, int second)
{
    int temp = arr[first];
    arr[first] = arr[second];
    arr[second] = temp;

    return arr;
}

public int[] DoQuickSort(ref int[] array, int left, int right)
{
    if (right > left)
    {
        int PivIndex = (left + right) / 2;
        int newPivIndex = Partition(array, left, right, PivIndex);
        DoQuickSort(ref array, left, newPivIndex - 1);
        DoQuickSort(ref array, newPivIndex + 1, right);
    }

    return array;
}
static void Main(字符串[]args)
{
快速排序qs=新的快速排序();
int[]arr=新的int[]{6,7,12,5,9,8,65,3};
foreach(内部l在arr中)
{
控制台。写(l+“,”);
}
int左=0;
int right=arr.Count()-1;
int[]arrr=qs.DoQuickSort(参考arr,左,右);
Console.WriteLine(“排序列表:”);
foreach(arrr中的int i)
{
控制台。写入(i+“”);
}
Console.ReadLine();
}
公共int分区(int[]数组、int左、int右、int数据透视索引)
{
int pivValue=数组[数据透视索引];
数组=交换(参考数组,数据透视索引,右侧);
int storeIndex=左;
for(int i=数据透视索引;i
在您的
分区
方法中,您有一个错误的循环范围:

for (int i = PivotIndex; i < right-1; i++)
for(int i=PivotIndex;i
应成为:

for (int i = left; i < right; i++)
for(int i=left;i
签出显示:

function partition(array, left, right, pivotIndex)
     pivotValue := array[pivotIndex]
     swap array[pivotIndex] and array[right] // Move pivot to end
     storeIndex := left
     for i  from  left to right - 1 // left ≤ i < right  
         if array[i] ≤ pivotValue 
             swap array[i] and array[storeIndex]
             storeIndex := storeIndex + 1
     swap array[storeIndex] and array[right] // Move pivot to its final place
     return storeIndex
函数分区(数组、左、右、数据透视索引)
数据透视值:=数组[数据透视索引]
交换数组[pivotIndex]和数组[right]//将数据透视移动到末尾
storeIndex:=左
对于i,从左到右-1//左≤ 我是对的
if数组[i]≤ 数据透视值
交换数组[i]和数组[storeIndex]
storeIndex:=storeIndex+1
交换数组[storeIndex]和数组[right]//将枢轴移动到其最终位置
返回存储索引

注意:
左≤ 我

除了我对问题本身的评论之外,我想指出
Swap()
DoQuickSort()
方法不需要返回数组(根据我在评论中的注释,说明数组本身就是一个引用).为此,执行此项工作的代码应如下所示:

public int Partition(int[] array, int left, int right, int pivotIndex)
{
    int pivValue = array[pivotIndex];

    Swap(array, pivotIndex, right);

    int storeIndex = left;

    for (int i = left; i < right; i++)
    {
        if (array[i] <= pivValue)
        {
            Swap(array, i, storeIndex);
            storeIndex = storeIndex + 1;
        }
    }

    Swap(array, storeIndex, right);

    return storeIndex;
}

public void Swap(int[] arr, int first, int second)
{
    int temp = arr[first];
    arr[first] = arr[second];
    arr[second] = temp;
}

public void DoQuickSort(int[] array, int left, int right)
{
    if (right > left)
    {
        int pivIndex = (left + right) / 2;
        int newPivIndex = Partition(array, left, right, pivIndex);
        DoQuickSort(array, left, newPivIndex - 1);
        DoQuickSort(array, newPivIndex + 1, right);
    }
}
公共int分区(int[]数组、int左、int右、int数据透视索引)
{
int pivValue=数组[数据透视索引];
交换(数组,数据透视索引,右侧);
int storeIndex=左;
for(int i=左;i<右;i++)
{
if(数组[i]左)
{
int-pivIndex=(左+右)/2;
int newPivIndex=分区(数组,左,右,pivIndex);
DoQuickSort(数组,左,newPivIndex-1);
DoQuickSort(数组,newPivIndex+1,右);
}
}

你是要求别人递给你一条鱼,还是要求别人教你如何钓鱼

学习如何调试您自己的程序,而不是依赖其他人为您调试,这是一项在将来对您很有帮助的技能

当遇到这个问题时,我要做的第一件事是用注释标记代码,指出代码每一部分的语义目的:

// Choose a pivot halfway along the portion of the list I am searching.
int PivIndex = (left + right) / 2; 
// Partition the array so that everything to the left of the pivot
// index is less than or equal to the pivot, and everything to
// the right of the pivot is greater than or equal to the pivot.
int newPivIndex = Partition(array, left, right, PivIndex); 
// Recursively sort each half.
DoQuickSort(ref array, left, newPivIndex - 1); 
DoQuickSort(ref array, newPivIndex + 1, right); 
好的,现在,这里的某个地方有一个bug。在哪里?开始列出您认为正确的事实,并为每个事实编写一个断言。编写自己的助手方法,比如AllLessThan,它为您验证断言

// Choose a pivot halfway along the portion of the list I am searching.
int PivIndex = (left + right) / 2;

int pivotValue = array[PivIndex];
// Partition the array so that everything to the left of the pivot
// index is less than or equal to the pivot, and everything to
// the right of the pivot is greater than or equal to the pivot.
int newPivIndex = Partition(array, left, right, PivIndex); 
Debug.Assert(array[newPivIndex] == pivotValue);
Debug.Assert(AllLessThanOrEqual(array, left, newPivIndex, pivotValue));
Debug.Assert(AllGreaterThanOrEqual(array, newPivIndex, right, pivotValue));
// Recursively sort each half.
DoQuickSort(ref array, left, newPivIndex - 1); 
Debug.Assert(IsSorted(array, left, newPivIndex));
DoQuickSort(ref array, newPivIndex + 1, right); 
Debug.Assert(IsSorted(array, left, right));

现在,当您再次运行此程序时,一旦您的一个断言被违反,就会弹出一个框,告诉您错误的性质。继续这样做,用断言记录您的先决条件和后决条件,直到您找到错误。

您真的需要开始发布完整的代码。您不断向我们展示p分区功能和快速排序功能,但您没有向我们展示主要的方法。您在本网站上就这个主题做了很多次。看起来您在开始时少了几行--是不是被意外剪掉了?(编辑:哦,没关系;大括号只是奇怪地对齐了)就编码风格和标准而言,PivotIndex是分区方法的一个参数,PivIndex是DoQuickSort方法的一个局部变量。因此,惯例规定两者都应该以小写字母开头,即PivotIndex和PivIndex。此外,还可以通过引用传递数组(ref int[]数组),这是不必要的。数组已经是对象引用,您正在修改它们的组成元素,而不是数组引用本身。顺便说一句:您不必通过引用传递这些数组。数组是引用类型,因此被调用的函数始终可以操作项。仅当您要替换整个数组(例如,调整其大小)时需要通过引用传递。最后一个(?)注意-我猜Partition()和Swap()不需要是公共的,因为调用者希望只调用DoQuickSort()非常感谢你的提示!!)这与为什么C++中的大多数标准算法使用第一个索引,以及超出数组的最终索引的原因有关,所以迭代可以是(i=开始;i <结束;i++)。因此,它永远不会触及最后一个要素,但你总是知道它在哪里。一个要素是很难学习的,但绝对必要的。