簡體   English   中英

Java:排序元素

[英]Java: Sorting Elements

我知道我們通常使用java.util.Arrays.sort(Object[], Comparator) JavaDoc 說它是一個修改過的歸並排序。

但我需要一個排序算法,將每個 object 與每個 object 進行比較。 我會有很多順序無關緊要的元素。 但是有些元素確實需要在特定的其他元素之后(不一定是連續的)。 而且我認為(但不知道)合並排序是不夠的......

也許,我想要實現的甚至不叫排序

我是否需要自己實現這樣的系統,或者是否有為此而存在的東西?


例子:

Obj1, Obj2, Obj3, Obj4

以下情侶的順序無關緊要(這意味着我的 Comparator 應該返回 0):

Obj1, Obj2 (*)
Obj1, Obj3
Obj2, Obj3
Obj2, Obj4 (*)
Obj3, Obj4

但! Obj4后面跟着Obj1確實很有必要。

由於有兩個 (*) 對,這在數學上意味着 Obj1 == Obj4。

它可以使用歸並排序嗎?

謝謝

如果您知道理想的排序,一種選擇是添加一些可排序的值,例如表示數據之間關系的 integer。 例如,如果項目 A 必須在項目 B 之前,則確保其排序值小於項目 B 的值。 然后,您可以提供一個僅查看排序值的自定義比較器,並且您可以使用標准排序算法。

聽起來您有一組 DAG(有向無環圖)。 我認為您需要對此進行 model ,然后對每個進行拓撲排序。 一種方法:

將每個元素包裝在包裝器 object 中,該包裝器引用 object 並具有用於保存與其他對象的依賴關系的列表。 將所有這些包裝器放入由 object id 鍵入的 hashMap 中。

對於沒有直接依賴關系的所有元素,發出該元素,並將其從 hashMap 中刪除。 重復直到 hashmap 為空。

如果依賴項列表通常很長,這將是低效的。 它適用於平均數量少於 5 個的直接依賴項。 如果由於執行了太多“重復直到 hashmap 為空”通道而導致性能問題,則應使用表示依賴關系圖的雙向數據結構,或者可能使用在此通道上只有一個依賴關系的 map 條目的列表,因此是下一次傳球的有力候選者。

這是未經測試的草圖:

class Obj           { String id;    }

class ObjWrapper    {
    String id;
    Obj obj;
    String[] depends; // may be null, may have null entries

    public ObjWrapper(Obj obj, String[] depends) {
        this.id = obj.id;
        this.obj = obj;
        if ( depends != null )
            this.depends = Arrays.copyOf(depends, depends.length);
    }
}

// order the objects by dependency. 
ArrayList<Obj> orderObjs(Iterable<ObjWrapper> objs)
{
    ArrayList<Obj> output = new ArrayList();
    HashMap<String, ObjWrapper> objMap = new HashMap();
    for ( ObjWrapper obj : objs )  
        objMap.put(obj.id, obj);  
    while ( !objMap.isEmpty() ) {
        Iterator<ObjWrapper> iter = objMap.values().iterator();
        while ( iter.hasNext() ) {
            ObjWrapper objWrapper = iter.next();
            if ( !hasDependencies(objWrapper, objMap) ) {
                output.add(objWrapper.obj);
                // must use iter to remove from hash, or bad things happen.
                iter.remove();  
            }
        }
    }
    return output;
}

boolean hasDependencies(ObjWrapper objWrapper, 
                        HashMap<String, ObjWrapper> objMap)
{
    if ( objWrapper.depends == null ) return false;
    for ( String depend : objWrapper.depends )   {
        if ( depend != null ) 
            if ( objMap.containsKey(depend) )
                return true;
            else
                depend = null;  // to speed up future passes
    }
    return false;
}

我發現你的要求有點不清楚。 但是,據我所知,您應該能夠通過提供適當的比較器來實現這一點。

編輯現在您已經添加了一個示例,我認為您甚至不需要排序。 假設元素 X、Y 和 Z 必須在某個元素 A 之后。您所要做的就是將 X、Y 和 Z 移到列表的末尾。 這可以在O(n)時間內完成,而不是排序的O(n logn)

或者,您可以將 A 移到列表的開頭。

如果您在元素之間有一個順序(即您可以說這個小於這個),那么合並排序(以及任何排序算法)實際上會對集合進行排序。

嘗試正式(數學)表達您需要的最終順序。

兩個元素的順序無關緊要這一事實並不意味着您的比較器必須返回 0。如果它們相等,它必須返回 0。

您已經實現了比較器(並將其傳遞給標准合並排序),如下所示:

int compare(Object o1, Object o2) {
  if (o1 instanceOf NotMatter) {
     if (o2 instanceOf NotMatter) {
        return 0;
     }
     return -1;
  }
  if (o2 instanceOf NotMatter) {
     return 1;
  }

  // ok, now we have two important objects
  if (o1.better(o2) {
     return 1;
  }
  if (o2.better(o1) {
     return -1;
  }
  return 0;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM