Last active
April 5, 2023 13:20
-
-
Save amantix/2a1a00282199d2de3a8d3ac6164e3c52 to your computer and use it in GitHub Desktop.
Реализация абстрактного типа данных список на основе динамического (расширяющегося) массива. Является упрощенным аналогом System.Collections.Generic.List<T>
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections; | |
using System.Collections.Generic; | |
using System.Linq; | |
namespace Vector | |
{ | |
/// <summary> | |
/// Представляет строго типизированный список объектов, доступных по индексу. | |
/// </summary> | |
/// <typeparam name="T"></typeparam> | |
public class Vector<T>: IList<T> | |
{ | |
/// <summary> | |
/// Итератор списка элементов типа T, представленных объектом Vector | |
/// </summary> | |
private class VectorEnumerator : IEnumerator<T> | |
{ | |
/// <summary> | |
/// Текущий индекс итератора в массиве элементов | |
/// </summary> | |
private int _idx; | |
/// <summary> | |
/// Итерируемый массив элементов | |
/// </summary> | |
private T[] _array; | |
public void Dispose() | |
{ | |
} | |
public VectorEnumerator(T[] array) | |
{ | |
_idx = -1; | |
_array = array; | |
} | |
public VectorEnumerator(Vector<T> v) | |
{ | |
_idx = -1; | |
_array = v._array; | |
} | |
/// <summary> | |
/// Продвижение итератора вперёд. | |
/// </summary> | |
/// <returns></returns> | |
public bool MoveNext() | |
{ | |
return ++_idx < _array.Length; | |
} | |
/// <summary> | |
/// Сброс итератора и возврат в позицию перед первым элементом. | |
/// </summary> | |
public void Reset() | |
{ | |
_idx = -1; | |
} | |
/// <summary> | |
/// Получение текущего элемента. | |
/// </summary> | |
public T Current | |
{ | |
get | |
{ | |
try | |
{ | |
return _array[_idx]; | |
} | |
catch (IndexOutOfRangeException) | |
{ | |
throw new InvalidOperationException(); | |
} | |
} | |
} | |
/// <summary> | |
/// Неуниверсальное свойство получения текущего элемента. | |
/// </summary> | |
object IEnumerator.Current => Current; | |
} | |
/// <summary> | |
/// Массив - хранилище элементов списка | |
/// </summary> | |
private T[] _array; | |
/// <summary> | |
/// Конструктор списка Vector по умолчанию, создающий пустой список. | |
/// </summary> | |
public Vector() | |
{ | |
_array = Array.Empty<T>(); | |
Capacity = 0; | |
Count = 0; | |
} | |
/// <summary> | |
/// Конструктор списка Vector с указанным значением ёмкости. | |
/// </summary> | |
/// <param name="capacity"></param> | |
public Vector(int capacity) | |
{ | |
_array = new T[Capacity = capacity]; | |
} | |
/// <summary> | |
/// Конструктор списка Vector по указанной коллекции. | |
/// </summary> | |
/// <param name="collection"></param> | |
public Vector(IEnumerable<T> collection) | |
{ | |
var enumerable = collection as T[] ?? collection.ToArray(); | |
Capacity = Count = enumerable.Length; | |
for(var i=0; i<Count; ++i) | |
_array[i] = enumerable[i]; | |
} | |
/// <summary> | |
/// Метод получения строго типизированного итератора Vector | |
/// </summary> | |
/// <returns></returns> | |
public IEnumerator<T> GetEnumerator() | |
{ | |
return new VectorEnumerator(_array); | |
} | |
/// <summary> | |
/// Метод получения итератора неуниверсальной коллекции для Vector | |
/// </summary> | |
/// <returns></returns> | |
IEnumerator IEnumerable.GetEnumerator() | |
{ | |
return GetEnumerator(); | |
} | |
/// <summary> | |
/// Внутренний метод расширения массива элементов. | |
/// Если массив пустой - расширяем до 4. | |
/// В противном случае увеличиваем ёмкость вдвое. | |
/// </summary> | |
private void Extend() | |
{ | |
if (Capacity == 0) | |
_array = new T[Capacity = 4]; | |
else | |
{ | |
Capacity *= 2; | |
var tmp = new T[Capacity]; | |
Array.Copy(_array, tmp, _array.Length); | |
_array = tmp; | |
} | |
} | |
/// <summary> | |
/// Метод добавления элемента в список Vector. | |
/// </summary> | |
/// <param name="item"></param> | |
public void Add(T item) | |
{ | |
if (Count == Capacity) | |
Extend(); | |
_array[Count++] = item; | |
} | |
/// <summary> | |
/// Метод очищения списка Vector | |
/// </summary> | |
public void Clear() | |
{ | |
Count = 0; | |
} | |
/// <summary> | |
/// Метод проверки наличия указанного элемента в списке Vector | |
/// </summary> | |
/// <param name="item"></param> | |
/// <returns></returns> | |
public bool Contains(T item) | |
{ | |
for (var i = 0; i < Count; ++i) | |
if (_array[i].Equals(item)) | |
return true; | |
return false; | |
} | |
/// <summary> | |
/// Метод копирования содержимого списка Vector в массив, | |
/// начиная с заданного индекса | |
/// </summary> | |
/// <param name="array"></param> | |
/// <param name="arrayIndex"></param> | |
public void CopyTo(T[] array, int arrayIndex) | |
{ | |
_array.CopyTo(array, arrayIndex); | |
} | |
/// <summary> | |
/// Метод удаления указанного элемента из списка Vector | |
/// </summary> | |
/// <param name="item"></param> | |
/// <returns></returns> | |
public bool Remove(T item) | |
{ | |
int found = IndexOf(item); | |
if (found < 0) | |
return false; | |
RemoveAt(found); | |
return true; | |
} | |
/// <summary> | |
/// Метод сокращения ёмкости списка Vector до фактического количества элементов. | |
/// </summary> | |
public void TrimExcess() | |
{ | |
if (Count >= Capacity) return; | |
var tmp = new T[Count]; | |
if(Count>0) | |
_array.CopyTo(tmp, 0); | |
_array = tmp; | |
Capacity = 0; | |
} | |
/// <summary> | |
/// Свойство получения ёмкости списка Vector | |
/// </summary> | |
public int Capacity { get; private set; } | |
/// <summary> | |
/// Свойство получения фактического количества элементов в списке Vector | |
/// </summary> | |
public int Count { get; private set; } | |
/// <summary> | |
/// | |
/// </summary> | |
public bool IsReadOnly => false; | |
/// <summary> | |
/// Получение индекса элемента в списке Vector | |
/// </summary> | |
/// <param name="item"></param> | |
/// <returns></returns> | |
public int IndexOf(T item) | |
{ | |
int i = 0; | |
int found = -1; | |
while (i < _array.Length) | |
{ | |
if (_array[i].Equals(item)) | |
{ | |
found = i; | |
break; | |
} | |
++i; | |
} | |
return found; | |
} | |
/// <summary> | |
/// Вставка элемента в список Vector по заданному индексу. | |
/// </summary> | |
/// <param name="index"></param> | |
/// <param name="item"></param> | |
public void Insert(int index, T item) | |
{ | |
if (index < 0 || index > Count) | |
throw new ArgumentOutOfRangeException(nameof(index)); | |
if (Count == Capacity) | |
Extend(); | |
for (int i = Count; i < index; --i) | |
_array[i] = _array[i - 1]; | |
_array[index] = item; | |
++Count; | |
} | |
/// <summary> | |
/// Удаление элемента из списка Vector, находящегося по заданному индексу. | |
/// </summary> | |
/// <param name="index"></param> | |
public void RemoveAt(int index) | |
{ | |
if (index < 0 || index >= Count) | |
throw new ArgumentOutOfRangeException(nameof(index)); | |
for (int i = index; i < Count - 1; i++) | |
_array[i] = _array[i + 1]; | |
--Count; | |
} | |
/// <summary> | |
/// Доступ к элементу списка Vector по индексу. | |
/// </summary> | |
/// <param name="index"></param> | |
/// <returns></returns> | |
public T this[int index] | |
{ | |
get | |
{ | |
if (index < 0 || index >= Count) | |
throw new ArgumentOutOfRangeException(nameof(index)); | |
return _array[index]; | |
} | |
set | |
{ | |
if (index < 0 || index >= Count) | |
throw new ArgumentOutOfRangeException(nameof(index)); | |
_array[index] = value; | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment