Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Основная книга по С++й.doc
Скачиваний:
16
Добавлен:
28.10.2018
Размер:
2.07 Mб
Скачать

Int bmtarr[255];

} *bmt;

Далее приводится процедура, вычисляющая таблицу смещений для образца p.

BMTable MakeBMTable(char *p)

{

int i;

for (i = 0; i <= 255; i++) bmt->bmtarr[i] = strlen(p);

for (i = strlen(p); i <= 1; i--)

{

if (bmt->bmtarr[p[i]] == strlen(p))

{

bmt->bmtarr[p[i]] = strlen(p)-i;

}

}

return(*bmt);

}

Теперь напишем функцию, осуществляющую поиск.

Int bmSearch(int startpos, char *s, char *p)

{

int pos, lp, i;

lp = strlen(p);

pos = startpos + lp - 1;

while (pos < strlen(s))

{

if (p[lp] != s[pos]) pos = pos + bmt->bmtarr[s[pos]];

else

{

for (i = lp - 1; i <= 1; i--)

{

if (p[i] != s[pos - lp + i])

{

pos++;

break;

}

else

if (i = 1)

{

return(pos - lp + 1);

exit;

}

}

}

}

return(0);

}

Функция BMSearch возвращает позицию первого символа первого вхождения образца p в строке s. Если последовательность p в s не найдена, функция возвращает 0. Параметр startpos позволяет указать позицию в строке s, с которой следует начинать поиск. Это может быть полезно в том случае, если вы захотите найти все вхождения p в s. Для поиска с самого начала строки следует задать startpos равным 1. Если результат поиска не равен нулю, то для того, чтобы найти следующее вхождение p в s, нужно задать startpos равным значению «предыдущий результат плюс длина образца».

Бинарный (двоичный) поиск

Бинарный поиск используется в том случае, если массив, в котором осуществляется поиск, уже упорядочен.

Переменные lb и ub содержат, соответственно, левую и правую границы отрезка массива, где находится нужный элемент. Поиск начинается всегда с исследования среднего элемента отрезка. Если искомое значение меньше среднего элемента, то нужно перейти к поиску в верхней половине отрезка, где все элементы меньше только что проверенного. Другими словами, значением ub становится (m – 1) и на следующей итерации проверяется половина исходного массива. Таким образом, в результате каждой проверки вдвое сужается область поиска. Например, если в массиве 100 чисел, то после первой итерации область поиска уменьшается до 50 чисел, после второй – до 25, после третьей до 13, после четвертой до 7 и т.д. Если длина массива равна n, то для поиска в массиве элементов достаточно около log2n сравнений.

Int BinarySearch (int lb, int ub, int key, int* pArr)

/* a – исходный массив, lb – левая граница поиска, ub – правая граница поиска, key – значение искомого элемента. Функция возвращает индекс совпадающего элемента в массиве, и -1 – если элемент не найден */

{

int m;

return(-1); // функция возвращает -1 , если элемент не найден

do

{

m = (lb + ub)/2; //находим индекс «половинки» массива

if (key < pArr[m]) ub = m-1;

else

if (key > pArr[m]) lb = m+1;

else

{ // найдено совпадение

return(m);

break;

}

}

while (lb > ub);

}

Динамические структуры данных

Динамические структуры данных основаны на использовании указателей и применении стандартных процедур и функций выделения/освобождения памяти в процессе работы программы. Они отличаются от статических структур данных, которые описываются в разделах описания типов и данных. Когда описывается статическая переменная в программе, то при компиляции программы выделяется оперативная память, в зависимости от типа переменной. При этом изменить размер выделенной памяти невозможно.

Например, если указан массив

char S[10];

то под него один раз в начале выполнения программ выделяется 10 байт оперативной памяти.

Динамические структуры характеризуются непостоянством и непредсказуемостью размера (числа элементов) структуры в процессе ее обработки.

Поскольку элементы динамической структуры располагаются по непредсказуемым адресам памяти, адрес элемента такой структуры не может быть вычислен из адреса начального или предыдущего элемента. Для установления связи между элементами динамической структуры используются указатели, через которые устанавливаются явные связи между элементами. Такое представление данных в памяти называется связным. Элемент динамической структуры состоит из двух полей:

1) информационного поля или поля данных, в котором содержатся те данные, ради которых и создается структура; в общем случае информационное поле само является интегрированной структурой – записью, вектором, массивом, другой динамической структурой и т.п.;

2) поля связок, в которых содержатся один или несколько указателей, связывающих данный элемент с другими элементами структуры.

Когда связное представление данных используется для решения прикладной задачи, для конечного пользователя "видимым" делается только содержимое информационного поля, а поле связок используется только программистом-разработчиком.

Достоинства связного представления данных:

  • в возможности обеспечения значительной изменчивости структур;

  • размер структуры ограничивается только доступным объемом машинной памяти;

  • при изменении логической последовательности элементов структуры требуется не перемещение данных в памяти, а только коррекция указателей;

  • большая гибкость структуры.

Вместе с тем связное представление не лишено и недостатков, основные из которых:

  • на поля связок расходуется дополнительная память;

  • доступ к элементам связной структуры может быть менее эффективным по времени.

Последний недостаток является наиболее серьезным и именно им ограничивается применимость связного представления данных. Если в смежном представлении данных (массивы) для вычисления адреса любого элемента нам во всех случаях достаточно было номера элемента и информации, содержащейся в дескрипторе структуры, то для связного представления адрес элемента не может быть вычислен из исходных данных. Дескриптор связной структуры содержит один или несколько указателей, позволяющих войти в структуру, далее поиск требуемого элемента выполняется следованием по цепочке указателей от элемента к элементу. Поэтому связное представление практически никогда не применяется в задачах, где логическая структура данных имеет вид вектора или массива - с доступом по номеру элемента, но часто применяется в задачах, где логическая структура требует другой исходной информации доступа (таблицы, списки, деревья и т.д.).

К динамическим структурам, используемым в программировании, относятся:

  • динамические массивы (были рассмотрены в теме 6);

  • линейные списки;

  • стек;

  • очередь, дек;

  • деревья.