Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лабы_по_проге_Берлин / Книги / учебное пособие ОАиП.pdf
Скачиваний:
49
Добавлен:
11.02.2015
Размер:
947 Кб
Скачать

int sr = ms[(l+r)/2];

// срединный элемент

i = l;

j = r;

// начальные значения границ массива

do

 

 

{ while(ms[i] < sr) i++;

// ищем слева элемент больше среднего

while(ms[j] > sr)

j--; // ищем справа элемент меньше среднего

if(i <= j)

// если левая граница не прошла за правую

{ k = ms[i];

// перестановка элементов

ms[i] = ms[j];

 

ms[j] = k;

 

i++;

j--;

// переходим к следующим элементам

}

 

 

} while(i <= j);

// пока границы не совпали

 

 

// массив разбит на два подмножества

if(i < r)

 

// если есть что-нибудь справа

hoar(ms,i,r);

// сортируем правый подмассив

if(j>l)

 

// если есть что-нибудь слева

hoar(ms,l,j);

// сортируем левый подмассив

}

Еще один вариант программы сортировки Хоора:

void hoor(int *a,int l,int r)

 

{ int i,las;

 

 

 

if(l>=r) return;

 

 

 

swap(a,l,(l+r)/2);

//

делящий эл-т переносится в a[l] (a[l]<->a[(l+r)/2])

las=l;

//

позиция последнего элемента большего

 

//

чем делящий

 

for(i=l+1;i<=r;i++)

//

деление [l,r] на [l,las-1] и [las+1,r]

if(a[i]<a[l]) swap(a,++las,i);

 

swap(a,l,las);

 

 

 

hoor(a,l,las-1);

//

сортировка для

[l, las-1]

hoor(a,las+1,r);

//

сортировка для

[las+1, r]

}

 

 

 

void swap(int *a,int i,int j)

{ int tmp; // функция замены i и j элементов в массиве a tmp=a[i];

a[i]=a[j];

a[j]=tmp;

}

Структуры

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

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

Примером использования структуры может служить, например, строка платежной ведомости. В ней должна содержаться информация о служащем: ФИО, адрес, табельный номер, зарплата и т.д.

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

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

struct [имя типа структуры]

{ тип элемента 1 имя элемента 1;

. . . . . . . . . . . . .

тип элемента n имя элемента n; }[имя переменной стр-ры];

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

Именем элемента структуры может быть любой идентификатор. Как и ранее, при описании нескольких идентификаторов одного типа в структуре они могут быть описаны через запятую. Имена элементов структуры (полей) могут совпадать с именами обычных переменных (не являющихся элементами структуры), так как они всегда различимы по контексту. Более того, одни и те же имена элементов могут встречаться в объявлениях различных структур.

Задание только типа не влечет выделения “под него” памяти компилятором. Описание типа структуры предоставляет компилятору

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

Определение переменной имеющей тип структура аналогично определению переменных рассмотренных ранее типов, например:

struct inform

 

{ char fam[30];

// фалилия

int god;

// год рождения

float stag;

// стаж работы

};

 

inform rab; // определение переменной rab типа struct inform

С синтаксической точки зрения эта запись аналогична записи вида:

char fam[30];

// фалилия

int god;

// год рождения

float stag;

// стаж работы

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

Описание шаблона и определение структурной переменной могут быть совмещены в одной записи, например:

struct book

{ char title [20]; char autor [30]; int page;

} bk1, bk2, *ptr_bk=&bk1;

Вэтом случае если имя структуры (тег) book более ни где не используется, то оно может быть опущено.

Ранее мы уже рассматривали процедуру инициализации переменных и массивов. Как и обычные переменные, элементы, входящие в состав структуры (определяющие структурную переменную), могут быть инициализированы. При этом можно инициализировать, как только все элементы, определяющие структурную переменную при ее декларировании:

struct st{char c; int i1,i2}; struct st a={‘a’,105,25};

так и некоторые из них в процессе работы с ними: a.c=‘a’;

a.i2=25;

При выполнении инициализации структурных переменных необходимо следовать некоторым правилам:

-присваиваемые значения должны совпадать по типу с соответствующими полями структуры;

-можно объявлять меньшее количество присваиваемых значений, чем количество полей. Компилятор присвоит нули остальным полям структуры;

-список инициализации последовательно присваивает значения полям

структуры вложенных структур и массивов. Например:

struct comp

{char nazv[20]; float speed;

int cena;

} cp[3]={ {“Celeron”,0.6,525}, {“Duron”,1.0,547}, {“Atlon”,1.4,610}

};

Доступ к элементам структуры. Доступ к полям структуры осуществляется с помощью оператора «точка» - при непосредственной работе со структурой и "->" - при использовании указателей на структуру. Возможны три вида спецификации доступа к элементам структуры:

имя_переменной_структуры . имя_поля; имя_указателя -> имя_поля; (*имя_указателя) . имя_поля; например:

struct str

{int i; float j;

} st1, st2[3],*st3,*st4[5];

а) Прямой доступ к элементу (оператор “ .”) st1.i=12;

st2[1].j= .52;

б) Доступ по указателю (оператор “->”). st3->i=12;

(st4+1)->j=1.23; *(st3).j=23; *(st4[2]).i=123;

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

шаблона:

 

struct str

 

{ char pole_1;

 

double pole_2;

 

str pole_3;

// ошибка

};

 

Однако структура может включать в себя элементы, являющиеся

указателями на шаблон этой же структуры:

struct str

 

{ char pole_1;

 

double pole_2;

 

str *pole_3;

// верно

};

Так же как и массив, структура может быть введена поэлементно. Например, для описанной выше структуры st

gets(a.c);

scanf(”% d % f”, &a.i1, &a.i2);

Как отмечалось выше, структуры могут быть вложены дуг в друга: struct FIO {char F[15], I[10], O[12]} f;

struct rab { struct FIO fio; int tab; float zarpl} rb;

Структура rab содержит структуру FIO. Доступ к элементам структуры FIO и rab осуществляется следующим образом:

f. F=''Петров''; f.I ='' '';

rb.fio.O= "Иванович'';

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

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

#include <stdio.h>

struct book

 

{ char avt[10];

 

int izd;

 

} st1,st2;

 

void main(void)

 

{ gets(st1.avt);

// ввод структуры st1

scanf("%d",&st1.izd);

st2=st1;

// копия всех полей структуры st1 в st2

}

Необходимо отметить, что копирование структур (st2=st1) допустимо, только если st1 и st2 являются структурными переменными соответствующими одному структурному типу.

Структуры нельзя сравнивать, то есть выражение if (st1==st2) неверно. Сравнение структур требуется выполнять поэлементно.

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