#java #graph #undirected-graph
#java #График #неориентированный-граф
Вопрос:
Я пытаюсь реализовать граф, содержащий вершины (узлы), которые относятся к Profile
классу (например, профиль Facebook, но более посредственный). Каждая из вершин (профилей) хранится в двоичном дереве поиска, которое затем загружается или сохраняется в виде списка-массива.
Точно так же, как в Facebook Profile
, у некоторых (не у всех, поскольку не у всех есть друзья) экземпляров класса Profile
будут друзья, которые являются ребрами.
Каждая связь ребер графа сохраняется в текстовом файле, который затем считывается и добавляется в график отдельным методом во время построения графика.
Как только это будет сделано, я пытаюсь реализовать рекомендуемый метод:
два профиля, которые не являются друзьями, но хотели бы дружить на основе отношений, возможно, являющихся триадическим замыканием, но до сих пор у меня ничего не получалось, и в настоящее время я застрял.
- В настоящее время мне удалось создать график, используя a
Matrix
, но я застрял в попытке найти возможное решение, чтобы рекомендовать возможных друзей для каждой вершины, у которой есть другj
, у которого есть другx
, который не является другом вершины (текущий профиль). -
Предполагается, что каждый из рекомендованных друзей сохраняется в массиве и добавляется в двоичное дерево поиска.
private List<Profile> getRecommendedFriends(){ Iterator profileIterator = this.vertexProfileMap.entrySet().iterator(); List<Profile> recommendedProfiles = new ArrayList<>(); Boolean isContained; while(profileIterator.hasNext()){ Map.Entry mapElement = (Map.Entry)profileIterator.next(); Profile user = (Profile) mapElement.getValue(); int sizeOfList = user.numOfFriends(); for(int i = 0; i < sizeOfList; i ){ recommendedProfiles.add(user.getFriend(i)); for(int x = 0; x < user.numOfFriends(); x ){ for(int j = 0; j < user.numOfFriends(); j ){ isContained = user.getFriend(x).getName().equals(user.getFriend(j).getName()); if(!isContained){ recommendedProfiles.add(user.getFriend(j)); } } } } } return recommendedProfiles; }
Комментарии:
1. Предполагается ли, что ваш алгоритм должен для конкретного данного пользователя находить всех возможных релевантных друзей — т.е.. друзья друзей пользователя, которые не отображаются в карте друзей пользователя?
2. Предполагается, что алгоритм берет вершину (user [x]), находит друзей пользователей [y], подтверждая, что у них есть отношение ребер в матрице, и проверяет, есть ли у друга пользователя [y] друг [z] (отношение ребер), который не дружит с текущим пользователем[x] и поместите его в arrayofRecommondations для этого пользователя [x] .
3. Спасибо за текущее решение, я буду работать над ним и посмотрю, может ли оно применяться. 🙂 — Ранн Лифшиц
Ответ №1:
Основываясь на данном алгоритме и предполагая Profile
, что у класса будет вызываться дополнительный метод containsProfile(Profile p)
, который проверяет, содержится ли данный профиль в списке друзей пользователя, должен работать следующий подход грубой силы:
private Map<Profile,List<Profile>> getRecommendedFriends(){
// under the asssumption that vertexProfileMap maps all Profiles/Users
Iterator profileIterator = this.vertexProfileMap.entrySet().iterator();
Map<Profile,List<Profile>> recommendedProfiles = new HashMap<>();
while(profileIterator.hasNext()){
Map.Entry mapElement = (Map.Entry)profileIterator.next();
Profile currentUser = (Profile) mapElement.getValue();
List<Profile> recommendedPerProfile = new ArrayList<>();
// iterate over all of the friends of the current user
for(int i = 0, endI = currentUser.numOfFriends(); i < endI; i ){
Profile checkedFriend = currentUser.getFriend(i);
// iterate over all of the friends of the currently checked friend
for(int j = 0; endJ < checkedFriend.numOfFriends(); j < endJ; j) {
Profile possibleRecommendation = checkedFriend.getFriend(j);
// add a recommended profile if it belongs to a friend of a friend, but is not a friend of the current user
if(!currentUser.containsProfile(possibleRecommendation)) {
recommendedPerProfile.add(possibleRecommendation);
}
}
}
// remove possible duplicate recommendations
recommendedProfiles = recommendedProfiles.stream()
.distinct()
.collect(Collectors.toList());
// map the current user to a list of friend recommendations
recommendedProfiles.put(currentUser, recommendedPerProfile);
}
return recommendedProfiles;
}
Комментарии:
1. Я создал аналогичный метод в классе graph, а не в классе profile, чтобы получить имя профиля (строка), метку (вершину) профиля из массива профилей (каждый из этих профилей был добавлен из двоичного дерева поиска). Я попытаюсь реализовать ваше решение с помощью строки в качестве входных данных, а не объекта профиля, и посмотреть, работает ли это.
2. @BrevynKurt: Рад помочь. Обратите внимание на предположение в приведенной выше реализации —
vertexProfileMap
это карта всех существующих профилей.3. О да, тогда я виноват. Однако у меня есть еще один вопрос о переменных endI и endJ, как именно они реализованы в условиях? они объявлены где-то еще или?
4. @BrevynKurt: endI и endJ — это соглашения об итерациях, которые я использую уже много лет. Небольшая оптимизация циклов for позволяет вычислять конечное условие цикла for только один раз во время цикла for, объявляясь вместе с итератором (i и j), и улучшает читаемость IMHO.
5. Верно, это имеет смысл. Поэтому моя реализация должна будет перевести ваш перевод циклов for в обычный стандарт. Заранее спасибо 🙂