Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

ПЕРОВА САБАЕВА

.pdf
Скачиваний:
190
Добавлен:
11.03.2016
Размер:
1.4 Mб
Скачать

5.4. Быстрая сортировка

Быстрая сортировка, хоть и была разработана более 40 лет назад, является наиболее широко применяемым и одним их самых эффективных алгоритмов сортировки. Метод основан на принципе «разделяй-и-властвуй».

Общая схема быстрой сортировки такова: из массива выбирается некоторый опорный элемент a[i], запускается процедура разделения массива, которая перемещает все ключи, меньшие, либо равные a[i], влево от него, а все ключи, большие, либо равные a[i] – вправо (рис. 5.5). Теперь массив состоит из двух подмножеств, причем левое подмножество меньше, либо равно правого:

Рис. 5.5. Разделение массива на два подмассива

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

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

1.На входе задаем массив a[0] ... a[N] и опорный элемент p, по которому будет производиться разделение.

2.Введем два указателя: i и j (рис. 5.6). В начале алгоритма они указывают, соответственно, на левый и правый концы последовательности.

3.Будем двигать указатель i с шагом в 1 элемент по направлению к концу массива, пока не будет найден элемент a[i] >= p.

4.Аналогичным образом начнем двигать указатель j от конца массива к началу, пока не будет найден a[j] <= p.

5.Если i <= j, меняем a[i] и a[j] местами и продолжаем двигать i, j по тем же правилам.

6.Повторяем шаг 3, пока i <= j.

Рассмотрим работу процедуры быстрой сортировки для массива a[0]...a[6]

иопорного элемента p = a[3] (рис. 5.6).

43

Рис. 5.6. Иллюстрация алгоритма быстрой сортировки

Теперь массив разделен на две части: все элементы левой меньше либо равны p, все элементы правой – больше, либо равны p. Разделение завершено.

Листинг 5.4. Задать исходный массив х[N]. Количество элементов массива N и значения элементов массива ввести с клавиатуры. Применяя алгоритм быстрой сортировки, отсортировать исходный массив в порядке возрастания его элементов. Вывести на экран дисплея исходный и отсортированный массивы.

//L5_4.cpp

#include <iostream> using namespace std;

void qs(int* s_arr, int first, int last); // Прототип функции qs() int main()

{

setlocale(LC_CTYPE,"russian"); int i, n, *x;

do

{

cout<<"Введите число элементов массива "; cin>>n;

}while (n<=1); x=new int[n]; for(i=0; i<n; i++)

{

cout<<"Введите x("<<i+1<<")=";

44

cin>>x[i];

}

cout<<"Исходный массив\n"; for(i=0; i<n; i++)

cout<<x[i]<<" "; cout<<endl; qs(x,0,n-1);

cout<<"Полученный массив\n"; for(i=0;i<n;i++)

cout<<x[i]<<" "; cout<<endl;

return 0;

}

void qs(int* s_arr, int first, int last)

{

int i = first, j = last, x = s_arr[(first + last) / 2];

do {

while (s_arr[i] < x) i++; while (s_arr[j] > x) j--;

if(i <= j) {

if (i < j) swap(s_arr[i], s_arr[j]); i++;

j--;

}

} while (i <= j);

if (i < last) qs(s_arr, i, last);

if (first < j) qs(s_arr, first, j);

}

На рис. 5.7 приведен результат выполнения программы листинга 5.4.

45

Рис. 5.7. Результат работы программы листинга 5.4

УПРАЖНЕНИЯ

1.Упорядочить массив из n числовых элементов методом пузырька по возрастанию.

2.Упорядочить массив из n числовых элементов методом пузырька по убыванию.

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

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

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

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

7.Упорядочить четные элементы массива из n числовых элементов методом пузырька по возрастанию.

8.Упорядочить нечетные элементы массива из n числовых элементов методом пузырька по убыванию.

9.Упорядочить массив из n символов методом пузырька в алфавитном по-

рядке.

10.Упорядочить массив из n символов методом быстрой сортировки в алфавитном порядке.

11.Упорядочить массив из n символов методом сортировки вставкой в алфавитном порядке.

12.Упорядочить массив из n числовых элементов методом пузырька по возрастанию числа их делителей.

46

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

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

15.Задан список студентов с указанием их среднего балла за текущую сессию. Упорядочить список студентов по убыванию балла, а в случае равенства баллов, упорядочить список студентов в алфавитном порядке.

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

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

18.Упорядочить массив из n элементов следующим образом: положительные элементы по возрастанию, а отрицательные – по убыванию.

19.Заданы два упорядоченных массива из n и m элементов. Построить массив размерностью n+m с той же упорядоченностью.

20.Заданы два упорядоченных массива из n и m элементов. Построить массив размерностью n+m с противоположной упорядоченностью.

21.Упорядочить массив из n элементов следующим образом: сначала положительные элементы по убыванию, а затем отрицательные элементы по возрастанию.

22.Задан список финалистов лыжного соревнования с указанием фамилии и результата в минутах. Упорядочить список по возрастанию результатов, а в случае равенства результатов, указать фамилии спортсменов в алфавитном порядке.

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

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

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

47

ГЛАВА 6. РАБОТА С ФАЙЛАМИ. ПОСТРОЕНИЕ МАССИВОВ БЕЗ ПОВТОРЕНИЙ

6.1. Работа с файлами

Файл – это поименованная часть памяти диска, которая содержит некоторый набор записей [32]. В С++ средства для доступа к файлам объявлены в заголовочном файле fstream, который необходимо включить в программный код при работе с файлами. Для обозначения источника либо приемника данных применяется термин «поток». Потоки для работы с файлами создаются как объекты следующих классов:

