- •Введение
- •Блок-схема алгоритма
- •Общие требования к блок-схеме алгоритма
- •Линейные и разветвляющиеся процессы
- •Циклические процессы
- •Итерационные процессы
- •Основные понятия языка С(С++)
- •Комментарии
- •Типы данных
- •Данные целого типа
- •Данные вещественного типа
- •Модификатор const
- •Переменные перечисляемого типа
- •Константы
- •Структура программы на языке С(С++)
- •Операции и выражения
- •sizeof
- •Операция присваивания
- •Арифметические операции
- •Операции поразрядной арифметики
- •Логические операции
- •Операции отношения
- •Инкрементные и декрементные операции
- •Операция sizeof
- •Порядок выполнения операций
- •Приоритет операций
- •Преобразование типов
- •Операция приведения
- •Операция запятая
- •Ввод и вывод информации
- •Директивы препроцессора
- •Директива #include
- •Директива #define
- •Операторы языка С(С++)
- •Понятие пустого и составного операторов
- •Операторы организации цикла
- •Оператор цикла for
- •Оператор цикла while
- •Оператор цикла do … while
- •Вложенные циклы
- •Примеры программ
- •Массивы
- •Одномерные массивы
- •Примеры программ
- •Многомерные массивы (матрицы)
- •Примеры программ
- •Указатели
- •Понятие указателя
- •Описание указателей
- •Операции с указателями
- •Связь между указателями и массивами
- •Массивы указателей
- •Многоуровневые указатели
- •Примеры программ
- •Символьные строки
- •Ввод/вывод строк.
- •Функции работы со строками.
- •Примеры программ
- •Функции
- •Прототип функции.
- •Определение функции.
- •Параметры функции
- •Передача массива в функцию
- •inline функции
- •Класс памяти
- •Автоматические переменные
- •Статические переменные
- •Регистровые переменные
- •Блочная структура
- •Примеры программ
- •Указатели на функции
- •Примеры программ
- •Рекурсия
- •Примеры программ
- •Аргументы в командной строке
- •Функции с переменным числом параметров
- •Вершина стека
- •Примеры программ
- •Сортировка
- •Пузырьковая сортировка.
- •Шейкер сортировка
- •Сортировка вставкой
- •Сортировка выбором
- •Метод Шелла
- •Метод Хора
- •Структуры
- •Указатели на структуры.
- •Структуры и функции
- •Примеры программ
- •Поля бит
- •Объединения
- •Переменные с изменяемой структурой
- •Организация списков и их обработка
- •Операции со списками при связном хранении
- •Стек
- •Построение обратной польской записи
- •Односвязный линейный список, очередь
- •Двусвязный линейный список
- •Циклический список, кольцо
- •Двусвязный циклический список
- •Примеры программ
- •Деревья
- •Файлы
- •Примеры программ
- •Литература
{s3->l=s1->l;
s1->l=ss->l;
ss->l=s1; |
|
} |
|
ss=ss->l; |
|
if(!s4) s4=s1; |
//новая вершина стека |
}
puts("Сортировка стека выполнена"); *s=s4;
}
Построение обратной польской записи
Одной из главных причин, лежащих в основе появления языков программирования высокого уровня, явились вычислительные задачи, требующие больших объёмов рутинных вычислений. Поэтому к языкам программирования предъявлялись требования максимального приближения формы записи вычислений к естественному языку математики. В этой связи одной из первых областей системного программирования сформировалось исследование способов трансляции выражений. Здесь получены многочисленные результаты, однако наибольшее распространение получил метод трансляции с помощью обратной польской записи, которую предложил польский математик Я.Лукашевич.
Арифметическое выражение вида: (A+B)*(C+D)-E
в форме обратной польской записи будет иметь вид: AB+CD+*E-
Характерные особенности этого выражения состоят в следовании символов операций за символами операндов и в отсутствии скобок.
Обратная польская запись обладает рядом замечательных свойств, которые превращают ее в идеальный промежуточный язык при трансляции. Вопервых, вычисление выражения, записанного в обратной польской записи, может проводиться путем однократного просмотра, что является весьма удобным при генерации объектного кода программ. Во-вторых, получение обратной польской записи из исходного выражения может осуществляться весьма просто на основе простого алгоритма, предложенного Дейкстрой. Для этого вводится понятие стекового приоритета операций(табл. 10.):
Таблица 10.
Операция |
Приоритет |
( |
0 |
) |
1 |
+ - |
2 |
* / |
3 |
Просматривается исходная строка символов слева направо, операнды переписываются в выходную строку, а знаки операций заносятся в стек на
основе следующих соображений:
а) если стек пуст, то операция из исходной строки переписывается в стек; б) операция выталкивает из стека все операции с большим или равным
приоритетом в выходную строку; в) если очередной символ из исходной строки есть открывающая скобка,
то он проталкивается в стек; г) закрывающая круглая скобка выталкивает все операции из стека до
ближайшей открывающей скобки, сами скобки в выходную строку не переписываются, а уничтожают друг друга.
Рассмотрим текст программы, выполняющей рассмотренные выше
действия. |
|
|
#include<stdio.h> |
|
|
#include<stdlib.h> |
|
|
#include<conio.h> |
|
|
struct st |
// Описание элемента стека |
|
{ char c; |
|
|
st *next; |
|
|
}; |
|
|
st *push(st *,char); |
|
// занесение в стек |
char pop(st **); |
|
// чтение из стека |
int PRIOR(char); |
|
// возвращает приоритет операции |
void main(void) |
|
|
{ |
|
|
st *OPR=NULL; |
|
// стек операций пуст |
char in[80],out[80]; |
// входная и выходная строки |
|
int k,point; |
|
|
do |
|
|
{puts("Введите выражение(в конце '='):"); fflush(stdin);
gets(in); // ввод арифметического выражения k=point=0;
while(in[k]!='\0' && in[k]!='=') // пока не дойдем до '='
{ if(in[k]==')') |
// если очередной символ - ')' |
|
{ while((OPR->c)!='(') |
// то удаляем из стека в |
|
|
out[point++]=pop(&OPR); |
// выходную строку все знаки операций |
|
|
// до открывающей скобки |
} |
pop(&OPR); // Удаляем из стека открывающую скобку |
|
|
|
|
if(in[k]>='a' && in[k]<='z') |
// если символ - буква ,то |
|
out[point++]=in[k]; |
// заносим её в выходную строку |
|
if(in[k]=='(') |
// если очередной символ - '(' ,то |
|
OPR=push(OPR,'('); |
// заносим её в стек |
|
if(in[k]=='+' || in[k]=='-' || in[k]=='/' || in[k]=='*') |
||
{ |
// Если следующий символ - знак операции ,то все на- |
//ходящиеся в стеке операции с большим или равным
//приоритетом переписываются в выходную строку while((OPR!=NULL)&&(PRIOR(OPR->c)>=PRIOR(in[k]))) out[point++]=pop(&OPR);
OPR=push(OPR,in[k]); // запись в стек новой операцию
} |
|
|
k++; |
// переход к следующему символу входной строки |
|
} |
|
|
while(OPR!=NULL) |
// после рассмотрения всего выражения |
|
out[point++]=pop(&OPR); // перезапись операции |
||
out[point]='\0'; |
// из стека в выходную строку |
|
printf("\n%s\n",out); |
// и печатаем её |
fflush(stdin); puts("\nПовторить(y/n)?");
} while(getch()!='n');
}
//push записывает в стек символ a, возвращает
//указатель на новую вершину стека
st *push(st *head,char a)
{st *PTR;
if(!(PTR=(st*) malloc(sizeof(*PTR))))
{puts("Нет памяти"); exit(-1);} PTR->c=a; //
PTR->next=head; |
// |
return PTR; |
// PTR -новая вершина стека |
}
//pop удаляет символ с вершины стека. Возвращает
//удаляемый символ. Изменяет указатель на вершину стека char pop(st **head)
{st *PTR; char a;
if(!(*head)) return '\0';//Если стек пуст, возвращаем \0
PTR=*head; |
// в PTR - адрес вершины стека |
a=PTR->c; |
|
*head=PTR->next; |
// Изменяем адрес вершины стека |
free(PTR); |
// Освобождение памяти |
return a; |
// Возврат символа с вершины стека |
}
// Функция PRIOR возвращает приоритет арифм. операции int PRIOR(char a)
{switch(a)
{case '*':case '/':return 3; case '-':case '+':return 2; case '(':return 1;
} return 0;
}
Односвязный линейный список, очередь
Односвязный список (очередь) - такая упорядоченная структура данных, которые могут удаляться с одного ее конца (начало очереди ), а добавляются в другой ее конец (конец очереди).
Очередь организована по принципу FIFO - ”первый вошел - первый вышел”. Для очереди определены следующие операции:
-проверка очереди на пустоту;
-добавление нового элемента в конец (хвост) очереди;
-удаление элемента из начала (головы) очереди;
-поиск и модификация элемента в очереди.
-упорядочивание элементов очереди.
Ниже приводится текст программы, иллюстрирующий работу с однонаправленной очередью.
#include <stdio.h> #include <alloc.h> #include <conio.h> #include <string.h> struct zap
{char inf[50]; zap *nx;
};
void add(zap **); void del(zap **);
void del_any(zap **,char *); void see(zap *);
void sort(zap **);
main()
{zap *h,*t; char l,*st;
st=(char *)malloc(10); h=NULL;
clrscr();
while(1)
{ puts("вид операции: 1-создать очередь");
puts(" |
2-вывод содержимого очереди"); |
puts(" |
3-удаление элемента из очереди"); |
puts(" |
4-удаление любого элемента из очереди"); |
puts(" |
5-сортировка очереди"); |
puts(" |
0-окончить"); |
fflush(stdin); |
|
switch(getch())
{case '1': add(&h); break; case '2': see(h); break;
case '3': if(h) del(&h); break; case '4': if(h)
{fflush(stdin);
puts("Введите информацию для удаления "); gets(st);
del_any(&h,st); } break;
case '5': if (h) sort(&h); break; case '0': return;
default: printf("Ошибка, повторите \n");
}
}
}
// функция создания очереди void add(zap **h)
{zap *n;
puts("Создание очереди \n"); do
{if(!(n=(zap *) calloc(1,sizeof(zap))))
{puts("Нет свободной памяти");
return;
}
puts("Введите информацию в inf"); scanf("%s",n->inf);
if (!*h) |
// очередь еще не создана |
*h=n; |
// хвост очереди |
else |
|
{ n->nx=*h; |
// очередной элемент очереди |
*h=n; |
// передвигаем указатель на хвост |
}
puts("Продолжить (y/n): "); fflush(stdin);
} while(getch()=='y');
}
// функция вывода содержимого очереди void see(zap *h)
{ puts("Вывод содержимого очереди \n"); if (!h)
{puts("Очередь пуста"); return;
}
do
{printf("%s\n",h->inf); h=h->nx;
}while(h);
return;
}
// функция удаления первого элемента очереди void del(zap **h)
{ zap *f,*pr; |
|
if (!(*h)->nx) |
// в очереди только один элемент |
{ free(*h); |
|
*h=NULL; |
// очередь пуста |
return; |
|
}
pr=*h; while(pr->nx->nx) pr=pr->nx;
free(pr->nx); // удаление первого элемента из очереди pr->nx=NULL;
return;
}
// функция удаления любого элемента очереди void del_any(zap **h,char *st)
{zap *f,*pr;
if (!(*h)->nx && // в очереди только один элемент
(!strcmp((*h)->inf,st) || *st=='\0'))
{ free(*h);
*h=NULL; // очередь пуста return;
}
pr=*h;
f=pr; // далее f предыдущий к pr элемент while(pr)
{if (!strcmp(pr->inf,st)) // найден элемент со строкой st
{if (pr==*h) {*h=pr->nx; free(pr); f=pr=*h;} else
{ f->nx=pr->nx; |
// обходим элемент pr |
free(pr); |
// удаляем элемент pr очереди |
pr=f->nx; |
// выбор следующего элемента очереди pr |
} |
|
}
else {f=pr; pr=pr->nx;} // переход к следующему элементу
}