Книги онлайн и без регистрации » Разная литература » Интернет-журнал "Домашняя лаборатория", 2007 №9 - Журнал «Домашняя лаборатория»

Интернет-журнал "Домашняя лаборатория", 2007 №9 - Журнал «Домашняя лаборатория»

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 327 328 329 330 331 332 333 334 335 ... 415
Перейти на страницу:
ind2-;

          // (Inv == true) & ~B2 (B2 — условие цикла while)

          if (ind1 < ind2)

          // Из Inv & ~B1 & ~B2 & ВЗ следует истинность:

          // ((tower1[ind1] >= item)&&(tower1[ind2]<item))==true.

          // Это условие гарантирует, что последующий обмен

          // элементов обеспечит выполнение инварианта Inv

          {

                temp = tower1[ind1]; tower1[ind1] = tower1[ind2];

                tower1[ind2] = temp;

                ind1++; ind2-;

          }

          //(Inv ==true)

     }

     // из условия окончания цикла следует: (S2 — пустое множество)

     if (ind1 == start)

     // В этой точке S1 и S2 — это пустые множества, — > //(S3 = tower1)

     // Нетрудно доказать, что отсюда следует истинность:

     // (item = min)

     // Как следствие, можно минимальный элемент сделать первым,

     // а к оставшемуся множеству применить рекурсивный вызов.

     {

           temp = tower1[start]; towerl[start] = item;

           tower1[ind] = temp;

           QSort(start+1,finish);

      }

      else

      // Здесь оба множества S1 и S3 не пусты.

      // К ним применим рекурсивный вызов.

      {

          QSort(start,ind1-1);

          QSort(ind2+1, finish);

      }

      // Индукция по размеру массива и истинность инварианта

      // доказывает истинность постусловия в общем случае.

   }

}// Quicksort

Приведу некоторые пояснения к этому доказательству. Задание предусловия и постусловия процедуры QSort достаточно очевидно — сортируемый массив должен быть не пустым, а после работы метода должен быть отсортированным. Важной частью обоснования является четкое введение трех множеств — S1, S2, S3 — и условий, накладываемых на их элементы. Эти условия и становятся частью инварианта, сохраняющегося при работе различных циклов нашего метода. Вначале множества S1 и S3 пусты, в ходе вычислений пустым становится множество S2. Так происходит формирование подзадач, к которым рекурсивно применяется алгоритм. Особым представляется случай, когда множество S1 тоже пусто. Нетрудно показать, что эта ситуация возможна только в том случае, если случайно выбранный элемент множества, служащий критерием разбиения исходного множества на два подмножества, является минимальным элементом.

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

Рис. 10.3. Результаты быстрой сортировки массива

11. Массивы языка С#

Общий взгляд на массивы. Сравнение с массивами C++. Почему массивы C# лучше, чем массивы C++. Виды массивов — одномерные, многомерные и изрезанные. Динамические массивы.

Общий взгляд

Массив задает способ организации данных. Массивом называют упорядоченную совокупность элементов одного типа. Каждый элемент массива имеет индексы, определяющие порядок элементов. Число индексов характеризует размерность массива. Каждый индекс изменяется в некотором диапазоне [а, Ь]. в языке С#, как и во многих других языках, индексы задаются целочисленным типом. В других языках, например, в языке Паскаль, индексы могут принадлежать счетному конечному множеству, на котором определены функции, задающие следующий и предыдущий элемент. Диапазон [а, Ь] называется граничной парой, анижней границей, bверхней границей индекса. При объявлении массива границы задаются выражениями. Если все границы заданы константными выражениями, то число элементов массива известно в момент его объявления и ему может быть выделена память еще на этапе трансляции. Такие массивы называются статическими. Если же выражения, задающие границы, зависят от переменных, то такие массивы называются динамическими, поскольку память им может быть отведена только динамически в процессе выполнения программы, когда становятся известными значения соответствующих переменных. Массиву, как правило, выделяется непрерывная область памяти.

В языке C++ все массивы являются статическими; более того, все массивы являются 0-базируемыми. Это означает, что нижняя граница всех индексов массива фиксирована и равна нулю. Введение такого ограничения имеет свою логику, поскольку здесь широко используется адресная арифметика. Так, несколько странное выражение mas + i, где mas — это имя массива, a i — индексное выражение, имеет вполне определенный смысл для C++ программистов. Имя массива интерпретируется как адрес первого элемента массива, к этому адресу прибавляется число, равное произведению i на размер памяти, необходимой для одного элемента массива. В результате сложения в такой адресной арифметике эффективно вычисляется адрес элемента mas [i].

В языке C# снято существенное ограничение языка C++ на статичность массивов. Массивы в языке C# являются настоящими динамическими массивами. Как следствие этого, напомню, массивы относятся к ссылочным типам, память им отводится динамически в "куче". К сожалению, не снято ограничение 0-базируемости, хотя, на мой взгляд, в таком ограничении уже нет логики из-за отсутствия в C# адресной арифметики. Было бы гораздо удобнее во многих задачах иметь возможность работать с массивами, у которых нижняя граница не равна нулю.

В языке C++ "классических" многомерных массивов нет. Здесь введены одномерные массивы и массивы массивов. Последние являются более общей структурой данных и позволяют задать не только многомерный куб, но и изрезанную, ступенчатую структуру. Однако использование массива массивов менее удобно, и, например, классик и автор языка C++ Бьерн Страуструп в своей книге "Основы языка C++ " пишет: "Встроенные массивы являются главным источником ошибок — особенно когда они используются для построения многомерных массивов. Для новичков они также являются главным источником смущения и непонимания. По возможности пользуйтесь шаблонами vector, vaiarray и т. п.".

Шаблоны, определенные в стандартных библиотеках, конечно, стоит использовать, но все-таки странной является рекомендация не пользоваться структурами, встроенными непосредственно в язык. Замечу, что в других языках массивы являются одной из любимых структур данных, используемых программистами.

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

Объявление массивов

Рассмотрим, как объявляются одномерные массивы, массивы массивов и многомерные массивы. Объявление одномерных массивов

Напомню общую структуру объявления:

1 ... 327 328 329 330 331 332 333 334 335 ... 415
Перейти на страницу:

Комментарии
Минимальная длина комментария - 20 знаков. В коментария нецензурная лексика и оскорбления ЗАПРЕЩЕНЫ! Уважайте себя и других!
Комментариев еще нет. Хотите быть первым?