
- •Глава 1. Разработка эффективных алгоритмов
- •Value значение переменной X, для которого рассчитывается Pn(X);
- •Value значение переменной X, для которого рассчитывается Pn(X);
- •Value значение переменной X, для которого рассчитывается Pn(X);
- •Void Insert_Element(char New_Unit, unsigned Free, unsigned Position, char *Name, unsigned Next)
- •Void Max_Min_Element(int array[], unsigned Size, unsigned max, unsigned min)
- •Алгоритм 4.2 нахождения наибольшего и наименьшего элементов множества
- •Алгоритм 6. Сортировка последовательности чисел слиянием
- •Void Merge(int *out1, int *out2, unsigned size, int *sorted)
- •Алгоритм 7. Динамического программирования для вычисления порядка, минимизирующего сложность умножения цепочки из n матриц m1m2…Mn
- •Void main()
Value значение переменной X, для которого рассчитывается Pn(X);
p и index вспомогательные переменные; *ptr указатель на элемент массива */
ptr=&Array[Order];
p=*ptr--;
for (index=Order; index; index--){
p*=Value; p+=*ptr--;}
return p;
}//Конец Polinom_Calculation_Fast
Для проверки скорости работы описанных вариантов программы был проведён численный эксперимент. По заданным коэффициентам полинома и величине x были проведены расчеты значений полинома в 1000 точках при различных степенях полиномов. Результаты времени счёта программ на IBM-совместимой ЭВМ с процессором Intel 80286 в миллисекундах показаны в таблице 3.
Таблица 3. Сравнение по временной сложности трех алгоритмов
№ пп |
Порядок полинома n |
Алгоритм с возведением в степень |
Алгоритм Горнера |
Алгоритм Горнера с использованием указателя |
1 |
5 |
1530 |
704 |
666 |
2 |
10 |
3071 |
1191 |
1115 |
3 |
20 |
6510 |
2187 |
2031 |
4 |
50 |
18063 |
5152 |
4758 |
Если за размер задачи взять степень полинома, то можно заметить, что алгоритм с возведением в степень имеет сложность O(n), алгоритмы Горнера 1.2 и 1.3 O(n), причём > 1 > . Поэтому выигрыш по скорости счёта будет тем выше, чем сложнее задача (выше порядок полинома). Если же сравнивать второй и третий алгоритмы, то можно заключить, что они имеют одинаковый порядок временной сложности, но константа c2 будет больше константы c3, и третий алгоритм работает быстрее.
1.2. Структуры данных: списки, очереди, стеки
Теперь рассмотрим некоторые структуры данных, которые полезны при разработке эффективных алгоритмов для обширных классов задач.
С математической точки зрения список (List) это конечная последовательность элементов, взятых из некоторого подходящего множества. Описание алгоритма часто включает в себя некоторый список, к которому добавляются и из которого удаляются элементы. В частности может потребоваться добавить или удалить элемент где-то в середине списка. По этой причине необходимо разработать структуры данных, позволяющие реализовать списки, в которых разрешается удалять и добавлять новые элементы так, как это требуется.
Рассмотрим список:
Unit1; Unit2; Unit3; Unit4. (1.3)
Простейшей его реализацией будет структура последовательно связанных компонент (Linked List), показанная на рисунке 1.
Unit
1
Unit
2
Unit
3
First
Unit
4
Рис.1. Список
со связями
Каждая компонента в этой структуре состоит из 2-х ячеек памяти. Первая ячейка содержит сам элемент (если этот элемент сам является сложной структурой, то первая ячейка может содержать указатель ее местоположения), вторая указатель следующего элемента. Такую структуру можно рассматривать в виде двух массивов, которые на рисунке 2 названы Name (Имя) и Next (Следующая). Если Index индекс в рассматриваемом массиве, то Name[Index] сам элемент, хранящийся там, а Next[Index] индекс следующего элемента в списке (если таковой существует). Если же Index индекс последнего элемента в этом списке, то Next[Index]=0.
Номер индекса элемента |
Name |
Next |
Рис. 2.
Представление списка из 4-х элементов |
|
1 |
1 |
Unit1 |
3 |
2 |
Unit4 |
0 |
3 |
Unit2 |
4 |
4 |
Unit3 |
2 |
Next[0] указатель на первый элемент в списке. Порядок элементов в массиве Name не совпадает с их порядком в списке. Тем не менее, рисунок 2 дает верное представление списка, изображенного на рисунке 1, так как массив Next располагает элементы в том же порядке, в каком они расположены в списке (1.3).
Создадим программу, вставляющую новую компоненту в список. Будем предполагать, что Free номер незанятой ячейки в массивах Name и Next, а Position индекс той компоненты в списке, после которой надлежит вставить новый элемент New_Unit. Тогда:
// Программа 2