Компания ALT Linux
Опубликован: 07.03.2015 | Доступ: свободный | Студентов: 2134 / 486 | Длительность: 24:14:00
Лекция 5:

Массивы

5.4.6 Сортировка элементов в массиве

Сортировка представляет собой процесс упорядочения элементов в массиве в порядке возрастания или убывания их значений. Например, массив Y из n элементов будет отсортирован в порядке возрастания значений его элементов, если

Y [0] < Y [1] < ... < Y [n - 1],

и в порядке убывания, если

Y [0] > Y [1] > ... > Y [n - 1].

Существует большое количество алгоритмов сортировки, но все они базируются на трёх основных:

  • сортировка обменом;
  • сортировка выбором;
  • сортировка вставкой.

Представим, что нам необходимо разложить по порядку карты в колоде. Для сортировки карт обменом можно разложить карты на столе лицевой стороной вверх и менять местами те карты, которые расположены в неправильном порядке, делая это до тех пор, пока колода карт не станет упорядоченной.

Для сортировки выбором из разложенных на столе карт выбирают самую младшую (старшую) карту и держат её в руках. Затем из оставшихся карт вновь выбирают наименьшую (наибольшую) по значению карту и помещают её позади той карты, которая была выбрана первой. Этот процесс повторяется до тех пор, пока вся колода не окажется в руках. Поскольку каждый раз выбирается наименьшая (наибольшая) по значению карта из оставшихся на столе карт, по завершению такого процесса карты будут отсортированы по возрастанию (убыванию).

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

Итак, решим следующую задачу. Задан массив Y из n целых чисел. Расположить элементы массива в порядке возрастания их значений.

5.4.6.1 Сортировка методом "пузырька"

Сортировка пузырьковым методом является наиболее известной. Её популярность объясняется запоминающимся названием, которое происходит из-за подобия процессу движения пузырьков в резервуаре с водой, когда каждый пузырёк находит свой собственный уровень, и простотой алгоритма. Сортировка методом "пузырька" использует метод обменной сортировки и основана на выполнении в цикле операций сравнения и при необходимости обмена соседних элементов. Рассмотрим алгоритм пузырьковой сортировки более подробно.

Сравним нулевой элемент массива с первым, если нулевой окажется больше первого, то поменяем их местами. Те же действия выполним для первого и второго, второго и третьего, i–го и (i + 1)–го, предпоследнего и последнего элементов. В результате этих действий самый большой элемент станет на последнее (n-1)-е место. Теперь повторим данный алгоритм сначала, но последний (n - 1)-й элемент рассматривать не будем, так как он уже занял своё место. После проведения данной операции самый большой элемент оставшегося массива станет на (n-2)-е место. Так повторяем до тех пор, пока не упорядочим весь массив.

В табл. 5.4 представлен процесс упорядочивания элементов в массиве.

Таблица 5.4. Процесс упорядочивания элементов
Номер элемента 0 1 2 3 4
Исходный массив 7 3 5 4 2
Первый просмотр 3 5 4 2 7
Второй просмотр 3 4 2 5 7
Третий просмотр 3 2 4 5 7
Четвёртый просмотр 2 3 4 5 7

Нетрудно заметить, что для преобразования массива, состоящего из n элементов, необходимо просмотреть его n-раз, каждый раз уменьшая диапазон просмотра на один элемент. Блок–схема описанного алгоритма приведена на рис. 5.13.

Сортировка массива пузырьковым методом

Рис. 5.13. Сортировка массива пузырьковым методом

Обратите внимание на то, что для перестановки элементов (рис. 5.13, блок 4) используется буферная переменная b, в которой временно хранится значение элемента, подлежащего замене. Текст программы, сортирующей элементы в массиве по возрастанию методом "пузырька", приведён далее.

#include <iostream>
using namespace std;
int main ( )
{
	int n, i, b, j;
	cout<<" n = "; cin>>n;
	float y [ n ];
	for ( i =0; i<n; i++) //Ввод массива.
	{
		cout<<" \n Y [ "<<i<<" ]= ";
		cin>>y [ i ];
	}
	for ( j =1; j<n; j++) //Упорядочивание элементов в массиве по возрастанию их значений.
		for ( i =0; i<n-j; i++)
		if ( y [ i ]>y [ i +1 ]) //Если текущий элемент больше следующего
		{
			b=y [ i ]; //Сохранить значение текущего элемента
			y [ i ]=y [ i + 1 ]; //Заменить текущий элемент следующим
			y [ i +1]=b; //Заменить следующий элемент на сохранённый в b
		}
	for ( i =0; i<n; i++) cout<<y [ i ]<<" \t "; //Вывод упорядоченного массива
	return 0;
}

