Российский государственный гуманитарный университет
Опубликован: 13.07.2022 | Доступ: свободный | Студентов: 343 / 38 | Длительность: 11:54:00
Специальности: Программист
Лекция 6:

Структуры данных и алгоритмы

Значение переменной u вычисляется и присваивается ей сразу, после этого оно не изменяется. Значение переменной v вычисляется в момент вызова.

Для определения функций применяются оба вида присваиваний. Почти всюду далее будет использоваться отсроченное присваивание. Например, функцию f(x) = x^2 + 1 можно определить следующим образом:

 In[10]:= f[x_] := x\^2 + 1
f[3]
 Out[12]= 10

Конструкции вида f[x_, y_, ...] := g[x, y, ...] называют правилами преобразования выражений. Знак подчеркивания (_) обозначает шаблонное выражение, которое может быть заменено произвольным значением. Выражение x_ обозначает шаблон с присвоенным ему именем x. Оно применяется для передачи объекта внутри функциональных конструкций. В правой части переменные используются без знака подчеркивания. Когда в коде встретится выражение, которое сопоставляется с левой частью, оно будет заменено только что вычисленным значением правой части.

Если для определения функции f используется несколько правил, то для вычисления значения выражения f[expr] применяется последнее из правил с одинаковой левой частью:

In[13]:= f[0] := 0
f[x_] := x + 1
f[x_] := x - 1
f[0] := 5
{f[2], f[1], f[0], f[-1], f[a]}
 Out[17]= {1, 0, 5, - 2, - 1 + a}

Более частное определение правила предшествует более общему. Например, ниже для вычисления g[0] используется первое правило, а не второе; если правила поменять местами, то результат не изменится:

 In[18]:= g[0] := 0
g[x_] := 1/x
{g[2], g[1], g[0], g[-1]}
 Out[20]= {1/2, 1, 0, -1}

Для условного задания функций используются встроенные функции If и Which. Например, рассмотрим функции

h(x)=\begin{cases}
\log_2(x), & x>0\\
0 & x \le 0
\end {cases}\\
sng(x)=\begin{cases}
-1, & x>0\\
0, & x = 0\\
1, & x > 0
\end {cases}\\

Функция If соответствует конструкции "если …, то …, иначе …". С ее помощью функцию h можно определить следующим образом:

 In[21]:= h[x_] := If[x > 0, Log[2, x], 0]
{h[8], h[4], h[2], h[0], h[-2]}
 Out[22]= {3, 2, 1, 0, 0}

Функция Which является обобщением функции If. Она может содержать произвольное число условных выражений. Используем ее для определения функции sgn:

In[23]:= sgn[x_] = Which[x>0, 1, x==0, 0, x<0, -1];
{sgn[-3], sgn[0], sgn[3]}
 Out[24]= {-1, 0, 1}

Отменить определение функций и очистить переменные можно с помощью функции Clear:

In[25]:=Clear[f, g];
{f[1], g[1]}
 Out[26]= {f[1], g[1]}

Рассмотрим функцию вычисления k-го члена последовательности Фибоначчи 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, … Вместе с шаблоном укажем тип переменной: значение функции будет вычисляться только для целых положительных значений аргумента. Сначала определим функцию следующим образом:

 In[27]:= f[1] = f[2] = 1;
f[k_Integer?Positive] := f[k - 1] + f[k - 2]
{f[2], f[3], f[8], f[9], f[10]}
f[0]
 Out[29]= {1, 2, 21, 34, 55}
 Out[30]= f[0]

В этом случае для некоторых запросов, например f[50], система может прерывать вычисления из-за превышения временных ограничений.

Определение функции Fibonacci, которое указано ниже, приводит к существенному сокращению рекурсивных вызовов. В этом определении используется вспомогательная функция g, два последних аргумента которой хранят два соседних члена последовательности:

In[31]:= fibonacci[k_Integer?Positive] := g[k, 0, 1]
g[0, m_, _] := m
g[k_, m_, n_] := g[k - 1, n, m + n]
{fibonacci[8], fibonacci[9], fibonacci[10]}
fibonacci[144]
 Out[34]= {21, 34, 55} 
 Out[35]= 555 565 404 224 292 694 404 015 791 808

Более быстрое вычисление значений функции Фибоначчи можно получить, если использовать ее первое определение, но при этом запоминать каждое вычисленное значение:

In[36]:= fib[1] = fib[2] = 1;
fib[n_Integer?Positive]:=fib[n]=fib[n-1]+fib[n-2] 
fib[200]
 Out[38]=280 571 172 992 510 140 037 611 932 413 038 677 189 525

Более подробное введение в определение и использование функций в языке Wolfram содержится в [3, 12].

Результаты вычислений сохраняются во время работы с программой - вычислительной сессии. По умолчанию сессия начинается при открытии программы и заканчивается при ее закрытии. Можно прекратить сессию и начать другую с помощью команды меню Evaluation -> Restart Session. В этом случае все вычисления можно будет произвести заново.

Линейные структуры данных. Список

Рассмотрим модели типов данных список, стек, очередь и дек, которые представляют линейные, или одномерные структуры данных.

Для представления линейной структуры данных в виде терма будет использоваться два функциональных символа - 0-арный символ nil для обозначения пустой структуры и бинарный символ cons для обозначения непустой. Например, список [1, 2, 3] представляется в виде cons(1, cons(2, cons(3, nil))).

Откроем в облаке Wolfram новый файл и введем код:

 In[1]:= 	x = cons[1, cons[2, cons[3, nil]]];
TreeForm[x] (  Shift+Enter  )

Представление данного терма в виде дерева показано на рис. 6.2.

 Представление линейной структуры данных в виде дерева

Рис. 6.2. Представление линейной структуры данных в виде дерева

Список - это конечная последовательность элементов, которая записывается в виде [1, 2, 3] для непустого списка или [] для пустого (в языке Wolfram для списков используются фигурные скобки).

Элементы списка нумеруются с нуля, слева направо. Например, если список имеет вид ["Иванов", "Петров", "Сидоров"], то его элементом с индексом 2 является "Сидоров". Первый элемент списка называется его головой, а список последующих элементов - его хвостом. Для приведенного выше списка головой является "Иванов", а хвостом - список ["Петров", "Сидоров"].