
- •Министерство образования и науки Российской Федерации
- •Цель лекции
- •План лекции
- •1 Происхождение вычислительных машин
- •2 Изучение алгоритмов
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Биты и их хранение
- •2 Оперативная память
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Устройства внешней памяти
- •3 Хранение и поиск файлов
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Представление числовых значений
- •2 Хранение целых чисел
- •3 Хранение дробей
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Представление текста
- •2 Представление изображений
- •Достоинства пиксельной графики
- •Недостатки пиксельной графики
- •Достоинства векторной графики
- •Недостатки векторной графики
- •3 Представление звука
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Сжатие изображений
- •2 Ошибки передачи данных
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Архитектура эвм
- •2 Связь процессора с другими устройствами
- •3 Другие архитектуры
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Машинный язык
- •2 Пример машинного языка
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Выполнение программы
- •2 Пример выполнения программы
- •3 Программы и данные
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Логические операции
- •2 Операции сдвига
- •3 Арифметические операции
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Эволюция операционных систем
- •2 Архитектура операционных систем
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Понятие процесса
- •2 Управление процессами
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Классификация сетей
- •2 Сетевые протоколы*
- •3 Безопасность сетей
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Понятие алгоритма
- •2 Представление алгоритма
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Теория решения задач
- •2 Общие методы решения задач
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Алгоритм последовательного поиска
- •2 Управление циклами
- •3 Алгоритм сортировки методом вставки
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Алгоритмы поиска и сортировки
- •2 Управление рекурсией
- •3 Разработка рекурсивных процедур
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Эффективность алгоритмов
- •2 Верификация программ
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Эволюция и классификация языков программирования
- •2 Концепции традиционного программирования
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Процедурные единицы
- •2 Реализация языка программирования
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Объектно-ориентированное программирование
- •2 Декларативное программирование
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Структуры данных
- •Integer Scores (2.9).
- •2 Статические и динамические структуры
- •3 Указатели
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Массивы
- •2 Списки
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Структура и функции стека
- •2 Реализация стека
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Очереди
- •2 Деревья
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Пользовательские типы данных
- •Int Age;
- •2 Классы
- •Int *StackEntries;
- •3 Стандартная библиотека шаблонов
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Роль операционной системы
- •2 Последовательные файлы
- •3 Вопросы программирования
- •0000000010000110
- •001100010011001100110100
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Основные положения индексации
- •2 Вопросы программирования
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Основные положения хеширования
- •2 Вопросы программирования
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Общие вопросы
- •2 Система управления базой данных
- •3 Поддержка целостности баз данных
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Модели баз данных
- •2 Реляционная модель баз данных
- •3 Объектно-ориентированные базы данных
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Интеллект и машины
- •2 Распознавание образов
- •3 Мышление
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Искусственные нейронные сети
- •2 Генетические алгоритмы
- •Контрольные вопросы
- •Невычислимые функции Цель лекции
- •План лекции
- •1 Основы машины Тьюринга
- •2 Невычислимая функция
- •3 Сложность задач
- •Листинг 1. Процедура MergeLists для объединения двух упорядоченных списков
- •Листинг 2. Алгоритм сортировки слиянием, реализованный в процедуре MergeSort
- •Контрольные вопросы
- •Цель лекции
- •План лекции
- •1 Шифрование с открытым ключом
- •2 Модульная арифметика
- •Контрольные вопросы
- •Литература
- •Internet-ресурсы
2 Статические и динамические структуры
Во время конструирования абстрактных представлений данных важно различать, является структура данных статической или динамической, то есть меняется ли со временем ее форма и размер. Например, если конструируемый абстрактный инструмент — это список имен, важно решить, останется ли его размер фиксированным на все время существования списка или он будет уменьшаться и увеличиваться с удалением и добавлением имен.
В целом, статическими структурами (static structure) проще управлять, чем динамическими (dynamic structure). Если структура статическая, нам необходимо только обеспечить способы доступа к различным элементам данных и, возможно, способы изменения значений элементов, находящихся на определенных местах. Но в случае динамической структуры также необходимо решать проблемы добавления и удаления элементов данных и поиска пространства в памяти для увеличения размера структуры. Излишнее разрастание плохо организованной структуры может привести к тому, что она целиком будет копироваться в другую, большую по размерам область памяти — а для этого требуется много времени.
3 Указатели
Вспомните, что ячейки в оперативной памяти машины идентифицируются числовыми адресами. Эти числовые значения можно также хранить в ячейках памяти. Указатель (pointer) — это ячейка (или блок ячеек) памяти, содержащая адрес другой ячейки памяти. Применительно к структурам данных, указатели используются для записи адресов элементов данных. Таким образом, элемент данных может храниться в какой-либо ячейке памяти, а адрес этой ячейки — в указателе, при помощи которого можно позже получить эти данные. То есть значение указателя сообщит нам, где искать данные. В некотором смысле указатель указывает на данные, отчего и получил такое название.
Мы уже встречались с концепцией указателей в контексте счетчика команд процессора, который содержит адрес очередной инструкции для выполнения. Фактически, другое название счетчика команд — указатель команд (instruction pointer). Адреса, также называемые URL, которые используются для связи гипертекстовых документов, также могут служить примером концепции указателей, но они указывают местоположения в сети Интернет, а не в оперативной памяти компьютера.
Во многих современных языках программирования указатели включены в набор основных типов данных. Можно объявлять, выделять память и манипулировать указателями так же, как целыми числами или строками. При помощи такого языка программист может создавать развитые сети элементов данных в памяти машины, где каждый блок ячеек памяти содержит указатели на другие блоки. Следуя указателям, можно проследить эти пути от блока к блоку.
В качестве примера давайте представим, что в компьютерной памяти хранится список рассказов, отсортированный в алфавитном порядке по названию. Такая организация удобна во многих приложениях, но одновременно затрудняет поиск всех рассказов, написанных одним автором, так как они беспорядочно разбросаны по списку. Для решения этой проблемы можно зарезервировать в каждом блоке ячеек памяти, представляющем один рассказ, отдельную ячейку типа указатель. Тогда в каждом из этих указателей можно хранить адрес другого блока, представляющего произведение того же автора, и все рассказы одного автора будут связаны в замкнутую цепь (рис. 3). Отыскав один рассказ заданного автора, мы можем найти и все остальные, переходя по указателям от книги к книге.
Рисунок 3 – Рассказы, отсортированные по названию и связанные указателями по автору
Рассмотрим, как указатели обрабатываются на машинном языке.
Предположим, что мы планируем написать программу на машинном языке, описанном в приложении В, которая выталкивает запись из стека, и помещает эту запись в регистр общего назначения. Другими словами, мы хотим поместить в регистр содержимое ячейки памяти, находящейся на вершине стека. В нашем машинном языке есть две инструкции для записи в регистры — первая с кодом операции 2, и вторая с кодом операции 1. Вспомните, что в случае кода операции 2 поле операнда содержит данные, которые будут записаны, а в случае кода операции 1 в поле операнда содержится адрес данных, которые будут загружены в регистр.
Поскольку мы заранее не знаем содержимого записи стека, код операции 2 не подходит для выполнения нашей задачи. Более того, код операции 1 мы также использовать не можем, так как не знаем адреса данных, ведь адрес вершины стека изменяется по мере выполнения программы. Но мы знаем адрес указателя стека. Таким образом, нам известно расположение ячейки, содержащей адрес данных, которые мы хотим загрузить в регистр. Что нам требуется — это еще один код операции для записи в регистр, где операнд содержит адрес указателя на нужные данные.
Для достижения этой цели разработчик машины из приложения В может воспользоваться кодом операции D. Язык можно дополнить так, чтобы инструкция вида DRXY означала запись в регистр R содержимого ячейки памяти, адрес которой находится по адресу XY (рис. 4). Так, если указатель стека находится в ячейке памяти по адресу АА, то при выполнении инструкции D5AA данные из вершины стека будут загружены в регистр 5.
Эта инструкция, однако, не выполняет операцию выталкивания полностью. От указателя стека необходимо отнять единицу, чтобы он теперь указывал на новую вершину стека. Инструкция должна выполняться следующим образом: программа на машинном языке загрузит указатель стека в регистр, отнимет от указателя единицу и запишет результат обратно в память.
Рисунок 4 – Первая попытка расширения машинного языка для использования указателей
Используя в качестве указателя стека один из регистров вместо ячейки памяти, мы можем сократить количество перемещений указателя стека между регистрами и памятью. Однако это означает, что нам необходимо переопределить инструкцию загрузки, чтобы она искала указатель в регистре, а не в оперативной памяти. Таким образом, вместо предыдущего подхода разработчик машины может определить инструкции с кодом операции D в форме DR0S, что означает запись в регистр R содержимого ячейки памяти, на которую указывает регистр S (рис. 5). Тогда, выполнив эту инструкцию и команду вычитания единицы из значения в регистре S, мы выполним полную операцию выталкивания.
Рисунок 5 – Загрузка в регистр значения из ячейки памяти, найденной при помощи указателя, хранящегося в регистре
Похожая инструкция требуется для выполнения операции проталкивания. Разработчик машины может еще более расширить язык из приложения В, введя код операции Е. Инструкция в форме EROS будет означать запись содержимого регистра R в ячейку памяти, на которую указывает регистр S. И снова для завершения операции проталкивания за этой инструкцией будет следовать команда добавления единицы к значению в регистре S.
С этими расширениями машинного языка из приложения В будут реализованы три способа адресации. В первом операнд инструкции содержит данные (код операции 2). Во втором случае в операнде инструкции содержится адрес данных (коды операции 1 и 3). В третьем случае в операнде инструкции хранится адрес указателя на данные (коды операции D и Е). Эти способы называются непосредственной адресацией (immediate addressing), прямой адресацией (direct addressing) и косвенной адресацией (indirect addressing) соответственно. Все они часто встречаются в современных машинных языках.
Проблема указателей. Также как использование блок-схем привело к созданию запутанных алгоритмов, а бессистемное употребление оператора goto — к появлению плохо спроектированных программ, необдуманное использование указателей может служить причиной излишней сложности и подверженности структур данных ошибкам. Чтобы внести порядок в этот хаос, многие языки программирования ограничивают гибкость указателей. Например, в языке Java указатели в общей форме запрещены. Вместо этого он разрешает использование ограниченной формы указателей, называемой ссылкой. Одно из различий состоит в том, что ссылку нельзя изменить, применив арифметическую операцию. То есть если Java-программист захочет переместить ссылку Next на следующую запись в непрерывном списке, ему придется использовать оператор типа переназначить Next на следующую запись списка, тогда как С-программист может применить оператор, эквивалентный следующему: присвоить Next значение Next + 1
Обратите внимание, что оператор Java лучше отражает желаемую цель. Более того, для успешного выполнения оператора Java в списке должна существовать еще хотя бы одна запись, а в случае, если Next уже указывает на последнюю запись списка, оператор С приведет к тому, что Next будет содержать адрес каких-то не относящихся к списку данных — эту ошибку часто делают начинающие и даже опытные С - программисты.