Учебная работа. Оборудование промежуточной станции устройствами электрической централизации

1 Звезда2 Звезды3 Звезды4 Звезды5 Звезд (Пока оценок нет)
Загрузка...

Оборудование промежуточной станции устройствами электрической централизации

СОДЕРЖАНИЕ

двумерный динамический массив программа

ВВЕДЕНИЕ

Глава 1. Динамические массивы в С++

1.1 Объявление и инициализация массива

1.2 Доступ к элементам массива

1.3 Рабочий размер массива

1.4 Многомерные массивы

1.5 Указатели, динамические массивы

1.6 использование адресов и указателей при работе с динамическими массивами

1.7 Формирование динамических массивов с использованием библиотечных функций

1.8 Формирование динамических массивов с использованием операций new и delete

Глава 2. Разработка прикладной программы. Представление

2.1 Функции, требования к программе

2.2 Анализ и исследование результата работы программы

Выводы

ВВЕДЕНИЕ

Информационные технологии развиваются очень быстро, гораздо быстрее развития человека. Знания опережают время, поэтому мы все чаще наблюдаем развитие какой-либо технологии или выход в свет очередного компьютерного новшества. Создатели этого чуда — в своем роде гении и мастера своего дела. Это программисты, или люди, которые занимаются разработкой программных продуктов. Не очевидно, но факт, что таких людей с каждым днем становится все больше и больше. В своем арсенале они используют множество языков программирования, большинство из которых широко известны [2].

Одним из мощнейший языков программирования является Си++, который был разработан Бьерном Страуструпом в 1979 году и остается актуальным по сей день. По своим функциональным возможностям Си++ должен был заменить язык Си ввиду недостаточной функциональности. Основное новшество, добавленное в язык Си++, это большой набор встроенных библиотек и возможность работы с объектно-ориентированным программированием. С уверенностью можно отметить, что язык Си++ поистине великий язык для успешного старта в области программирования [3].

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

Одним из мощнейших средств языка Си++ являются динамические массивы. Их основное отличие от обычных массивов заключается в том, что они хранятся в динамической памяти [5].

В данной работе мы попытаемся проанализировать, какие типы массивов существуют, какие операции предусмотрены с переменными данного типа и как они задаются в С++, изучение организации массивов и способов доступа к их элементам.

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

Для достижения поставленной цели нами были поставлены следующие задачи:

.Исследовать аспекты изучения темы: объявление, выделение и освобождение памяти под динамические массивы, обращение к элементам, научиться решать задачи с использованием динамических массивов на языке C++.

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

.Оценить эффективность использования динамического распределения памяти в массивах

В главе 1приведено описание правила использования динамической памяти, указателя и его назначение, формат определения указателя, способы инициализации указателя, операции над указателями, связь массива с указателем, способы доступа к элементам массива через указатель.

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

ГЛАВА 1. ДИНАМИЧЕСКИЕ МАССИВЫ В С++

.1 Объявление и инициализация массива

Массив — именованная последовательность однотипных объектов. Массивы используются в том случае, когда над группой величин одинакового типа требуется выполнять однообразные действия.

Отдельная единица данных, входящая в состав массива, называется элементом массива. Доступ к элементам массива осуществляется по их порядковому номеру. Все элементы массива относятся к одному типу данных и имеют одинаковый размер.

Использованию массива в программе предшествует его объявление, резервирующее под массив определенное количество памяти. При объявлении массива следует указать его имя, размер (количество элементов) и тип элементов:

Следует отметить, что размер массива не может быть изменен в процессе работы программы.

В следующем примере объявляется массив, состоящий из 10 элементов типа int:

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

Одновременно с объявлением массива, можно инициализировать его элементы. В следующем примере мы укажем начальные значения для элементов массива Q:

В случае инициализации массива, его размер можно не указывать. Компилятор самостоятельно определит размер массива по количеству указанных при инициализации значений:

.2 Доступ к элементам массива