ofstream – для вывода (записи) данных в файл;

ifstream – для ввода (чтения) данных из файла;

fstream – для чтения и записи данных (двунаправленный обмен).

Имя файла задается либо при создании объекта, либо при использовании метода open(). В качестве примера рассмотрим пример с двойной сортировкой (см. листинг 5.2), но информацию нужно получать из файла.

Листинг 6.1. В текстовом файле «input.txt» записана следующая информация: число студентов, а затем идут парой фамилия и номер группы (рис. 6.1). Необходимо преобразовать этот список так, чтобы он оказался отсортированным по группам и внутри каждой группы в алфавитном порядке. Полученный список вывести на экран дисплея и записать в файл.

//L6_1.cpp

 

 

#include <string.h>

 

 

#include <fstream>

 

 

#include <iostream>

 

 

using namespace std;

 

 

int main( )

 

 

{

 

 

setlocale(LC_CTYPE,"russian");

 

int n,i,*grup,f,k=0,gtmp;

 

 

char**name,*ntmp,fam[30];

 

 

fstream ff("input.txt");

//Соэдание объекта ff и открытие файла

ff>>n;

 

 

name=new char*[n];

//Выделение памяти для указателей,

 

 

//связанных с фамилией студентов

.

grup=new int[n];

//Выделение памяти под номера групп

 

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

 

 

{

 

 

ff>>fam>>grup[i];

 

 

 

48

 

name[i]=strdup(fam);

//Заполняется фамилия i-го студента

}

 

ff.close();

//Закрытие файла

. . .

//См. листинг 5.2

ff.open("input.txt",ios::app); //Открытие файла для пополнения ff<<"\nПолученный список\n";

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

{

ff.width(6); ff<<grup[i]<<" "; ff<<name[i]<<'\n';

}

ff.close(); //Закрытие файла return 0;

}

Содержимое файла “input.txt”

Рис. 6.1. Информация, находящаяся в файле «input.txt»

На рис. 6.2 приведен результат выполнения программы листинга 6.1.

Рис. 6.2. Результат работы программы листинга 6.1

49

6.2. Построение массивов без повторений

Предположим, что в файле «input.txt» записана информация, содержащая количество студентов в списке, фамилию студента, название предмета и оценку по этому предмету. Фамилии студентов и названия предметов могут повторяться (рис. 6.3). Необходимо сформировать список студентов и вычислить общее количество пропусков занятий для каждого из них, а также общее число пропусков занятий по каждому предмету. Таким образом, для каждого студента и каждого предмета нужно суммировать число пропусков занятий.

Содержимое файла “input.txt”

Рис. 6.3. Информация, находящаяся в файле «input.txt»

Листинг 6.2. Сформировать список из неповторяющихся фамилий и список из неповторяющихся предметов. При вводе проверять, если среди раннее введенных фамилий (рис. 6.3) вводимые фамилии и предметы. Если их нет, то вводится новая запись, а если они уже есть, то добавляется число прогулов в уже существующую запись.

//L6_2.cpp

#include <string.h> #include <fstream> #include <iostream> using namespace std; int main( )

{

setlocale(LC_CTYPE,"russian");

int n,i,j,*nname,*nsubject,mn=0,ms=0,f,aut;

50

char**name,**subject,fam[30],sb[30];

fstream ff("input.txt");

 

ff>>n;

//Читаем число записей

name=new char*[n];

//Выделяем память под указатели

 

//на фамилии.

subject=new char*[n];

//Выделяем память под указатели

 

//на названия предметов.

nname=new int[n];

//Выделяем память под количество

 

//пропусков длякаждого студента.

nsubject=new int[n];

//Выделяем память под количество

 

//под каждый предмет.

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

 

{

 

ff>>fam;

//Ввод фамилии студента

ff>>sb;

//Ввод предмета

ff>>aut;

//Ввод числа прогулов студента по этому

 

//предмету.

for(j=0;j<mn;j++)

if(strcmp(name[j],fam)==0)

break;

if(j>=mn)

{

name[mn]=strdup(fam);

nname[mn++]=aut;

}

else

nname[j]+=aut;

for(j=0;j<ms;j++)

if(strcmp(subject[j],sb)==0)

break;

if(j>=ms)

{

subject[ms]=strdup(sb);

nsubject[ms++]=aut;

}

else

nsubject[j]+=aut;

}

ff.close();

cout<<"\nПолученные списки\nСТУДЕНТЫ\n\n"; for(i=0;i<mn;i++)

{

cout.width(10);

cout<<name[i];

51

cout.width(5);

cout<<nname[i]<<'\n';

}

cout<<"\nПРЕДМЕТЫ\n\n"; for(i=0;i<ms;i++)

{

cout.width(10);

cout<<subject[i];

cout.width(5);

cout<<nsubject[i]<<'\n';

}

cout<<'\n';

ff.open("input.txt",ios::app); ff<<"\nПолученные списки\nСТУДЕНТЫ\n\n"; for(i=0;i<mn;i++)

{

ff.width(10);

ff<<name[i];

ff.width(5);

ff<<nname[i]<<'\n';

}

ff<<"\nПРЕДМЕТЫ\n\n"; for(i=0;i<ms;i++)

{

ff.width(10);

ff<<subject[i];

ff.width(5);

ff<<nsubject[i]<<'\n';

}

ff<<'\n';

ff.close(); return 0;

}

Результат работы программы листинга 6.2 приведен на рис. 6.4.

52