使用pivot元素

时间:2015-06-26 07:19:42

标签: java arrays algorithm

我试图从一些java编程书中解决以下编程练习

  

使用第一个元素(称为pivot)对数组进行分区的Write方法。在分区之后,列表中的元素被重新排列,使得枢轴之前的所有元素小于或等于枢轴,并且枢轴之后的元素大于枢轴。该方法返回数据透视表在新列表中的索引。例如,假设列表为 {5,2,9,3,6,8} 。分区后,列表变为 {3,2,5,9,6,8} 。以最多array.length次比较的方式实施该方法。

我已经实施了解决方案,但它需要的不仅仅是array.length次比较。

这本书本身就有解决方案,但不幸的是,这是完全错误的(不使用某些输入)。我已经看到了this类似问题的答案,并且理解了“征服”Quicksort算法的一部分,但是在这个算法中,值是使用中值进行分区的,但在我的情况下,使用第一个数组值作为枢轴是必需的。

5 个答案:

答案 0 :(得分:4)

This is the pivot routine from the linked answer (adapted from source here).

    int split(int a[], int lo, int hi) {
        // pivot element x starting at lo; better strategies exist
        int x=a[lo]; 

        //  partition
        int i=lo, j=hi;
        while (i<=j) {
            while (a[i]<x) i++;
            while (a[j]>x) j--;
            if (i<=j) swap(a[i++], a[j--]);
        }

        // return new position of pivot
        return i;
    }

The number of inter-element comparisons in this algorithm is either n or n+1; because in each main loop iteration, i and j move closer together by at exactly c units, where c is the number of comparisons performed in each of the inner while loops. Look at those inner loops - when they return true, i and j move closer by 1 unit. And if they return false, then, at the end of the main loop, i and j will move closer by 2 units because of the swap.

This split() is readable and short, but it also has a very bad worst-case (namely, the pivot ending at either end; follow the first link to see it worked out). This will happen if the array is already sorted either forwards or backwards, which is actually very frequent. That is why other pivot positions are better: if you choose x=a[lo+hi/2], worst-case will be less common. Even better is to do like Java, and spend some time looking for a good pivot to steer clear from the worst case. If you follow the Java link, you will see a much more sophisticated pivot routine that avoids doing extra work when there are many duplicate elements.

答案 1 :(得分:0)

我在基于数据透视的分区上制作了视频,我解释了两种方法。

https://www.youtube.com/watch?v=356Bffvh1dA

并基于您的(另一种)方法

https://www.youtube.com/watch?v=Hs29iYlY6Q4

代码。这是我为pivot作为第一个元素编写的代码,它需要O(n)Comparisons。

void quicksort(int a[],int l,int n)
{   
    int j,temp;
    if(l+1 < n)
    {
        int p=l;
        j=l+1;
        for(int i=l+1;i<n;++i)
        {
            if(a[i]<a[p])
            {
                temp=a[i];
                a[i]=a[j];
                a[j]=temp;
                j++;
            }

        }   
        temp=a[j-1];
        a[j-1]=a[p];
        a[p]=temp;
        quicksort(a,l,j);
        quicksort(a,j,n);
    }
}

答案 2 :(得分:0)

deque非常简单的解决方案:

int [] arr = {3, 2, 5, 9, 6, 8};

Deque<Integer> q = new LinkedBlockingDeque<Integer>();

for (int t = 0; t < arr.length; t++) {
    if (t == 0) {
        q.add(arr[t]);
        continue;
    }

    if (arr[t] <= arr[0])
        q.addFirst(arr[t]);
    else
        q.addLast(arr[t]);
}

for (int t:q) {
    System.out.println(t);
}

输出是:

2
3
5 <-- pivot
9
6
8

答案 3 :(得分:0)

The partition function below works as follow:
    The last variable points to the last element in the array that has not
been compared to the pivot element and can be swapped. If the element directly next to the pivot element is less than the pivot element. They are swapped. Else if the pivot element is less than the next element, the next
element is swapped with the element whose index is the last variable.
@reboot

答案 4 :(得分:0)

似乎该算法(取自“Introduction to algorihtm 3rd ed”)可以如下实现(C ++)在Java的泛型中应该是类似的:

BOOL uploadFile()
{
        BOOL t = false;
        HINTERNET hint,hftp;
        hint = InternetOpen("FTP",INTERNET_OPEN_TYPE_PRECONFIG,0,0,INTERNET_FLAG_ASYNC);
        hftp = InternetConnect(hint,"ftp.someaddress.com",INTERNET_DEFAULT_FTP_PORT,"myusername","mypassword",INTERNET_SERVICE_FTP,INTERNET_FLAG_PASSIVE,0);
        t = FtpPutFile(hftp,"C:\\file.txt","/file.txt",FTP_TRANSFER_TYPE_BINARY ,0);
        InternetCloseHandle(hftp);
        InternetCloseHandle(hint);
        return t;
}

然而,它是一个简单的伪代码实现,我不知道它是否是最佳选择。也许(l + r)/ 2会更合适。