обращение к элементу массива осуществляется по имени массива и порядковому номеру элемента — индексу. Индекс указывается в квадратных скобках после имени массива. При этом нумерация элементов массива начинается с нуля. Индекс элемента не должен превышать фактическое количество элементов в массиве. В противном случае, возможны непредсказуемые ошибки в процессе работы программы. Элементы массива можно использовать в программе таким же образом, как и обычные переменные: они могут участвовать выражениях, указываться в качестве параметров при вызове функций, и изменять свое В следующих трех примерах мы объявим массив Q, состоящий из трех элементов типа int, присвоим элементам начальные значения и выведем все элементы массива на экран.

1.3 Рабочий размер массива

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

В качестве решения данной проблемы можно объявить массив с заведомо большим размером, чем может потребоваться на этапе выполнения программы, и, впоследствии, работать только с частью из этих элементов. В таком случае массив будет характеризоваться двумя размерами: фактическим и рабочим. Фактический размер массива — размер, указанный при объявлении массива — максимальное количество элементов с которым может работать программа. Фактический размер является постоянной величиной. Рабочий размер массива — это количество элементов, которые используются в программе на текущий момент. Рабочий размер массива может изменяться в процессе работы программы. Для хранения информации о рабочем размере массива в программе обычно предусматривают отдельную переменную. Очевидно, что рабочий размер массива не может превышать фактический.

В следующей программе мы вычислим сумму элементов массива M, имеющего фактический размер 100 элементов. Рабочий размер массива и значения его элементов определяются пользователем в процессе работы программы.

Листинг 1.1

#include

#include namespace std;main()

