Векторы, списки, последовательности

Содержание

Слайд 2

АТД «Вектор» 1 Пусть S — линейная последовательность из n элементов.

АТД «Вектор» 1

Пусть S — линейная последовательность из n элементов. Разряд

элемента е последовательности S равен количеству элементов, находящихся в S перед е, то есть разряд первого элемента последовательности равен 0, а последнего — n-1. Очевидно, что разряд каждого элемента в S уникален.
Абстракция «Вектор» заключается в том, что последовательность S не обязана быть массивом.
Кроме того, «Вектор» – более динамическая структура, поскольку разряд элемента в S может меняться вследствие удаления и добавления новых элементов.
Слайд 3

АТД «Вектор» 2 Основные методы: ElemAtRank(r): возвращает элемент S с разрядом

АТД «Вектор» 2

Основные методы:
ElemAtRank(r): возвращает элемент S с разрядом r; если

r<0 или r>п-1, где п — текущее число элементов, выдается сообщение об ошибке. Input: целое число; Output: объект.
ReplaceAtRank(r,e): замещает объектом е элемент с разрядом r и возвращает замещаемый объект. Если r<0 или r>п-1, где п — текущее число элементов, выдается сообщение об ошибке. Input: целое число r и объект е; Output: объект.
InsertAtRank(r,e): добавляет в S новый элемент е; если r<0 или r>п, где п — текущее число элементов, выдается сообщение об ошибке. Input: целое число r и объект е; Output: нет.
RemoveAtRank(r): удаляет из S элемент с разрядом r; если r<0 или r>п-1, где п — текущее число элементов, выдается сообщение об ошибке. Input: целое число; Output: объект.
стандартные методы Size() и IsEmpty()
Слайд 4

Адаптация вектора для реализации дека

Адаптация вектора для реализации дека

Слайд 5

Реализация вектора с помощью массива Недостатки: 1.InsertAtRank и RemoveAtRank выполняются за

Реализация вектора с помощью массива

Недостатки:
1.InsertAtRank и RemoveAtRank выполняются за O(N)

времени
2.Емкость вектора ограничена фиксированным размером массива
Слайд 6

Реализация вектора на основе расширяемого массива (Имитация изменения размера массива)

Реализация вектора на основе расширяемого массива (Имитация изменения размера массива)

Слайд 7

Реализация вектора на основе расширяемого массива public class ArrayVector : Vector

Реализация вектора на основе расширяемого массива

