Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Рацеев С.М. Программирование на языке Си.pdf
Скачиваний:
369
Добавлен:
23.03.2016
Размер:
1.65 Mб
Скачать

Приложение 5. СОРТИРОВКА С УСЛОВИЕМ

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

В этом случае можно использовать алгоритмы сортировок из приложения 2 с некоторыми модификациями, не меняющими принцип самих алгоритмов. Общая схема является такой. Пусть a – некоторый массив размера n, в котором требуется упорядочить элементы со свойством Q. Обозначим через m количество таких элементов массива a (со свойством Q), при этом очевидно, что 0≤ m n. Введем дополнительный (динамический) целочисленный массив индексов ind размера m, в который запишем индексы всех элементов массива a, обладающих свойством Q.

Например, пусть массив a состоит из элементов 20, -10, 30, - 20, 10 и требуется упорядочить только положительные элементы (то есть свойство Q заключается в том, чтобы быть положительным числом и после упорядочивания по возрастанию только положительных чисел массив a должен принять такой вид : 10, -10, 20, -20, 30). Тогда массив индексов ind будет состоять из трех элементов

(m=3) и иметь такой вид: ind[0] = 0, ind[1] = 2, ind[2] = 4.

После того, как массив ind сформирован, можно использовать сортировки из приложения 2, в которых упорядочиваются ровно m элементов массива a с использованием такой индексации:

a[ind[0]], a[ind[1]],…,a[ind[m-1]].

1. Сортировка с условием на базе пузырьковой сортировки

#define N 10

/* подсчет количества элементов, обладающих свойством Q */ int Count(const double *a, const int n)

{

int i, count;

for(i = count = 0; i < n; i++)

329

if (Q(a[i])) count++; return count;

}

/* сортировка пузырьком элементов со свойством Q */ int BubbleSort(double *a, const int n)

{

int i, j, r, flag, *ind, m; double buf;

/* вычисляем количество элементов со свойством Q: */ m = Count(a, n);

ind = (int *)malloc(m * sizeof(int)); /* заполняем массив ind: */

for(i = j = 0; i < n; i++) if (Q(a[i]))

ind[j++] = i;

/* сортируем элементы со свойством Q */ r = m;

do

{

flag = 0;

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

if (a[ind[i]] < a[ind[i-1]])

{

buf = a[ind[i]]; a[ind[i]] = a[ind[i-1]]; a[ind[i-1]] = buf; flag = 1;

}

r--; }while(flag); free(ind);

return m; /* возвращаем количество элементов со свойством Q */

}

int main()

330

{

double a[N];

…/* заполняем массив a */

/* сортируем элементы массива a со свойством Q: */ BubbleSort(a, N);

}

2. Сортировка с условием на базе быстрой сортировки

#define N 10

/* подсчет количества элементов, обладающих свойством Q */ int Count(const double *a, const int n)

{

int i, count;

for(i = count = 0; i < n; i++) if (Q(a[i]))

count++; return count;

}

/* быстрая сортировка массива a через массив ind */ void QuickSort (double *a, int *ind, int left, int right)

{

int i, j; double x, buf; i = left;

j = right;

x = a[ind[(left + right)/2]]; do

{

while (a[ind[i]] < x) i++;

while (x < a[ind[j]]) j--;

if (i <= j)

331

{

buf = a[ind[i]]; a[ind[i]] = a[ind[j]]; a[ind[j]] = buf; i++;

j--;

}

} while( i <= j);

if (left < j) QuickSort (a, ind, left, j); if (right > i) QuickSort (a, ind, i, right);

}

int main()

{

double a[N];

int i, j, m, *ind = NULL; …/* заполняем массив a */

/* вычисляем количество элементов со свойством Q: */ m = Count(a, N);

if (m > 0)

{

ind = (int *)malloc(m * sizeof(int)); for(i = j = 0; i < N; i++)

if (Q(a[i])) ind[j++] = i;

QuickSort(a, ind, 0, m - 1); free(ind);

}

return 0;

}

3.Сортировка с условием двоичных файлов

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

332

не все записи в файле по какому-либо полю, а только те из них, которые обладают некоторым свойством Q, а остальные записи должны остаться на своем месте. Например, может потребоваться отсортировать по году рождения самых высокооплачиваемых работников. Отсортируем все записи в файле по году рождения, которые обладают свойством Q. Опять же, для ускорения алгоритма используем динамический массив, в который выгрузим весь файл. В качестве алгоритма сортировки используем пузырьковую сортировку, которая легко может быть трансформирована в любой другой алгоритм.

#include<stdio.h> struct WORKER

{

char name[20]; int year;

float earnings; };

/* размер файла в байтах */ long Size(char *fileName)

{

FILE *f; long n;

if ((f = fopen(fileName, "rb")) == NULL) return -1;

fseek(f, 0, SEEK_END); n = ftell(f);

fclose(f); return n;

}

/* количество записей в файле, обладающих свойством Q */ long Count(struct WORKER *a, long n)

{

long i, count = 0; for(i = 0; i < n; i++)

333

if(Q(a[i]))

count++; return count;

}

/* сортировка файла с условием на основе пузырьковой сортировки */

int SortFile(char *fileName)

{

FILE *f;

struct WORKER *a; /* динамический массив структур */ struct WORKER buf;

long n, m, i, j, r;

long *ind; /* динамический массив индексов */ int flag;

if ((f = fopen(fileName, "r+b")) == NULL) return 1;

/* вычисляем количество записей в файле */ n = Size(fileName)/sizeof(struct WORKER);

/* выделяем память для динамического массива a */

a = (struct WORKER *)malloc(n * sizeof(struct WORKER));

/* проверяем успешность выделения памяти и пытаемся выгрузить файл в массив */

if (a == NULL || fread(a, sizeof(struct WORKER), n, f) != n)

{

fclose(f); return 2;

}

/* вычисляем количество записей в файле, обладающих свойством Q */

m = Count(a, n);

/* выделяем память для динамического массива ind */ ind = (long *)malloc(m * sizeof(long));

/* проверяем успешность выделения памяти */ if (ind == NULL)

{

fclose(f);

334