- •2.Понятие формального алгоритма. Тезис Тьюринга - Черча об эквивалентности различных определений вычислимости. Абстрактная машина фон Неймана. Понятие об элементарном исполнителе. 2 часа
- •3. Основные этапы решения задач на эвм: математическая постановка; алгоритм; программа; отладка и тестирование; сдача в эксплуатацию. 1 час
- •4. Критерии качества программы (надежность, эффективность, модифицируемость, возможность многократного использования, стиль программирования). 1 час.
- •5. Диалоговые программы, дружественность (интерфейс человек–компьютер, процессы ввода–вывода, структура диалога, поддержка пользователя). 1 час.
- •7. Постановка задачи и спецификация программы (представление в виде спецификации ввода–вывода; особенности спецификации для завершающихся и циклических программ); способы записи алгоритма. 1 час
- •9. Программа на языке высокого уровня. Язык программирования Си.
- •Элементы языка си
- •Алфавит
- •Буквы и цифры
- •Пробельные символы
- •Разделители
- •Специальные символы
- •Операции
- •Константы
- •Целые константы
- •Константы с плавающей точкой
- •Символьные константы
- •Символьные строки
- •Идентификаторы
- •Ключевые слова
- •Комментарии
- •Структура программы Исходная программа
- •Исходные файлы
- •Выполнение программы
- •Время жизни и область действия
- •Области значений
- •Операторы
- •Оператор выражение
- •Пустой оператор
- •Составной оператор
- •Оператор if
- •Оператор switch
- •Оператор break
- •Оператор for
- •Оператор while
- •Оператор do while
- •Оператор continue
- •Оператор return
- •Оператор goto
- •Категории типов данных
- •Объединения (смеси)
- •Методы организации и хранения линейных списков
- •Операции со списками при последовательном хранении
- •Операции со списками при связном хранении
- •Организация двусвязных списков
- •Стеки и очереди
- •Сжатое и индексное хранение линейных списков
Операции со списками при последовательном хранении
При выборе метода хранения линейного списка следует учитывать, какие операции будут выполняться и с какой частотой, время их выполнения и объем памяти, требуемый для хранения списка.
Пусть имеется линейный список с целыми значениями и для его хранения используется массив d (с числом элементов 100), а количество элементов в списке указывается переменной l. Реализация указанных ранее операций над списком представляется следующими фрагментами программ которые используют объявления:
float d[100];
int i,j,l;
1) печать значения первого элемента (узла)
if (i<0 || i>l) printf("\n нет элемента");
else printf("d[%d]=%f ",i,d[i]);
2) удаление элемента, следующего за i-тым узлом
if (i>=l) printf("\n нет следующего ");
l--;
for (j=i+1;j<="1" if узла i-того соседей обоих печать 3) d[j]="d[j+1];">=l) printf("\n нет соседа");
else printf("\n %d %d",d[i-1],d[i+1]);
4) добавление нового элемента new за i-тым узлом
if (i==l || i>l) printf("\n нельзя добавить");
else
{ for (j=l; j>i+1; j--) d[j+1]=d[j];
d[i+1]=new; l++;
}
5) частичное упорядочение списка с элементами К1,К2,...,Кl в
список K1',K2',...,Ks,K1,Kt",...,Kt", s+t+1=l так, чтобы K1'= K1.
{ int t=1;
float aux;
for (i=2; i<=l; i++) if (d[i]=2; j--) d[j]=d[j-1];
t++;
d[i]=aux;
}
}
Схема движения индексов i,j,t и значения aux=d[i] при выполнении приведенного фрагмента программы приведена на рис.2.
Рис.2. Движение индексов при выполнении операций над списком в последовательном хранении.
Количество действий Q, требуемых для выполнения приведенных операций над списком, определяется соотношениями: для операций 1 и 2 - Q=1; для операций 3,4 - Q=l; для операции 5 - Q=l*l.
Заметим, что вообще операцию 5 можно выполнить при количестве действий порядка l, а операции 3 и 4 для включения и исключения элементов в конце списка, часто встречающиеся при работе со стеками, - при количестве действий 1.
Более сложная организация операций требуется при размещении в массиве d нескольких списков, или при размещении списка без привязки его начала к первому элементу массива.
Операции со списками при связном хранении
При простом связанном хранении каждый элемент списка представляет собой структуру nd, состоящую из двух элементов: val - предназначен для хранения элемента списка, n - для указателя на структуру, содержащую следующий элемент списка. На первый элемент списка указывает указатель dl. Для всех операций над списком используется описание:
typedef struct nd
{ float val;
struct nd * n; } ND;
int i,j;
ND * dl, * r, * p;
Для реализации операций могут использоваться следующие фрагменты программ:
1) печать значения i-го элемента
r=dl;j=1;
while(r!=NULL && j++n ;
if (r==NULL) printf("\n нет узла %d ",i);
else printf("\n элемент %d равен %f ",i,r->val);
2) печать обоих соседей узла(элемента), определяемого указателем p (см. рис.3)
Рис.3. Схема выбора соседних элементов.
if((r=p->n)==NULL) printf("\n нет соседа справа");
else printf("\n сосед справа %f", r->val);
if(dl==p) printf("\n нет соседа слева" );
else { r=dl;
while( r->n!=p ) r=r->n;
printf("\n левый сосед %f", r->val);
}
3) удаление элемента, следующего за узлом, на который указывает р (см. рис.4)
Рис.4. Схема удаления элемента из списка.
if ((r=p->n)==NULL) printf("\n нет следующего");
p->n=r->n; free(r->n);
4) вставка нового узла со значением new за элементом, определенным указателем р (см. рис.5)
Рис.5. Схема вставки элемента в список.
r=malloc(1,sizeof(ND));
r->n=p->n; r->val=new; p->n=r;
5) частичное упорядочение списка в последовательность значений , s+t+1=l, так что K1'=K1; после упорядочения указатель v указывает на элемент K1' (см. рис.6)
Рис.6. Схема частичного упорядочения списка.
ND *v;
float k1;
k1=dl->val;
r=dl;
while( r->n!=NULL )
{ v=r->n;
if (v->valn=v->n;
v->n=dl;
dl=v;
}
else r=v;
}
Количество действий, требуемых для выполнения указанных операций над списком в связанном хранении, оценивается соотношениями: для операций 1 и 2 - Q=l; для операций 3 и 4 - Q=1; для операции 5 - Q=l.