#java #collections #linked-list
Вопрос:
Я пытаюсь сохранить более 1 элемента данных в одном индексе в моем связанном списке. Все примеры в моем учебнике, похоже, иллюстрируют добавление только 1 части данных на индекс. Я предполагаю, что можно добавить больше?
Например, используя API коллекций для хранения целого числа, я бы сделал следующее:
LinkedList <Integer>linky = new LinkedList<Integer>();
int num1 = 2, num2 = 22, num3 = 25, num4 = 1337;
linky.add(num1);
Как бы я мог добавить num2, num3 и num4 в один и тот же первый индекс в списке? Спасибо, ребята.
Ответ №1:
Похоже, существует небольшая путаница в том, как работают связанные списки. По сути, связанный список состоит из узлов, каждый из которых содержит один элемент данных (объект, который сам по себе может содержать несколько переменных-членов, если быть точным), и ссылку на следующий узел в списке (или нулевой указатель, если такого следующего узла нет). Вы также можете иметь двусвязный список, где каждый узел также содержит указатель на предыдущий узел в списке, чтобы ускорить определенные типы шаблонов доступа.
Добавление нескольких «фрагментов данных» в один узел похоже на добавление нескольких ссылок с одного узла, что превращает ваш связанный список в N-арное дерево.
Чтобы добавить несколько фрагментов данных в конец списка способом, наиболее часто ассоциируемым со связанным списком, просто сделайте:
LinkedList <Integer>linky = new LinkedList<Integer>();
int num1 = 2, num2 = 22, num3 = 25, num4 = 1337;
linky.add(num1);
linky.add(num2);
linky.add(num3);
linky.add(num4);
Альтернативно, если вы хотите, чтобы каждый узел связанного списка содержал несколько фрагментов данных
Эти данные должны быть упакованы в объект (путем определения a class
, в котором все они являются переменными-членами). Например:
class GroupOfFourInts
{
int myInt1;
int myInt2;
int myInt3;
int myInt4;
public GroupOfFourInts(int a, int b, int c, int d)
{
myInt1 = a; myInt2 = b; myInt3 = c; myInt4 = d;
}
}
class someOtherClass
{
public static void main(String[] args)
{
LinkedList<GroupOfFourInts> linky = new LinkedList<GroupOfFourInts>();
GroupOfFourInts group1 = new GroupOfFourInts(1,2,3,4);
GroupOfFourInts group2 = new GroupOfFourInts(1337,7331,2345,6789);
linky.add(group1);
linky.add(group2);
}
}
Теперь у linky
вас будет 2 узла, каждый из которых будет содержать 4 int
s, myInt1, myInt2, myInt3 и myInt4.
Примечание
Ничто из вышеперечисленного не относится конкретно к связанным спискам. Этот шаблон следует использовать всякий раз, когда вы хотите хранить кучу данных вместе как единое целое. Вы создаете класс, содержащий переменные-члены для каждого фрагмента данных, которые вы хотите хранить вместе, затем создаете любой тип коллекций Java (ArrayList, LinkedList, TreeList,…) этого типа.
Убедитесь, что вы хотите использовать связанный список (так как при выборе списка ArrayList или списка деревьев нет никаких штрафных санкций с точки зрения сложности программирования). Это будет зависеть от вашего шаблона доступа к данным. Связанные списки обеспечивают O(1) добавление и удаление, но O(n) поиск, тогда как списки массивов обеспечивают O(1) поиск, но O(n) произвольное добавление и удаление. Списки деревьев обеспечивают вставку, удаление и поиск O(log n). Компромиссы между ними зависят от объема имеющихся у вас данных и того, как вы собираетесь изменять структуру данных и получать к ней доступ.
Конечно, все это не имеет значения, если у вас будет только, скажем,
Надеюсь, это поможет!
Комментарии:
1. о, хорошо, значит, вы говорите, что я могу создать объект, содержащий все нужные мне целые числа, а затем сохранить этот единственный объект в узле. Я думаю, что Нельсон тоже это говорил.
2. ха-ха, вы обновили его правильно, как я и комментировал. Большое вам спасибо за вашу помощь! Очень четкий ответ.
3. Я не планирую включать в список более 25 элементов. Я пытаюсь воплотить это в настольную игру в крестики-нолики 5х5, чтобы иметь возможность отменять ходы. 25-это максимальное количество ходов за игру, так что это не должно быть проблемой. Спасибо за информацию о большом O, мы как раз обсуждали это сегодня в классе 🙂
4. Хороший пост; гораздо понятнее, чем мой 🙂 но я бы предостерег вас: не думайте, что из-за того, что у вас мало элементов в вашей коллекции, не имеет значения, какую реализацию вы используете. O(n) поиск приведет к большому штрафу, если вы решите использовать его, скажем, в игровом цикле, когда возможен произвольный доступ 🙂
5. Согласен, все имеет значение, когда вы находитесь в замкнутом цикле, но если это не на критическом пути вашей программы, и разница между O(1) и O(n) составляет Как только ваш профилировщик скажет вам обратное, тогда пришло время сделать мудрый выбор 🙂
Ответ №2:
Используйте структуру.
Например:
private struct Node
{
int Num1;
int Num2;
int Num3;
}
…
LinkedList<Node> list = new LnkedList<Node>();
Node n = new Node();
n.Num1 = 10;
n.Num2 = 100;
n.Num3 = 1000;
list.Add(n);
Примечание; Я предполагаю, что это на C#; поправьте меня, если я ошибаюсь, и я исправлю код 😉
Если вы еще не изучали ООП в своей книге — тогда я бы рекомендовал попробовать; это поможет вам решить подобные проблемы.
Комментарии:
1. Вы можете использовать класс вместо структуры ~ так что это не проблема!
2. Так себе… Один из немногих распространенных языков, к которым я никогда не прикасался… Хотя, в конце концов, я должен это сделать.
3. Вы не найдете слишком много различий, я никогда в жизни не писал ни строчки на C#, но я прекрасно могу ее прочитать 😉
4. Как обойти узлы в этом случае. не могли бы вы, пожалуйста, сказать мне … я реализую что-то подобное этому.
Ответ №3:
Почему бы не сделать что-нибудь в этом роде:
LinkedList<LinkedList<Integer>> linky = new LinkedList<LinkedList<Integer>>();
//...
linky.add(new LinkedList<Integer>().add( //...
Ответ №4:
Как сказал Нельсон, вам нужен другой объект, в Java, хотя вам нужно использовать класс. Если вам нужно, чтобы класс «Узел» использовался вне класса, в котором вы работаете, вам нужно сделать его общедоступным классом и переместить его в собственный файл.
private Class Node
{
//You might want to make these private, and make setters and getters
public int Num1;
public int Num2;
puclic int Num3;
}
LinkedList<Node> list = new LinkedList<Node>();
Node n = new Node();
n.Num1 = 10;
n.Num2 = 100;
n.Num3 = 1000;
list.Add(n);
Приносим извинения Нельсону за кражу его кода 😉
Комментарии:
1. Как обойти узлы в этом случае. не могли бы вы, пожалуйста, сказать мне … я реализую что-то подобное этому.
Ответ №5:
Вот полный пример кода, который показывает использование добавления структуры в связанный список:
import java.util.LinkedList;
class Node {
int num1;
int num2;
int num3;
int num4;
public Node(int a, int b, int c, int d) {
num1 = a; num2 = b; num3 = c; num4 = d;
}
}
public class dummy {
public static void main(String[] args) {
LinkedList <Node>linky = new LinkedList<Node>();
x myNode = new Node(2, 22, 25, 1337);
linky.add(myNode);
}
}
Ответ №6:
Я действительно не понимаю, чего вы пытаетесь достичь, поэтому я предлагаю решение для другого прочтения проблемы (на java).
LinkedList <Integer>linky = new LinkedList<Integer>();
linky.add(num1);
// Lots of code possibly adding elements somewhere else in the list
if (linky.size() > 0) { // Always good to be sure; especially if this is in another methode
int first = linky.get(0);
linky.set(0, first num2);// Value of linky.get(0) is num1 num2
}
// The same again
// Lots of code possibly adding elements somewhere else in the list
if (linky.size() > 0) { // Always good to be sure; especially if this is in another methode
int first = linky.get(0);
linky.set(0, first num3); // Value of linky.get(0) is num1 num2 num3
}
Мне лично больше всего нравится решение Нельсона, если количество добавляемых чисел постоянно (num1 .. num4),
а если оно не является постоянным, я бы предпочел решение Грегора (который использует список вместо узла). Если вы выберете метод узла в java, я предлагаю:
// added static, Class to class
private static class Node
{
//You might want to make these private, and make setters and getters
public int Num1;
public int Num2;
puclic int Num3;
}
// Prefer interfaces if possible
List<Node> list = new LinkedList<Node>();
Node n = new Node();
n.Num1 = 10;
n.Num2 = 100;
n.Num3 = 1000;
list.add(n); // Add -> add
Много придирок, но я думаю, что статический класс вместо нестатического частного класса предпочтительнее, если это возможно (и обычно это должно быть возможно).