Для перестановки элементов в массиве по убыванию их значений необходимо в программе и блок-схеме при сравнении элементов массива заменить знак ">" на "<".

Однако, в этом и во всех далее рассмотренных алгоритмах не учитывается то факт, что на каком-то этапе (или даже в начале) массив уже может оказаться отсортированным. При большом количестве элементов (сотни и даже тысячи чисел) на сортировку "вхолостую" массива тратится достаточно много времени. Ниже приведены тексты двух вариантов программы сортировки по убыванию методом пузырька, в которых алгоритм прерывается, если массив уже отсортирован.

Вариант 1.

#include <iostream>
using namespace std;
int main ( int argc, char **argv )
{
	int n, i, b, j;
	bool pr;
	cout<<" n = "; cin>>n;
	float y [ n ];
	for ( i =0; i<n; i++) //Ввод массива.
	{
		cout<<" \n Y [ "<<i<<" ]= ";
		cin>>y [ i ];
	}
	for ( j =1; j<n; j++) //Упорядочивание элементов массива по убыванию их значений.
	{
		for ( pr=false, i =0; i<n-j; i++) //Предполагаем, что массив уже отсортирован
		// ( pr=false ) .
		if ( y [ i ]<y [ i +1 ]) //Если текущий элемент меньше следующего
		{
			b=y [ i ]; //Сохранить значение текущего элемента
			y [ i ]=y [ i + 1 ]; //Заменить текущий элемент следующим
			y [ i +1]=b; //Заменить следующий элемент текущим
			pr=true; //Если элемент менялись местами, массив ещё не отсортирован (pr=true);
		}
		cout<<" j = "<<j<<endl;
		//Если на j-м шаге соседние элементы не менялись, то массив уже отсортирован,
		if ( ! pr ) break; //повторять смысла нет;
	}
	for ( i =0; i<n; i++) cout<<y [ i ]<<" \t "; //Вывод упорядоченного массива
	return 0;
}

Вариант 2.

#include <iostream>
using namespace std;
int main ( int argc, char **argv )
{
	int n, i, b, j;
	bool pr=true;
	cout<<" n = "; cin>>n;
	float y [ n ];
	for ( i =0; i<n; i++) //Ввод массива.
	{
		cout<<" \n Y [ "<<i<<" ]= ";
		cin>>y [ i ];
	}
	for ( j =1; pr; j++) //Упорядочивание элементов массива по убыванию их значений.
	{ //Вход в цикл, если массив не отсортирован (pr=true).
		for ( pr=false, i =0; i<n-j; i++) //Предполагаем, что массив уже отсортирован
		// ( pr=false ) .
			if ( y [ i ]<y [ i +1 ]) //Если текущий элемент меньше следующего
			{
				b=y [ i ]; //Сохранить значение текущего элемента
				y [ i ]=y [ i + 1 ]; //Заменить текущий элемент следующим
				y [ i +1]=b; //Заменить следующий элемент текущим
				pr=true; //Элементы менялись местами, массив ещё не отсортирован ( pr=true )
			}
	}
	for ( i =0; i<n; i++) cout<<y [ i ]<<" \t "; //Вывод упорядоченного массива
	return 0;
}
Сергей Радыгин
Сергей Радыгин

Символы кириллицы выводит некорректно. Как сделать чтобы выводился читабельный текст на русском языке?

Тип приложения - не Qt,

Qt Creator 4.5.0 основан на Qt 5.10.0. Win7.

 

Юрий Герко
Юрий Герко

Кому удалось собрать пример из раздела 13.2 Компоновка (Layouts)? Если создавать проект по изложенному алгоритму, автоматически не создается  файл mainwindow.cpp. Если создавать этот файл вручную и добавлять в проект, сборка не получается - компилятор сообщает об отсутствии класса MainWindow. Как правильно выполнить пример?