public class ArrayVector : Vector
{ private

Object[ ] a;
private int capacity =16; /* емкость вектора*/ private int size = 0; /* текущий размер*/
public ArrayVector() { a = new Object[capacity]; } //время O(1)
public Object ElemAtRank(int r) { return a[r]; } //время O(1)
public int Size() { return size; }
public bool IsEmpty() { return (size == 0); }
public Object ReplaceAtRank(int r, Object e) { Object temp = a[r]; return temp; } //время O(1)
public Object RemoveAtRank(int r) // время O(N)
{ Object temp = a[r];
for (int i=r; i size--; return temp;
}
public void InsertAtRank(int r, Object e) // время O(N)
{ if (size == capacity) // переполнение
{ capacity *= 2; Object[ ] b = new Object[capacity];
for (int i=0; i a = b;
}
for (int i=size-1; i>=r; i--) a[i+1] = a[i];
a[r] = e; size++;
}
}
Слайд 8

АТД «Список» 1 В списке узлы «знают» друг о друге. Поэтому

АТД «Список» 1

В списке узлы «знают» друг о друге. Поэтому операции

с параметрами-узлами быстрее, чем операции с индексами в массиве.
Например: RemoveAtNode(v), InsertAfterNode(v,e)
Абстракция узла – АТД «Позиция»
GetElement(): возвращает элемент, хранящийся в данной позиции. Input: нет; Output: объект.
SetElement(Object e): помещает элемент в позицию. Input: элемент; Output: нет
Слайд 9

АТД «Список» - операции доступа по чтению First(): возвращает позицию первого

АТД «Список» - операции доступа по чтению

First(): возвращает позицию первого элемента

списка S; если список пуст, выдается сообщение об ошибке. Input: нет; Output: позиция.
Last(): возвращает позицию последнего элемента списка S; если список пуст, выдается сообщение об ошибке. Input: нет; Output: позиция.
IsFirst(р): возвращает логическое значение, показывающее, является ли данная позиция первой в списке. Input: позиция р; Output: логическое значение.
IsLast(p): возвращает логическое значение, показывающее, является ли данная позиция последней в списке. Input: позиция р; Output: логическое значение.
Before(p): возвращает позицию элемента S, который предшествует элементу позиции р; если р является первой позицией, выдается сообщение об ошибке. Input: позиция; Output: позиция.
After(р): возвращает позицию элемента S, который следует за элементом позиции р; если р является последней позицией, выдается сообщение об ошибке. Input: позиция; Output: позиция.
Слайд 10

АТД «Список» - модифицирующие операции ReplaceElement(p,e): замещает элемент в позиции р

АТД «Список» - модифицирующие операции

ReplaceElement(p,e): замещает элемент в позиции р на

е и возвращает элемент, который до этого был в позиции р. Input: позиция р и объект е; Output: объект.
SwapElements(p,q): меняет местами элементы в позициях р и q таким образом, что элемент в позиции р перемещается в позицию q, а элемент, бывший в позиции q, перемещается в позицию р. Input: две позиции; Output: нет.
InsertFirst(e): вставляет новый элемент е в S в качестве первого элемента списка. Input: объект е; Output: позиция вставленного элемента е.
InsertLast(e): вставляет новый элемент е в S в качестве последнего элемента списка. Input: объект е; Output: позиция вставленного элемента е.
InsertBefore(p, е): вставляет новый элемент е в S перед позицией р; если р является первой позицией, выдается сообщение об ошибке. Input: позиция р и объект е; Output: позиция вставленного элемента е.
InsertAfter(p, e): вставляет новый элемент е в S после позиции р; если р является последней позицией, выдается сообщение об ошибке. Input: позиция р и объект е; Output: позиция вставленного элемента е.
Remove(p): удаляет из S элемент в позиции р Input: позиция; Output: удаленный элемент.
Слайд 11

Пример использования списка

Пример использования списка

Слайд 12

Реализация АТД «Список» с помощью двусвязного списка – класс DNode class

Реализация АТД «Список» с помощью двусвязного списка – класс DNode

class DNode

: Position
{ private DNode prev, next;
private Object element; // элемент, хранящийся в данной позиции
public DNode(DNode newPrev, DNode newNext, Object elem)
{ prev = newPrev; next = newNext; element = elem; }
public Object GetElement()
{ if ((prev == null) && (next == null))
throw new InvalidPositionException("Positionisnotinalist!");
return element;
}
public void SetElement(Object newElement) {element = newElement;}
public DNode GetNext() { return next; }
public DNode GetPrev() { return prev; }
public void SetNext(DNode newNext) { next = newNext; }
public void SetPrev(DNode newPrev) { prev = newPrev; }
}
Слайд 13

Реализация АТД «Список» с помощью двусвязного списка – операция InsertAfter Алгоритм

Реализация АТД «Список» с помощью двусвязного списка – операция InsertAfter

Алгоритм InsertAfter(p,

e):
Создать новый узел v
v.SetElement(e)
// связать v с предшествующим узлом
v.SetPrev(p)
// связать v с последующим узлом
v.SetNext(p.getNext())
// связывает ранее следовавший за р узел с v
(p.GetNext()).SetPrev(v)
// связывает р с новым последующим узпом v
p.SetNext(v)
return v { позиция элемента e }
Слайд 14

Реализация АТД «Список» с помощью двусвязного списка – вспомогательный метод checkPosition

Реализация АТД «Список» с помощью двусвязного списка – вспомогательный метод checkPosition

protected DNode checkPosition(Position p)
{ if (p == null)
throw new InvalidPositionException("Null Position passed to NodeList.");
if (p == header)
throw new InvalidPositionException("Header is not a valid position");
if (p == trailer)
throw new InvalidPositionException("Trailer is not a valid position");
try
{ DNode temp = (DNode)p;
if ((temp.GetPrev() == null) || (temp.GetNext() == null))
throw new InvalidPositionException("Position does not belong to a valid NodeList");
return temp;
}
catch (Exception e)
{ throw new InvalidPositionException("Position is of wrong type for this container.");
}
}
Слайд 15

АТД «Последовательность» все методы векторов все методы списков два дополнительных «связующих»

АТД «Последовательность»

все методы векторов
все методы списков
два дополнительных «связующих» метода,

которые обеспечивают переход между разрядами и позициями:
AtRank(r): возвращает позицию элемента с разрядом r. Input: целое число; Output: позиция.
RankOf(p): возвращает разряд элемента в позиции р. Input: позиция; Output: целое число.
Слайд 16

АТД «Последовательность» – множественное наследование public interface Sequence : List, Vector

АТД «Последовательность» – множественное наследование

public interface Sequence : List, Vector
{ //

Дополнительные "переходные" методы.
Position AtRank(int rank);
int RankOf(Position position);
}
Слайд 17

Реализация последовательности с помощью двусвязного списка все методы АТД «список» выполняются

Реализация последовательности с помощью двусвязного списка

все методы АТД «список» выполняются за

O(1) время.
Методы же АТД «вектор» реализованы менее эффективно.
ElemAtRank(r) - поиск можно начать с ближайшего конца последовательности, время выполнения составит O(min(r+1, n-r))
- Аналогично - InsertAtRank(r, e) и RemoveAtRank(r)
Слайд 18

Реализация последовательности с помощью двусвязного списка 1 public class NodeSequence :

Реализация последовательности с помощью двусвязного списка 1

public class NodeSequence : NodeList,

Sequence
{ // проверяем, находится ли разряд в интервале [0,numElt-1];
protected void checkRank(int rank) // время O(1).
{ if (rank<0 || rank>=numElts)
{ String s = String.Format("Rank {0} is invalid for this sequence of {1} elements.", rank, numElts);
throw new BoundaryViolationException(s);
}
public Position ElemAtRank (int rank) // время O(1)
{ DNode node;
checkRank(rank);
if (rank <= Size()/2) // просматриваем последовательность от начала
{ node = header.GetNext(); for (int i=0; i < rank; i++) node = node.GetNext();
}
else // просматриваем последовательность с конца
{ node = trailer.GetPrev();
for(int i=1; i }
return node;
}
Слайд 19

Реализация последовательности с помощью двусвязного списка 2 public void InsertAtRank (int

Реализация последовательности с помощью двусвязного списка 2

public void InsertAtRank (int rank,

Object element) // время O(n)
{ if (rank == Size()) // в данном случае не выполняется checkRank
InsertLast(element);
else
{ checkRank(rank);
InsertBefore(AtRank(rank), element);
}
}
public Object RemoveAtRank (int rank) // время O(n)
{ checkRank(rank);
return Remove(AtRank(rank));
}
public Object ReplaceAtRank (int rank,Object element) //время O(n)
{ checkRank(rank);
return ReplaceElement(AtRank(rank),element);
}
}
Слайд 20

Сравнительный анализ различных реализаций последовательности Каждая из реализаций имеет свои преимущества

Сравнительный анализ различных реализаций последовательности

Каждая из реализаций имеет свои преимущества и

недостатки. Выбор того или иного способа обусловлен конкретными требованиями приложения. Поскольку структура АТД «последовательность» не зависит от конкретных условий реализации, применяется наиболее соответствующая реализация с минимальными изменениями в программе.
Слайд 21

Векторы, списки, последовательности – иерархия интерфейсов Задача – оптимизация состава методов

Векторы, списки, последовательности – иерархия интерфейсов

Задача – оптимизация состава методов
Введем обобщающее

понятие «контейнер» («коллекция») и классификацию методов контейнеров:
методы запросов возвращают информацию о контейнере;
методы доступа возвращают элементы или позиции контейнера;
методы обновления изменяют контейнер, добавляя, удаляя элементы или изменяя отношения между элементами.
методы конструктора, создающие экземпляр контейнера.
Слайд 22

Инспектирующие контейнеры В таких контейнерах, после их инициализации с помощью конструктора,

Инспектирующие контейнеры

В таких контейнерах, после их инициализации с помощью конструктора, разрешен

доступ «только для чтения». Таким образом, элементы в них защищены от ошибочных или злонамеренных внешних попыток изменения.
Слайд 23

Структура иерархии последовательностей

Структура иерархии последовательностей