Порівняння представлення графіків об’єктів із поданнями сусідства та матрицями


82

В даний час я дотримуюся порад Стіва Єгге щодо підготовки до співбесіди з технічного програмування: http://steve-yegge.blogspot.com/2008/03/get-that-job-at-google.html

У своєму розділі про графіки він зазначає:

Існує три основних способи представити графік у пам’яті (об’єкти та покажчики, матриця та список суміжностей), і вам слід ознайомитися з кожним поданням та його плюсами та мінусами.

Плюси та мінуси представлення матриць та списків суміжності описані в CLRS, але мені не вдалося знайти ресурс, який порівнює їх із поданням об’єкта.

Подумавши лише про це, я сам можу зробити висновок щодо цього, але хотів би переконатися, що не пропустив чогось важливого. Якби хтось міг описати це всебічно або вказати мені на ресурс, який це робить, я був би дуже вдячний.


як щодо індуктивних графіків - до якої з 3 категорій вони підпадають?
Ерік Каплун,

Відповіді:


94

об'єкти та покажчики

Це лише основні структури даних, як Hammar, сказане в іншій відповіді, і Javaви б представляли це за допомогою таких класів, як ребра та вершини. Наприклад, ребро з'єднує дві вершини і може бути направленим або ненаправленим, і воно може містити вагу. Вершина може мати ідентифікатор, назву тощо. В основному обидві вони мають додаткові властивості. Таким чином, ви можете побудувати свій графік з ними, як

Vertex a = new Vertex(1);
Vertex b = new Vertex(2);
Edge edge = new Edge(a,b, 30); // init an edge between ab and be with weight 30  

Цей підхід зазвичай використовується для об'єктно-орієнтованих реалізацій, оскільки він є більш читабельним та зручним для об'єктно-орієнтованих користувачів;).

матриця

Матриця - це просто простий двовимірний масив. Припускаючи, що у вас є ідентифікатори вершин, які можна представити у вигляді масиву int, як це:

int[][] adjacencyMatrix = new int[SIZE][SIZE]; // SIZE is the number of vertices in our graph
adjacencyMatrix[0][1] = 30; // sets the weight of a vertex 0 that is adjacent to vertex 1

Це зазвичай використовується для щільних графіків, де необхідний доступ до індексу. За допомогою цього ви можете представити ненаправлену та зважену структуру.

список суміжності

Це просто простий мікс структури даних, я зазвичай реалізую це, використовуючи HashMap<Vertex, List<Vertex>>. Подібним використовується HashMultimapв Гуаві.

Цей підхід класний, тому що у вас є O (1) (амортизований) пошук вершин, і він повертає мені список усіх сусідніх вершин до цієї конкретної вершини, яку я вимагав.

ArrayList<Vertex> list = new ArrayList<>();
list.add(new Vertex(2));
list.add(new Vertex(3));
map.put(new Vertex(1), list); // vertex 1 is adjacent to 2 and 3

Це використовується для представлення розріджених графіків. Якщо ви подаєте заявку в Google, ви повинні знати, що веб-графіка розріджена. Ви можете мати справу з ними більш масштабовано, використовуючи BigTable .

О, і до речі, ось дуже хороший підсумок цього допису із вигадливими малюнками;)


Цей підхід класний, оскільки у вас є пошук вершин O (1), ця складність дещо неправильна, зокрема це O (1 + альфа), де альфа = кількість слотів у хеш-карті / кількість вершин. Тому я пропоную використовувати масив замість хеш-карти
Тимофій

@Tim це амортизовано O (1). Ваш розрахунок складності сильно залежить від реалізації. Дивіться javadoc HashMap( docs.oracle.com/javase/7/docs/api/java/util/HashMap.html ), в якому сказано: This implementation provides constant-time performance for the basic operations= O (1) амортизовано.
Thomas Jungblut 03.03.13

6
@Tim Я думаю, що всі тут знають, що доступ до масиву швидший, ніж будь-яке HashTableвикористання. Тож не потрібно нікчемно обводити невеликі постійні альфа-витрати, якими можна знехтувати.
Thomas Jungblut 03.03.13

2
Будь ласка, не зрозумійте мене неправильно, я не ображаю вас на приємну відповідь, але у мене відчуття, що ваша відповідь може бути покращена, то чому б не згадувати про це тут :)
Тимофій

2
@Tim Я додав амортизовану ноту до відповіді. Дякую.
Thomas Jungblut 03.03.13

7

Об'єкти та покажчики здебільшого однакові зі списком суміжностей, принаймні для цілей порівняння алгоритмів, що використовують ці подання.

Порівняйте

struct Node {
    Node *neighbours[];
};

з

struct Node {
    Node *left;
    Node *right;
};

В останньому випадку ви можете легко побудувати список сусідів на льоту, якщо з ним легше працювати, ніж з названими вказівниками.


4

Перевага представлення об’єкта ( списку випадковості ) полягає в тому, що дві сусідні вершини мають однаковий екземпляр ребра. Це дозволяє легко маніпулювати неорієнтованими крайовими даними (довжина, вартість, потік або навіть напрямок). Однак він використовує додаткову пам'ять для покажчиків.


5
чому існує посилання на подання списку суміжності, яке називається "список випадків"? Напевно, краще використовувати цей один алгоритміст.com
index.php/Graph_data_structures#Incidence_List

1

Ще один хороший ресурс: Академія Хан - "Представлення графіків"

Окрім списку суміжності та матриці суміжності, вони перелічують "списки ребер" як 3-й тип подання графіків. Список країв можна інтерпретувати як список "крайових об'єктів", таких як відповіді Томаса на "об'єкти та покажчики".

Перевага: Ми можемо зберігати більше інформації про край (згаданий Міхалом)

Недолік: робота з дуже повільною структурою даних:

  • Пошук краю: O (log e)
  • Видалити край: O (e)
  • Знайти всі вузли, суміжні з даним вузлом: O (e)
  • Визначте, чи існує шлях між двома вузлами: O (e ^ 2)

e = кількість ребер

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.