Примитивные операции

Под примитивными операциями подразумевается низкоуровневые операции которые в большинстве случаев не зависят от языка программирования, могут быть легко записаны на псевдокоде, а так же выполнятся за константное время. К примитивным операциям относятся следующие

  • вызов функции;
  • возвращение значения из функции;
  • выполнение простейших арифметических операций (+, -, *, /);
  • сравнение двух чисел;
  • присвоение значения переменной;
  • обращение по индексу массива;
  • и т.д.

Рассмотрим алгоритм нахождения наибольшего элемента в массиве и посчитаем количество совершаемых в нем примитивных операций.

public int ArrayMax(int[] a)               // Количество операций
{
  int max = a[0];                          // 2

  for (int i = 1; i < n; i++)              // 2n
  {
    if (a[i] > max)                        // 2(n-1)
      max = a[i]                           // 2(n-1)
  }

  return max;                              // 1
}
                                           // Общее количество примитивных операций: 6n-1

Максимальное количество примитивных операций совершаемых алгоритмом равно $$6n-1$$. Пусть $$a$$ - время за которое выполняется самая быстрая операция, $$b$$ - время за которое выполняется самая медленная операция. Пусть $$T(n)$$ время выполнения алгоритма в наихудшем случае. Тогда

$$ a(6n-1) \leq T(n) \leq b(6n-1)

$$ Таким образом время $$T(n)$$ заключено между двумя линейными функциями. Изменение программного или аппаратного обеспечения, влияет только на постоянный множитель в $$T(n)$$, но качественно не изменяет скорость роста $$T(n)$$.

Линейная скорость роста времени $$T(n)$$ является внутренним свойством алгоритма нахождения максимального элемента в массиве.

На следущей картинке изображено время выполнения примитивных операций на современном компьтере.

Упражнения

1) Посчитать количество примитивных операций в сортировке выбором.

public void SelectionSort(int[] a)                 // Количество операций
{ 
  for (int i = 0; i < a.Length; i++)               // n
  {                                                // n
      int minPos = i;
      for (int j = i + 1; j < a.Length; j++)       // n(n-1)/2
      {
        if (a[j] < a[minPos])                      // n(n-1)/2
          minPos = j;                              // n(n-1)/2
      }
    int temp = a[i];                               // n
    a[i] = a[minPos];                              // n
    a[minPos] = temp;                              // n
  }
}

Максимальное количество примитивных операций совершаемых алгоритмом равно $$5n + \dfrac{3 n(n-1)}{2} = \mathcal{O}(n^2)$$

2) Посчитать количество примитивных операций в алгоритме перемножения двух матриц.

public void MultiplyMatrix(int[,] a, int[,] b, int n)   // Количество операций
{ 
  int[,] c = new int[n, n];                             // 1

  for (int i = 0; i < a.Length; i++)                    // n
  {
    for (int j = 0; j < a.Length; j++)                  // n*n
    {
      int sum = 0;                                      // n*n
      for (int k = 0; k < a.Length; k++)                // n*n*n
        sum = sum + a[i, k] * a[k, j];                  // n*n*n
    }
    c[i, j] = sum;                                      // n*n
  }
}

Максимальное количество примитивных операций совершаемых алгоритмом равно $$1+n+3n^2+2n^3 = \mathcal{O}(n^3)$$.

МУСОР

Seven functions that often appear in algorithm analysis:

– Constant ≈ 1

– Logarithmic ≈ log n

– Linear ≈ n

– N-Log-N ≈ n log n

– Quadratic ≈ n2

– Cubic ≈ n3

– Exponential ≈ 2n

В log-log масштабе, наклон линии (угловой коэффициент) соответствует скорости роста функции.

results matching ""

    No results matching ""