2013-06-24 85 views
3

我有2組數據。 讓我們說一個是人,另一個是一個團體。 一個人可以在多個組中,而一個組可以有多個人。 我的行動基本上是對羣體和人羣的CRUD。 以及確保人員列表在不同組中的方法(這被稱爲很多)。尋找表格式的數據結構

現在我正在考慮製作一個二進制0和1的表格,用水平方式代表所有人和垂直所有組。

我可以在O(n)時間通過添加每個二進制文件列表並與二進制列表的「和」操作進行比較來執行該方法。

E.g

Group A B C D 
ppl1 1 0 0 1 
ppl2 0 1 1 0 
ppl3 0 0 1 0 
ppl4 0 1 0 0 

check (ppl1, ppl2) = (1001 + 0110) == (1001 & 0110) 
       = 1111 == 1111 
       = true 

check (ppl2, ppl3) = (0110 + 0010) == (0110+0010) 
       = 1000 ==0110 
       = false 

我想知道如果有一個數據結構,做類似的事情已經讓我沒有寫我自己和維護O(n)的運行時間。

回答

2

我不知道你的問題的所有細節,但我的直覺是,你可能會在這裏思考的東西。您計劃在此數據結構中存儲多少個對象?如果你有大量的數據存儲在這裏,我建議你使用一個實際的數據庫而不是數據結構。這裏描述的操作類型是關係數據庫擅長的一些經典事例。 MySQLPostgreSQL是大型關係數據庫的例子,可以在睡眠中做這種事情。如果你想要更輕便的東西SQLite可能會感興趣。

如果你沒有大量的數據需要存儲在這個數據結構中,我建議保持簡單,只有在你確定它不足以滿足你的需求時纔會優化它需要做。作爲第一個鏡頭,我只是推薦使用內置的List接口來存儲你的人員和一個Map來存儲組。你可以做這樣的事情:

// Use a list to keep track of People 
List<Person> myPeople = new ArrayList<Person>(); 
Person steve = new Person("Steve"); 
myPeople.add(steve); 
myPeople.add(new Person("Bob")); 


// Use a Map to track Groups 
Map<String, List<Person>> groups = new HashMap<String, List<Person>>(); 
groups.put("Everybody", myPeople); 
groups.put("Developers", Arrays.asList(steve)); 

// Does a group contain everybody? 
groups.get("Everybody").containsAll(myPeople); // returns true 
groups.get("Developers").containsAll(myPeople); // returns false 

這definitly不是最快的選項可用,但如果沒有人的數量龐大,以保持跟蹤,你可能不會注意到任何性能問題。如果您確實有一些特殊情況會導致使用常規列表和地圖的速度不可行,請發佈它們,我們可以根據這些建議提出建議。

編輯:

閱讀您的意見後,看來我通過誤解你的問題在第一次運行。看起來你並不是很喜歡將羣組映射到人羣,而是將人員映射到羣組。你可能想要的更多的是這樣的:

Map<Person, List<String>> associations = new HashMap<Person, List<String>>(); 

Person steve = new Person("Steve"); 
Person ed = new Person("Ed"); 

associations.put(steve, Arrays.asList("Everybody", "Developers")); 
associations.put(ed, Arrays.asList("Everybody")); 

// This is the tricky part 
boolean sharesGroups = checkForSharedGroups(associations, Arrays.asList(steve, ed)); 

那麼你如何實現checkForSharedGroups方法?在你的情況下,由於圍繞這個數字相當低,我只是嘗試天真的方法,並從那裏去。

public boolean checkForSharedGroups(
        Map<Person, List<String>> associations, 
        List<Person> peopleToCheck){ 
    List<String> groupsThatHaveMembers = new ArrayList<String>(); 
    for(Person p : peopleToCheck){ 
     List<String> groups = associations.get(p); 
     for(String s : groups){ 
      if(groupsThatHaveMembers.contains(s)){ 
       // We've already seen this group, so we can return 
       return false; 
      } else { 
       groupsThatHaveMembers.add(s); 
      } 
     } 
    } 
    // If we've made it to this point, nobody shares any groups. 
    return true; 
} 

此方法在大型數據集上可能沒有很好的性能,但它很容易理解。因爲它被封裝在自己的方法中,所以如果事實證明你需要更好的性能,它也應該很容易更新。如果你確實需要提高性能,我會看看overriding the equals method of Person,這將使聯想中的查找映射更快。從那裏你也可以看看一個自定義類型,而不是字符串組,也有一個重寫的equals方法。這將大大加快上面使用的包含方法。

我不太關心性能的原因是您提到的數字並不像算法那麼大。因爲此方法一找到兩個匹配組就會返回,在最糟糕的情況下,您將調用ArrayList.contains的次數等於存在的組數。在最好的情況下,它只需要被調用兩次。如果您經常調用checkForSharedGroups,性能可能只會成爲一個問題,在這種情況下,您最好找一種方法來減少調用它,而不是優化方法本身。

+0

是的,OP應該採取更加面向對象的方法來解決這個問題,除非有某種其他原因(教授)以特定方式進行。使用面向對象的方法會使後面的問題變得更容易,例如 - 如果組需要一些額外的屬性,例如主持人,名稱,描述,該怎麼辦? – aglassman

+0

感謝您的建議,我估計最多會有~100人和〜10000人。不會有太多的數據修改。 唯一會被稱爲最多的將是檢查函數,該函數接受人員列表,如果它們都不屬於同一組,則返回true,否則返回false。我想以一種只使用很少內存的方式存儲數據,並且可以非常快速地執行此功能。 – user1181031

+0

我應該提到我將存儲組和其他人的所有信息(他們實際上是類),我只需要這個關係表來快速計算這1個函數。 – user1181031

0

你考慮過HashTable嗎?如果您知道所有將要使用的按鍵,則可以使用Perfect Hash Function,這將使您可以實現恆定的時間。

+0

我不確定你的意思。關鍵是什麼?團隊還是人民? – user1181031

+0

如果我明白你在做什麼正確的話,我會把組織看作關鍵人物,把他們看作是價值觀。 –

+0

我不認爲存儲它會使檢查功能更快。 – user1181031

0

如何爲人員和組分配兩個單獨的實體。 Inside People有一組Group,反之亦然。

class People{ 

Set<Group> groups; 
//API for addGroup, getGroup 

} 

class Group{ 

Set<People> people; 
//API for addPeople,getPeople 

} 

校驗(人P1,人們P2):

1)調用getGroup在兩個P1,P2
2)同時檢查該組的大小,
3)迭代較小集合,並檢查該組是否存在於其他組(組)

現在,基本上可以將People對象存儲在任何數據結構中。最好是一個鏈表,如果大小不是固定的,否則是一個數組。

+0

這可能工作,我只是想知道是否有10,000人,100組,檢查功能是否足夠快,以不到一秒的時間運行? – user1181031

+0

我不太確定,但是如果排除預處理時間(填充這些People對象)。我認爲這應該快速放棄。原因是,一旦預處理完成,你最終只會比較那些不喜歡你的情況的人,而你必須遍歷整個數組來首先計算總和。 – zerocool

+0

當你有10000個組時會發生什麼,你最終會得到一個10000位數?比做和它呢? – zerocool