1. Реализация множества как набора номеров элементов универса. Оценка сложности по памяти. Оценка сложности по времени.
Множество – набор элементов
Операции над множествами
- получение значения бита n
- проверка наличия элемента (a принадлежит A)
- при условии, если бит больше -1 и меньше количества битов
- в противном случае возвращается 0
int TBitField::GetBit(const int n) const
{
if ((n > -1) && (n < BitLen))
return (pMem[(GetMemIndex(n))] & (GetMemMask(n)));
else return(0);
}
- установка бита
- добавление элемента (A + a)
- происходит в позицию n том случае, если бит больше -1 и меньше количества битов
void TBitField::SetBit(const int n)
{ if ((n > -1) && (n < BitLen))
pMem[(GetMemIndex(n))] |= GetMemMask(n);
}
- удаление бита в позиции n
- удаление элемента A – a
- при условии, если бит больше -1 и меньше количества битов
void TBitField::ClrBit(const int n)
{ if ((n > -1) && (n < BitLen))
pMem[(GetMemIndex(n))] &= ~GetMemMask(n);
}
Теоретико-множественные операции
- объединение A ⋃ B
- Операция "или" для двух битовых полей, осуществляется с помощью сравнивания двух полей, причем, результирующее будет с длиной наибольшего из них
- Затем последовательно выполняется дизъюнкция для i-ых элементов двух массивов
TBitField TBitField::operator|(const TBitField& bf)
{
int i, len;
if (BitLen > bf.BitLen)
len = BitLen;
else len = bf.BitLen;
TBitField temp(len);
for (i = 0; i < MemLen; i++)
temp.pMem[i] = pMem[i];
for (i = 0; i < bf.MemLen; i++)
temp.pMem[i] |= bf.pMem[i];
return temp;
}
- пересечение A ∩ B
- Операция "и" для двух битовых полей, осуществляется с помощью сравнивания двух полей, результирующее будет с длиной наименьшего из них
- Затем последовательно выполняется конъюнкция для i-ых элементов двух массивов
TBitField TBitField::operator&(const TBitField &bf)
{
int i, len;
if (BitLen < bf.BitLen)
len = BitLen;
else len = bf.BitLen;
TBitField temp(len);
for (i = 0; i < MemLen; i++)
temp.pMem[i] = pMem[i];
for (i = 0; i < bf.MemLen; i++)
temp.pMem[i] &= bf.pMem[i];
return temp;
}
- вычитание A B
- Для отрицания последовательно выполняется инверсия для каждого бита массива
TBitField TBitField::operator~(void)
{
TBitField temp(BitLen);
for (int i = 0; i < MemLen; i++)
temp.pMem[i] = ~pMem[i];
return temp;
}
Универс U – множество всех элементов.
Конкретизация (допущения и ограничения):
Оценка сложности по времени
Битовое поле представляет из себя массив int
Бред, который нужно исправить:
- все операции с конкретным int это константны
- там везде битовые операции они грубо говоря все О(1)
- остаётся только найти этот int
- мы там делили нацело, потом брали ещё остаток как смещение и шагали по массиву, а потом по int в этом массиве
- это всё грубо говоря О(1) - очень быстро.
Оценка сложности по памяти
Бред, который нужно исправить:
- делили на 32 (типо int 4 байта 1 байт 8 битов) значит в int 32 бита
- будет [n/32] + 1
- +1 ,потому что если элементов меньше 32, то деление даст 0
- предположим 5/32 = 0 деление же целочисленное значит для хранения 5 элементов множества нужно 5/32 + 1 = 1
- элемент в массиве это размер чтобы получить индекс мы делали n » 5
- по факту делили на 32 без остатка, только делая это битовым сдвигом
- битовые операции просто быстрее работают
2. Линейный список как динамическая структура. Базисное множество. Неоднозначность операций вставки и удаления.
Структура хранения данного типа (звенья, сцепление, барьер, переменная связи) называется линейным или односвязным списком.
Среда выполнения обеспечивает динамически–распределяемую область памяти:
- звено
- выделение звена PTemp = new TDatLink()
- освобождение звена –delete pTemp
Базисное множество - структуры
Неоднозначность операций в том что можем вставлять как в голову так и в хвост и после текущего и удалять можно тоже по-разному.
Для показа неоднозначности взять простой односвязный линейный список с головой и двусвязный с хвостом и головой.