{

//Фактический размер массива М constintphys_size = 100;

//Рабочий размер массива М intwork_size = 0;

//Массив M[phys_size];

// Определяем рабочий размер массива cout<<"Введите количество элементов:»; // Ввод значения work_size с клавиатуры cin>>work_size;

// Проверяем phys_size)cout<< "ошибочный размер массива»;else{// Вводим значения элементов массиваfor (inti=0; i> M[i];// Определяем сумму элементов массиваintsum = 0;for (inti=0; iрезультат на экранcout<< "СУММА ЭЛЕМЕНТОВ МАССИВА: " <любую клавишу}

1.4 Многомерные массивы

Массивы, рассмотренные нами выше, являются одномерными. В общем случае, массивы могут иметь несколько измерений.

Многомерный массив — это массив, элементами которого являются массивы.

Двумерный массив — массив одномерных массивов — может быть представлен как матрица, состоящая из строк и столбцов, на пересечении которых размещаются значения (рис. 1.1).

Рисунок 1.1 — Двумерный массив

Трехмерный массив — массив двумерных массивов — может быть представлен как множество одинаковых матриц или как куб (рис. 1.2).

При объявлении многомерного массива в отдельных квадратных скобках для каждого измерения указывается количество элементов:

Рисунок 1.1 — Трехмерный массив массив

Для обращения к элементу многомерного массива необходимо определить его порядковый номер по каждому измерению:

.5 Указатели, динамические массивы

Как видно из рассмотренного примера программы, приведенного в листинге 1.1 в разделе 1.3 курсового проекта, в Си++ массивы статические, и их размер задается при описании. Это не всегда удобно, кроме того, при решении некоторых задач заранее неизвестен размер формируемого массива.

В Си++ существуют динамические массивы — массивы переменной длины, они определяются с помощью указателей.

Указательпеременная, значением которой является адрес памяти, по которому хранится объект определенного типа. При объявлении указателей всегда указывается тип объекта, который будет храниться по данному адресу.

Указатель описывается следующим образом:

* name;

Здесь name — переменная, объявляемая, как указатель . По этому адресу (указателю) храниться Например:

*i;

Объявляем указатель (адрес) i. По этому адресу будет храниться переменная типа int.

Переменная i указывает на тип данных int.

*x,*z;

Объявляем указатели с именами x и z, которые указывают на переменные типа float.

Операции * и & при работе с указателями

При работе с указателями в основном используются операции & и *. Операция & возвращает адрес своего операнда.

Например, если объявлена переменная a следующим образом:

float a;

тооператор

_a=&a;

записывает в переменную adr_a адрес переменной a, переменная adr_aдолжна быть указателем на тип float. Ее следует описать следующим образом:

*adr_a;

Операция * выполняет действие, обратное операции &. Она возвращает значение переменной, хранящееся по заданному адресу.

Например, оператор

=*adr_a;

записывает в переменную a вещественное

Операция присваивания указателей.

одного типа, то один можно присваивать другому с помощью обычной операции присваивания.

Рассмотрим следующий пример

#include

#include main()

{PI=3.14159,*p1,*p2;=p2=&PI;

printf(«По адресу p1=%p хранится *p1=%gn»,p1,*p1);(«По адресу p2=%p хранится *p2=%gn»,p2,*p2);

В этой программе определены: вещественная переменная PI=3.14159 и два указателя на тип float p1 и p2. затем в указатели p1 и p2 записывается адрес переменной PI. Операторы printf выводят на экран адреса p1 и p2 и значения, хранящиеся по этим адресам. Для вывода адреса используется спецификатор типа %p. В результате работы этой программы в переменных p1и p2 будет храниться значение одного и того же адреса, по которому хранится вещественная переменная PI=3.14159.

По адресу p1=0012FF7C хранится *p1=3.14159

По адресу p2=0012FF7C хранится *p2=3.14159

Если указатели ссылаются на различные типы, то при присваивании значения одного указателя другому, необходимо использовать преобразование типов. Без преобразования можно присваивать любому указателю указатель void *. Рассмотрим пример работы с указателями различных типов.

#include

#include main()

{PI=3.14159,*p1;

double *p2;

//В переменную p1 записываем адрес PI=&PI;

//указателю на double присваиваем значение, которое ссылается на

//тип float.=(double *)p1;

printf(«По адресу p1=%p хранится *p1=%gn»,p1,*p1);(«По адресу p2=%p хранится *p2=%en»,p2,*p2);

}

По адресу p1=0012FF7C хранится *p1=3.14159

По адресу p2=0012FF7C хранится *p2=2.642140e-308

В указателях p1 и p2 хранится один и тот же адрес, но значения, на которые они ссылаются, оказываются разными. Это связано с тем, указатель типа *float адресует 4 байта, а указатель *double — 8 байт. После присваивания p2=(double *)p1; при обращении к *p2 происходит следующее: к переменной, хранящейся по адресу p1, дописывается еще 4 байта из памяти. В результате значение *p2 не совпадает со значением *p1.

#include

#includemain()

{PI=3.14159,*p1;*p2;=&PI;=(float *)p1;

printf(«По адресу p1=%p хранится *p1=%gn»,p1,*p1);(«По адресу p2=%p хранится *p2=%en»,p2,*p2);

}

после присваивания p2=(double *)p1; при обращении к *p2 происходит следующее: из переменной, хранящейся по адресу p1, выделяется только 4 байта. В результате и в этом случае значение *p2 не совпадает со значением *p1.

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

Если есть следующий оператор

*p;

то в переменной p хранится адрес, а с помощью конструкции *p можно получить значение, хранящееся по адресу p.

В случае использования оператора

p;

то для вычисления адреса используется конструкция &p, а в переменной p находится вещественное значение.

Арифметические операции над адресами.

Над адресами в языке Си определены следующие операции:

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

однако при выполнении арифметических операций есть некоторые особенности. Рассмотрим их на следующем примере.

}

Операция p1++ увеличивает значение адреса на 8, операция p2++ увеличивает значение адреса на 4, а операция i++ на 2. Операции адресной арифметики выполняются следующим образом:

операция увеличения приводит к тому, что указатель будет слаться на следующий объект базового типа (для p1 — это double,д ля p2 — float, для i — int);

операция уменьшения приводит к тому, что указатель, ссылается на предыдущий объект базового типа;

после операции p1=p1+n, указатель будет передвинут на n объектов базового типа;p1+n как бы адресует n-й элемент массива, если p1 — адрес начала массива.

1.6 Использование адресов и указателей при работе с динамическими массивами

С помощью указателей в Си можно выделить участок памяти (динамический массив) заданного размера для хранения данных определенного типа. Для этого необходимо выполнить следующие действия:

. Описать указатель (например, переменную p) определенного типа.

. Начиная с адреса, определенного указателем, с помощью функций calloc, malloc или операции new выделить участок памяти определенного размера. после этого p будет адресом первого элемента выделенного участка оперативной памяти (0-й элемент массива), p+1 будет адресовать — следующий элемент в выделенном участке памяти(1-й элемент динамического массива), & , p+i является адресом i-го элемента.

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

К i-му элементу динамического массива p можно обратиться одним из двух способов *(p+i) или p[i].

. Когда участок памяти будет не нужен, его можно освободить с помощью функции free(), операции delete.

Перед подробным описанием работы с динамическими переменными, рассмотрим функции calloc, malloc, realloc и free и операции new и delete.

Единственным параметром функции malloc является целое беззнаковое байтах. Функция malloc возвращает безтиповый указатель (void *) на выделенный участок памяти. обращение к функции malloc имеет вид

*malloc(n);

здесь n определяет размер выделяемого участка памяти в байтах, функция вернет значение NULL, если выделить память не удалось и указатель на выделенный участок памяти, при успешном выделении.

.7 Формирование динамических массивов с использованием библиотечных функций

Динамический массив — массив переменной длины, память под который выделяется в процессе выполнения программы.

Обычно, объем памяти, необходимый для той или иной переменной, задается еще до процесса компиляции посредством объявления этой переменной. Если же возникает необходимость в создание переменной, размер которой неизвестен заранее, то используют динамическую память. Резервирование и освобождение памяти в программах на C++ может происходить в любой момент времени. Доступ к элементам динамического массива такой же, как и к статическим. Динамический массив нельзя при создании инициализировать и нельзя обнулять.

Формирование массивов с переменными размерами можно организовать с помощью указателей и средств динамического распределения памяти двумя способами:

с использованием библиотечных функций, описанных в заголовочных файлах alloc.h и stdlib.h (стандартный Си);

с использованием операций new и delete (Си++).

Для выделения и освобождения динамической памяти используются функции, приведенные в табл. 1.1.

Таблица 1.1 — Библиотечные функции для формирования динамических массивов

ФункцияПрототип и краткое описаниеmallocvoid * malloc(unsigned s) Возвращает указатель на начало области динамической памяти длиной в s байт, при неудачном завершении возвращает NULLcallocvoid * calloc(unsigned n, unsigned m) Возвращает указатель на начало области динамической памяти для размещения n элементов длиной по m байт каждый, при неудачном завершении возвращает NULLreallocvoid * realloc(void * p, unsigned s) Изменяет размер блока ранее выделенной динамической памяти до размера s байт, р- адрес начала изменяемого блока, при неудачном завершении возвращает NULLfreevoid *free(void p) Освобождает ранее выделенный участок динамической памяти, р — адрес первого байта

Пример:

Функция для формирования одномерного динамического массива

int * make_mas(int n)

{

int *mas;=(int*)malloc(n*sizeof(int));(inti=0;i

}

Для выделения памяти используется функция malloc, параметром которой является размер выделяемого участка памяти равный n*sizeof(int). Так как функция malloc возвращает нетипизированный указатель void*, то необходимо выполнить преобразование полученного нетипизированного указателя в указатель int*.освободить выделенную память можно функцией free(mas).

.8 Формирование динамических массивов с использованием операций new и delete

Для динамического распределения памяти используются операции new и delete. Операция

имя_типа

или

newимя_типа инициализатор

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

Примеры:

1) int *i;=new int(10);

) float *f;=new float;

  • int *mas=new[5];
  • В примерах 1, 2 показано как выделить память под скалярные переменные, пример 3 показывает выделение памяти под массив переменных.

    Операция delete указатель освобождает участок памяти ранее выделенный операцией new.

    Пример:

    Функция для формирования двумерного динамического массива

    int ** make_matr(int n)

    {**matr;,j;=new int*[n];(i=0;i

    {[i]=new int[n];(j=0;j

    }matr;

    }

    При формировании матрицы сначала выделяется памяти для массива указателей на одномерные массивы, а затем в цикле с параметром выделяется память под n одномерных массивов.

    рисунок 1.2 — Выделение памяти под массив

    Чтобы освободить память необходимо выполнить цикл для освобождения одномерных массивов

    for(inti=0;i

    delete matr[i];

    после этого освобождаем память, на которую указывает указатель matr

    delete [] matr;

    Выводы к главе 1

    В данной главе нами было подробно описано с демонстрацией примеров такие понятия, как: правила использования динамической памяти, указателя и его назначение, формат определения указателя, способы инициализации указателя, операции над указателями, связь массива с указателем, способы доступа к элементам массива через указатель.

    Из выше изложенного отметим возможности указателей и динамических массивов в С++.

    Преимущество указателей в том, что они могу указывать на различные области памяти; в том, что сами указатели занимают в памяти гораздо меньше места, чем массив/объект, на который они указывают (вместо отправки в функцию полностью массива/объекта, т.е. его копии, можно передать только указатель на него, а скопировать указатель гораздо проще).

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

    ГЛАВА 2. РАЗРАБОТКА ПРИКЛАДНОЙ программы. ПРЕДСТАВЛЕНИЕ

    .1 Функции, требования к программе

    Принципы программирования на языке C++ основаны на понятии функции. Функция — самостоятельная единица программы, спроектированная для реализации конкретной задачи. Функции в языке C++ играют ту же роль, какую играют функции, подпрограммы и процедуры в других языках, хотя детали их структуры могут быть разными. Вызов функции приводит к выполнению некоторых действий. например, при обращении к функции printf() осуществляется вывод данных на экран. другие же функции позволяют получать величины, используемые затем в других частях программы.

    В разработанной нами программе мы описали функцию под общим именем main(), которая выполняет формирование и обработку двухмерного динамического массива. Функции пользователя в данной программе мы не использовали.

    Работа с динамическими массивами имеет ряд особенностей и сложностей. Они усугубляются еще и тем, что в С++ в соответствии с требованиями эффективности программного кода, функции библиотеки минимально защищены от ошибок программирования:

    если динамическая переменная создана, а указатель на нее «потерян» программой, то такая переменная представляет собой «вещь в себе» -существует, но недоступна для использования. Тем не менее, занимаемая ею память остается за программой;

    ошибки в процессе создания, уничтожения и работы с динамическими переменными (повторная попытка уничтожения динамической переменной, попытка уничтожения переменной, не являющейся динамической и т.д.), приводят к непредсказуемым последствиям в работе программы. Причем программа «валится» иногда не в том месте, где производятся ошибочные действия, при последующих выводах функций работы с библиотекой.

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

    Алгоритм решения этой задачи очевиден. Для вычисления среднего арифметического элементов массива требуется найти их общую сумму, после чего разделить ее на количество элементов. Порядок просмотра массива роли не играет. Определение положительных элементов каждой строки требует просмотра матрицы по строкам. Обе величины вычисляются при одном просмотре матрицы. здесь размерности массива заданы именованными константами N row и M col, что позволяет легко их изменять. Для упрощения отладки рекомендуется задать небольшие значения этих констант. При вычислении количества положительных элементов для каждой строки выполняются однотипные действия:

    обнуление счетчика n, просмотр каждого элемента строки и сравнение его с нулем, при необходимости увеличение счетчика на единицу, а после окончания вычислений — вывод результирующего значения счетчика.

    Рекомендуется после ввода матрицы выполнять её контрольный вывод на экран.

    #include

    #includenamespace std;()

    {(LC_CTYPE, «»);, ncol;<< "Введите N row: " <>nrow;<< "Введите M col:" <>ncol;** a = new int*[nrow];i, j;(i = 0; i

    {[i] = new int[ncol];(j = 0; j

    {[i][j] = rand() % 201 — 100; // -100 : 100<< a[i][j] << " ";

    }<

    }n; // счетчик положительных элементов

    float s = 0; // суммаэлементов(i = 0; i

    {= 0;(j = 0; j

    {+= a[i][j];(a[i][j]>0) n++;

    }<< "B строке " << i << " кол-во положительных элементов: «

    << n <

    }/= nrow*ncol; // вычисление среднего

    system(«pause»);(int i = 0; i

    return;

    }

    рисунок 2.1 — Реакция ЭВМ

    На рис. 2.1 приведен пример демонстрации работы двухмерного динамического массива с использованием операции new.

    В нашем примере для матрицы выделяется динамическая память, которая задана именованными константами Nrow=5 и Mcol=4.

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

    Программа была протестирована и проверен результат работы с помощью математических вычислений вручную.

    ВЫВОДЫ

    При разработке данного курсового проекта были достигнуты все запланированные цели и задачи: систематизация знаний по теме, получили практические навыки выделения, перераспределения и освобождение памяти при работе с динамическими массивами, а также разработан программный продукт, который демонстрирует работу динамического массива.

    Преимуществом разработки данной программы с использованием динамического распределения памяти в отличие от статического является:

    экономное использование памяти;

    возможность изменять размер массива во время работы программы.

    Недостатком данного программного продукта является то, что в программе не обеспечивается автоматическая оптимизация кода, а также выдача транслятором диагностических сообщений. Для полноценной реализации динамических массивов требуется, чтобы их поддержка была включена в трансляторы языка C++.

    Данный курсовой проект можно использовать как учебный пример по дисциплине «Программирование» для наглядной демонстрации работы с динамическими массивами. Размер программного продукта 9,03 МБ.

    список ИСПОЛЬЗУЕМЫХ ИСТОЧНИКОВ

    1.Архангельский А.Я. Программирование в С++ Builder 6/А.Я. Архангельский-М.:бином,2002.-1152с.

    2.Вирт Н. Алгоритмы и структуры данных.: Пер. С англ. — М.: мир, 2001.

    .Подбельский В.В. Язык Си++. — М.: Финансы и статистика, 2004.

    .Седжвик Р. Фундаментальные алгоритмы на C++. Части 1-4. Анализ. Структуры данных. Сортировка. Поиск. 2001.

    .Подбельский В.В., Программирование на языке Си++:/ Учеб. пособие для студентов вузов, обучающихся по специальностям Приклад. Математика и Вычисл. машины, комплексы, системы и сети/В.Подбельский.-5 е изд.-М.: финансы и статистика, 2003.-560с.

    .Страуструп, Бьерн. Язык программирования С++/Бьерн Страуструп; пер.с английского С.Анисимова, М.Кононова под ред. Ф.Андреева, А.Ушакова.- Спец. издание.-М.:бином,2004.-1038с

    .Керниган, Бриан В., Ритчи, ДеннисМ. язык программирования С/ Пер. с англ. изд., перераб. И доп.-М.:финансы и статистика, 1992.-271 с.

    .Топп У., Форд У. Структуры данных в С++. 1999.

    .Хэзфилд Р., Кирби Л. Искусство программирования на C. Фундаментальные алгоритмы, структуры данных и примеры приложений. 2001.

    .Фридман А.Л. язык программирования Си++. Курс лекций: [учеб. пособие для вузов]/А.Л. Фридман — М.: Интернет-Университет Информационных технологий, 2004.

    Учебная работа. Оборудование промежуточной станции устройствами электрической централизации