【问题标题】:Using comparator in custom quicksort in java在java中的自定义快速排序中使用比较器
【发布时间】:2015-04-13 02:43:37
【问题描述】:

我有一个我自己实现的快速排序方法。我给该方法一个对象数组。我如何使用比较器告诉方法对象将按哪个属性排序? 我搜索了一下,发现了如何实现比较器,但没有发现如何在搜索方法中使用它,因为我发现的每个示例都只使用了 arrays.sort()。

我需要不同的 getter 方法来获取不同的属性,我看不出比较器对此有何帮助?

我只需要一点帮助来启动整个事情,或者也许有人可以设法在网上找到一个很好的例子?

    public WifiData[] qsortSSID(WifiData[] array, int left, int right){
    int ll=left;
    int rr=right;

        if (rr>ll){
            String pivot=array[(ll+rr)/2].getSSID();
            //System.out.println(pivot);
            while (ll <=rr){
                //finde erstes element >= pivot
                while(ll<right && array[ll].getSSID().compareTo(pivot) < 0){
                    ll +=1;
                }
                //finde letztes elemtn kleiner gleich pivot
                while(rr>left && array[rr].getSSID().compareTo(pivot) > 0){
                    rr -=1;
                }
                if (ll <=rr){
                    swap(array, ll ,rr);
                    ll +=1;
                    rr -=1;

                }
            }
            if (left < rr){
                qsortSSID(array,left,rr);

            }
            if (ll<right){
                qsortSSID(array,ll,right);
            }
        }



    return array;
}

【问题讨论】:

  • 阅读the documentation。调用compareTo,它会返回一个int,它会告诉你哪个对象“更大”。
  • 你能发布你的代码吗?
  • (a) 你为什么要实现你的自己的方法?当前的排序方法非常优化,(b) 请展示你的实现...
  • 我自己做了因为任务说的。这是给学校的,我认为让你为我做这只是作弊。
  • 好的,现在我编辑了它。我应该按 ssid 排序一次,然后按 mac 排序一次,我应该给我的排序方法一个比较器来告诉它按哪个排序

标签: java quicksort comparator


【解决方案1】:

WifiData 应该通过比较thisotherSSID 来实现Comparable&lt;WifiData&gt; 接口。

您的方法的签名将变为:

public Comparable[] qsort(Comparable[] array, int left, int right)

而且实现会更加抽象,所以:

String pivot=array[(ll+rr)/2].getSSID();

会变成:

Comparable pivot=array[(ll+rr)/2];

while(ll<right && array[ll].getSSID().compareTo(pivot) < 0){

会变成:

while(ll<right && array[ll].compareTo(pivot) < 0){

等等

例子:

class WifiData implements Comparable<WifiData> {
    String SSID;

    public String getSSID() {
        return SSID;
    }

    @Override
    public int compareTo(WifiData o) {
        return this.SSID.compareTo(o.getSSID());
    }

    public Comparable[] qsort(Comparable[] array, int left, int right){
        int ll=left;
        int rr=right;

        if (rr>ll){
            Comparable pivot = array[(ll+rr)/2];
            while (ll <=rr){
                while(ll<right && array[ll].compareTo(pivot) < 0){
                    ll +=1;
                }
                while(rr>left && array[rr].compareTo(pivot) > 0){
                    rr -=1;
                }
                if (ll <=rr){
                    swap(array, ll ,rr);
                    ll +=1;
                    rr -=1;
                }
            }
            if (left < rr){
                qsort(array,left,rr);

            }
            if (ll<right){
                qsort(array,ll,right);
            }
        }
        return array;
    }

    void swap(Comparable[] arr, int l, int r) {
        Comparable t = arr[l];
        arr[l] = arr[r];
        arr[r] = t;
    }
}

更新
阅读下面的评论后,您的问题更加清晰。你应该做的是使用Comparator:你可以实现不同的比较器,每个比较器按不同的属性排序。

请看下面的例子:

class WifiData {
    String SSID;

    public String getSSID() {
        return SSID;
    }

    // example how to use it
    public static void main(String[] args) {
        Comparator<WifiData> comp = new SSIDComparator();
        WifiData[] arr = new WifiData[10];
        // ... fill the array
        arr = qsort(arr, 0, arr.length-1, comp);        
    }

    public static WifiData[] qsort(WifiData[] array, 
                                    int left, 
                                    int right,                        
                                    Comparator<WifiData> comp){
        int ll=left;
        int rr=right;

        if (rr>ll){
            WifiData pivot = array[(ll+rr)/2];
            while (ll <=rr){
                // that's how we'll use the comparator:
                while(ll<right && comp.compare(array[ll], pivot) < 0){
                    ll +=1;
                }
                while(rr>left &&  comp.compare(array[rr], pivot) > 0){
                    rr -=1;
                }
                if (ll <=rr){
                    swap(array, ll ,rr);
                    ll +=1;
                    rr -=1;
                }
            }
            if (left < rr){
                qsort(array,left,rr, comp);

            }
            if (ll<right){
                qsort(array, ll, right, comp);
            }
        }
        return array;
    }    

    // an example of Comparator that sorts by SSID
    static class SSIDComparator implements Comparator<WifiData>{
        @Override
        public int compare(WifiData o1, WifiData o2) {
            return o1.getSSID().compareTo(o2.getSSID());
        }
    }
}

【讨论】:

  • 我非常感谢您的帮助,但我不知道,我开始认为这项任务只是非常尴尬。它的字面意思是“不必执行两次快速排序,使用您提供给排序方法的比较器”。但即使有你的建议,我也只能比较 ssid,我无法以相同的方法按 mac 排序。
  • @banzai 明白了。请参阅答案的“更新”部分。
【解决方案2】:

这是我编写的示例Comparator,用于按多维数组的第一个元素对其进行排序:

    private static class FirstItemComparator implements Comparator<int[]> {
        public int compare(int[] first, int[] second) {
            if (first[0] < second[0]) {
                return -1;
            } else if (first[0] == second[0]) {
                return 0;
            } else {
                return 1;
            }
        }
    }

    int[][] test = {{0,1},{4,8},{3,5}, {10,12}, {9,10}};
    Arrays.sort(input, new FirstItemComparator());
    // test is now {{0,1},{3,5},{4,8},{9,10},{10,12}}

通常,如果您要将比较器传递给比较两个实例的静态方法,则通常只会编写比较器(传递比较器本质上就像传递其他语言中的函数)。您可以编写不同的比较器以几种不同的方式对同一类型的对象进行排序。

如果您想将一个实例与另一个实例进行比较,那么您将在类本身上实现接口Comparable(而不是像我那样创建一个新类)。但是,这会对对象进行排序,因此您不能编写三个或四个 compareTo 方法来以不同的方式对对象进行排序。

【讨论】:

  • 是的,Arrays.sort 对新的 StartTimeComparator 有什么作用?这就是我不明白的
  • 它执行排序算法(可能是快速排序的一种版本),但使用比较方法来确定我的二维数组中一维数组的顺序。因此,排序现在使用if(theComparator.compare(item1, item2) &lt; 0),而不是评估if(item1 &lt; item2)
猜你喜欢
  • 2014-09-05
  • 1970-01-01
  • 2014-12-25
  • 2021-03-23
  • 2020-02-24
  • 1970-01-01
  • 2016-11-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多