Главная
>>
Каталог задач
>>
Сортировка
>>
Сортировка Вставками
>>
Сортировка вставкой
Aвтор:
this
Дата:
17.08.2002
Просмотров: 113903
реализации(C++: 3шт...)
+добавить
Коротко
Проходимся по всем элементам и вставляем каждый текущий элемент на свое место в уже отсортированную последовательность предыдущих просмотренных элементов. В самом начале считаем первый элемент уже отсортированной последовательностью и далее проходимся по всем остальным элементам.
В результате получим:
for i = 1 to n
/* инвариант: элементы x[0..i-1] -
уже отсортированы */
/* ставим x[i] в правильную позицию */
insert x[i] in x[0..i-1]
Подробно
По книге Джона Бентли:
"Жемчужины программирования"
"...Большинство картежников, сами того не сознавая, пользуются именно таким методом сортировки для упорядочения пришедших им карт. Когда игрок получает очередную карту, все предыдущие уже отсортированы, поэтому он просто вставляет ее в нужное место. Для сортировки массива х[n] в порядке возрастания начинать следует с первого элемента, считая его отсортированной подпоследовательностью х[0..0]. Затем нужно вставлять элементы х[1], ..., х[n-1] в правильные позиции, как это делается в приведенном ниже псевдокоде:
for i = 1 to n
/* инвариант: элементы x[0..i-1] -
уже отсортированы */
/* ставим x[i] в правильную позицию */
insert x[i] in x[0..i-1]
Последовательность сортировки массива из 4-х элементов иллюстрируется ниже. Символ "|" - показывает текущее значение переменной i; елементы слева от этого символа уже отсортированы, справа - нет.
3 | 1 4 2
1 3 | 4 2
1 3 4 | 2
1 2 3 4 |
Вставка элемента в нужную позицию производится циклом, в котором элементы перебираются справа налево, а в переменной j хранится индекс очередного вставляемого элемента. В цикле текущий элемент переставляется местами с предыдущим, если этот предыдущий элемент существует (то есть j>0) и текущий элемент еще не установлен в нужное положение (он и предыдущий элементы находятся в неправильном порядке). Итак, получившаяся программа сортировки примет вид:
for i = 1 to n
for (j = i; j > 0 && x[j-1] > x[j]; j--)
swap(j-1, j);
В тех редких случаях, когда мне нужно написать свою собственную сортировку, я начинаю именно с этой функции, потому что она очень проста — всего три очевидные строки.
Программисты, стремящиеся к оптимизации, могут счесть нерациональным вызов функции swap из тела внутреннего цикла. Программу можно ускорить, раскрыв функцию явно, хотя многие оптимизирующие компиляторы способны делать это за нас. Заменим вызов функции нижеследующим кодом, в котором переменная t используется для обмена x[j] и x[j-l]:
t = x[j] x[j] = x[j-1] x[j-1] = t
На моем компьютере вторая версия сортировки работает примерно в три раза быстрее, чем первая.
После этого улучшения появляется возможность сделать следующий шаг. Поскольку переменной t несколько раз присваивается одно и то же значение (исходно находящееся в x[i]), мы можем вынести присваивания, относящиеся к этой переменной, за рамки внутреннего цикла, а также изменить вид сравнения, что даст третью версию сортировки вставкой:
for i = 1 to n
t = x[i]
for (j = i; j > 0 && x[j-1] > t; j--)
x[j] = x[j-1]
x[j] = t;
Эта программа сдвигает элементы вправо до тех пор, пока они превосходят значение t, а потом ставит t в правильную позицию. Эта функция из пяти строк чуть сложнее своих предшественников, но на моем компьютере она работает примерно на 15% быстрее, чем вторая версия той же сортировки.
Для случайного расположения элементов во входном массиве, как и в худшем случае (обратный порядок сортировки), время выполнения сортировки вставкой пропорционально O(n2). Таблица 11.1 содержит данные о времени выполнения трех программ, когда на вход подается n случайных целых чисел:
Третьей программе требуется несколько миллисекунд для сортировки n = 1000 целых чисел, треть секунды на n = 10 000 целых, и почти час на сортировку миллиона чисел. Скоро мы встретимся с программой, сортирующей миллион чисел меньше, чем за секунду. Если входной массив уже почти отсортирован, сортировка вставкой работает гораздо быстрее, поскольку все элементы сдвигаются лишь на небольшое расстояние. Алгоритм в разделе 11.3 данной главы(прим. ред-ра: т.е. алгоритм #2 задачи улучшение быстрой сортировки) основан именно на этом свойстве.
..."
Джон Бентли
Реализации:
C++(3)
+добавить
1)
Сортировка вставкой, версия #3 на C++, code #17[автор:this]
template<class T>
void InsertSort(T* x) {
T t;
int i, j;
for (i = 1; i < n; i++) {
t = x[i];
for (j = i; j > 0 && x[j-1] > t; j--) {
x[j] = x[j-1];
}
x[j] = t;
}
}
2)
Сортировка вставками на C++, code #604[аноним:bes]
//Сортировка вставками
void InsertMethod (int *mas,int n)
{
int temp;
int j;
for (int i=0;i<n;i++)
{
temp=mas[i];
j=i-1;
while ((j>=0)&&(mas[j]>temp))
{
mas[j+1]=mas[j];
j=j-1;
mas[j+1]=temp;
}
}
}
3)
работа fgets на C++, code #633[аноним:Ванюшка]
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include <tchar.h>
#include <iostream.h>
#include <stdio.h>
#include <fstream.h>
#include <stdlib.h>
//---------------------------------------------------------------------------
#pragma argsused
int _tmain(int argc, _TCHAR* argv[])
{
//открываем файл
FILE *input = fopen("D:\\input.txt", "r");
//подготавливаем переменную для записи в нее значения из файла
char str[1024];
fgets(str, 1023, input) ;
int x;
char plus;
//Приводим отпарсенные данные к целому типу
int one = static_cast<int>(str[0]-'0');
int two = static_cast<int>(str[2]-'0');
//Узнаем знаки
plus=str[1];
int result;
if (plus == '+') {
result = one+two;
}
if (plus == '-') {
result = one-two;
}
int i;
int j=0;
int p;
int p2;
for (i = 0; i < 100; i++) {
if (!str[i]) {
break;
}
else
{
j++;
}
}
int *s3 = new int [j];
for (p = 0; p < j; p++) {
s3[p] = str[p];
}
for (p2 = 0; p2 < j; p2++) {
if (str[p2] != '+' & str[p2] != '-' & str[p2] != '*'& str[p2] != '/') {
s3[p2] = static_cast<int>(str[p2]-'0');
}
else {
s3[p2] = str[p2];
}
}
int c;
int sum1;
int itog=0;
int end = 0;
int k;
int sam = 0;
int raz = 0;
int temp2;
int sum=0;
int l;
for (c = 0; c < j-1; c++) {
if (c%2 != 0) {
end++;
}
}
char temp;
for (c = 0; c < j; c++) {
if (c%2 != 0) {
if (s3[c] == '*') {
if (s3[c+2] != '*' && s3[c+2] != '/') {
if (raz == 0) {
itog = s3[c-1]*s3[c+1]+sum;
s3[c+1] = itog;
sum=0;
}
if (raz != 0) {
itog = raz - s3[c-1]*s3[c+1]+sum;
s3[c+1] = itog;
sum=0;
raz = 0;
}
}
else {
itog = s3[c-1]*s3[c+1];
s3[c+1] = itog;
}
}
if (s3[c] == '/') {
if (s3[c+2] != '*' && s3[c+2] != '/') {
if (raz==0) {
itog = s3[c-1]/s3[c+1]+sum;
s3[c+1] = itog;
}
if (raz!= 0 ) {
itog = raz-s3[c-1]/s3[c+1]+sum;
s3[c+1] = itog;
}
}
else {
itog = s3[c-1]/s3[c+1];
s3[c+1] = itog;
}
}
if (s3[c] == '+') {
sum=0;
if (s3[c+2] == '*' || s3[c+2] == '/' ) {
sum = sum+s3[c-1];
}
if (s3[c+2] != '*' && s3[c+2] != '/') {
itog = s3[c-1]+ s3[c+1] +sum;
s3[c+1] = itog;
}
}
if (s3[c] == '-') {
if (s3[c+2] == '*' || s3[c+2] == '/' ) {
raz = raz+s3[c-1];
}
if (s3[c+2] != '*' && s3[c+2] != '/') {
itog = s3[c-1]- s3[c+1] +sum;
s3[c+1] = itog;
}
}
}
}
cin>> x;
}
//---------------------------------------------------------------------------