[英]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.