ArrayList.

advertisement
1
СТРУКТУРЫ ДАННЫХ C#.
В C#.NET есть много различных структур данных, например Array - одна из самых
часто используемых. Однако C# поставляется с гораздо большим количеством таких
структур. Необходимо выбирать правильные структуры данных для написания хорошо
структурированных и эффективных программ.
В этой статье я перечислю встроенные в C# структуры данных, включая новые из
C#.Net 3.5.
1.1 Array.
Возможно самым простой и известной структурой данных является array. В C#
array является простым массивом объектов. Для него характерно то, что все его объекты
одного типа и их количество фиксировано. Он объявляется и инициализируется
следующим образом:
1
[object type][] myArray = new [object type][number of elements]
Некоторые примеры:
1
2
int[] myIntArray = new int[5];
int[] myIntArray2 = { 0, 1, 2, 3, 4 };
Как
можно
видеть
из
приведенного
выше
примера,
массив
может
инициализироваться пустым или с уже заданными элементами.
1.2 ArrayList.
ArrayList - это динамический массив. Он может иметь любое количество объектов
любого типа.
Ниже приведён пример, где ArrayList - массив произвольных объектов,
расширяющийся по мере добавления в него новых элементов.
1
2
3
4
ArrayList myArrayList = new ArrayList();
myArrayList.Add(56);
myArrayList.Add("String");
myArrayList.Add(new Form());
Недостатком ArrayList является необходимость распаковки его элементов в их
оригинальный тип:
1
int arrayListValue = (int)myArrayList[0];
1.3 List<> (список).
Вкратце, структура данных List<> - это строго типизированный ArrayList. Это тоже
динамический массив, но его отличие от ArrayList в том, что List<> должен содержать
данные только одного типа:
1
2
3
4
List<int> intList = new List<int>();
intList.Add(45);
intList.Add(34);
</int></int>
Поскольку элементы List<> относятся к одному типу их нет необходимости
распаковывать при получении:
1
int listValue = intList[0];
Для простых типов данных (int, bool, итд.) использование List<> обеспечивает
гораздо большую скорость работы, нежели использование ArrayList.
1.4 LinkedList<> (двусвязный список).
Теперь совершенно другой тип структуры данных - LinkedList<>. LinkedList<> - это
группа объектов, которые вместо того, чтобы индексироваться по ссылке (как,
например, Array), расположены в узлах и соединены друг с другом.
LinkedList<> узел содержит три основных значения: сам объект, ссылку на
следующий узел, а также ссылки на предыдущий узел.
Какой смысл в такой структуре данных? Её преимущество в том, что добавление
элемента в середину списка происходит значительно быстрее, чем в другом типе
структуры данных. LinkedList<> также снижает затраты памяти до минимума. С другой
стороны, для нахождения элемента, находящегося в середине или в конце списка,
требуется довольно много времени.
1
2
3
LinkedList<int> list = newLinkedList<int>();
list.AddLast(6);
</int></int>
Получение значения производится не напрямую, а перебором:
1
list.First.Value
1
list.Last.Value
или
Теперь мы можем перейти к более сложным структурам данных.
1.5 Dictionary<> (словарь).
Структура данных Dictionary<> очень удобна, она позволяет программисту
обращаться к значению по её ключевому индексу. Что это значит? ArrayList, к примеру,
автоматически создаёт свои "ключи" - числа, 1, 2 и т.д., так, что для доступа к
необходимому объекту используется следующая запись:
1
myArrayList[2];
Dictionary<> позволяет использовать ключи любого типа, например:
1
2
3
4
Dictionary<string, int=""> myDictionary = new
Dictionary<string, int="">();
myDictionary.Add("one", 1);
myDictionary.Add("twenty", 20);
</string,></string,>
Получение значения производится следующим образом:
1
int myInt = myDictionary["one"];
При использовании Dictionary<> нет необходимости метаться между типами.
Также никто не запрещает создать Dictionary<> таким образом:
1
2
Dictionary<int, int="" dictionary<string,="">>
nestedDictionary =
new Dictionary<int, int="" dictionary<string,="">>();
3
</int,></int,>
То есть вложенные структуры данных Dictionary<> возможны и разрешены.
Я понимаю, что может ввести в заблуждение то, как получить все значения из этой
структуры данных, поскольку мы можем не знать закономерности в составлении её
ключей. К счастью, это не обязательно, вот пример получения всех данных из
Dictionary<>:
1
2
3
4
5
6
7
//List<[same type as index]>
List<string>
keyList
=
new
List<string>
(myDictionary.Keys);
for (int i = 0; i < keyList.Count; i++)
{
int myInt = myDictionary[keyList[i]];
}
</string></string>
Если вы заинтересованы, вы можете прочитать более подробно о C# Dictionary<>.
1.6 Hashtable (хеш-таблица).
Структура данных Hashtable очень похожа на структуру Dictionary<>. Hashtable
также принимает пару ключ/значение, но они должны быть объектными ссылками ссылкой на ключ и ссылкой на сам объект. С приходом .NET 2.0 обобщённые словари
вроде Dictionary<> стали более предпочтительнее, по сравнению со словарями,
основанными на типе Object.
Значения в хеш-таблице хранится в порядке, зависящем от хэш-кода их ключа.
1
Hashtable myTable = new Hashtable();
1.7 HashSet<>.
Структура данных HashSet<> была введена в C# Net 3.5. Эта специфическая
структура данных очень сильно напоминает List<>. В чём же различие? У HashSet<>
есть очень важная особенность - она не допускает повторяющихся значений. Например:
1
2
3
4
5
6
7
8
9
HashSet<int> mySet = new HashSet<int>();
mySet.Add(3);
mySet.Add(5);
mySet.Add(3);
mySet.Add(10);
List<int> myListFromSet = mySet.ToList<int>();
int myInt = myListFromSet[2];
</int></int></int></int>
Если mySet был бы обычной структурой данных List<>, то индекс 2 должен был
вернуть значение 3 (проверьте сами). Но если вы запустите пример, вы увидите, что
myInt возвращает значение 10. Это происходит потому, что HashSet<> игнорирует
дубликат со значением 3.
Для более подробного изучения вы можете посетить страницу C# HashSet<>.
1.8 Stack и Stack<>(стек).
Класс Stack является одним из многих структур данных в C#, которые напоминают
ArrayList. Как и ArrayList, стек имеет методы для добавления и получения данных, но с
небольшой разницей в их поведении.
Чтобы добавить в стек данные, необходимо использовать метод Push, который
является эквивалентом Add в ArrayList. Получение значения немного отличается. Стек
имеет метод Pop, который возвращает и одновременно удаляет последний добавленный
объект. Если вы хотите получить последнее значение в стеке без его удаления,
используйте метод Peek.
Стек работает по алгоритму LIFO, что расшифровывается как Last-In-First-Out
(последним пришёл - первым обслужен). Эта специфическая структура данных будет
полезна, если вам необходимо вернуться той же дорогой, так сказать.
Есть два вида объявления стека в C#:
1
2
3
Stack stack = new Stack();
Stack<string> stack = new Stack<string>();
</string></string>
Различия в них в том, что первая структура данных будет работать с производными
от класса Object, тогда как вторая принимает только определённый тип данных.
Вот код C#, для добавления и извлечения данных из стека:
01
02
03
04
05
06
07
08
09
10
Stack<string> stack = new Stack<string>();
stack.Push("1");
stack.Push("2");
stack.Push("3");
while (stack.Count > 0)
{
MessageBox.Show(stack.Pop());
}
</string></string>
Если запустить этот код, то увидите, что список возвращён в следующем порядке:
3, 2, 1.
1.9 Queue и Queue<>(очередь).
Очередь - ещё одна из многих структур данных в C#. Очередь очень похожа на
стек, но есть одно важное отличие. Вместо того, чтобы следовать алгоритму LIFO,
очередь следует алгоритму FIFO, что расшифровывается как First-In-First-Out (первый
пришёл - первый обслужен). К примеру, когда вы отправляете статью для утверждения
на сайт, то там она добавляется в очередь на утверждение. Таким образом, объекты,
добавленные первыми, первыми будут и обработаны.
Добавление элемента в очередь (аналогичено Push для стека) осуществляется
методом Enqueue:
1
queue.Enqueue("1");
Извлечение элемента - методом Dequeue:
1
queue.Dequeue();
Аналогично, метод Peek позволяет просмотреть верхнее значение в очереди, не
удаляя его. Эта специфическая структура данных очень часто используется в связке со
стеком.
Вот простой код для добавления и извлечения данных из очереди:
01
02
03
04
05
06
07
08
09
10
Queue<string> queue = new Queue<string>();
queue.Enqueue("1");
queue.Enqueue("2");
queue.Enqueue("3");
while (queue.Count > 0)
{
MessageBox.Show(queue.Dequeue());
}
</string></string>
Также имейте ввиду, что очередь, как и стек, может быть определена как любого
типа данных (Queue), так и только для одного типа (Queue<>).
Download