Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекция 11 12 ятп.docx
Скачиваний:
7
Добавлен:
22.02.2015
Размер:
75.96 Кб
Скачать

Лекция 11, 12

Сортировка

Сортировка — это процесс перегруппировки элементов заданной совокупности с целью расположить их в определённом порядке, т.е. это процесс упорядочения элементов в соответствии с некоторым принципом.

Рассмотрим некоторую совокупность из n элементов:

a0, a 1, …, a n-1

После сортировки элементы располагаются в совокупности в каком-то порядке:

Например, для некоторой функции f(x) элементы перегруппированы так, что

Здесь функция f(x) называется упорядочивающей функцией. Если элементы исходной совокупности с одинаковыми значениями упорядочивающей функции не изменяют своего относительного расположения при перегруппировке, то метод сортировки называют устойчивым.

Примем следующие соглашения:

  • элементы совокупности a0 ,a1, …a n-1 — числовые;

  • упорядочивающая функция f(x) = x, т.е. f( ai ) = ai ;

  • элементы в результате сортировки удовлетворяют условию a0a 1  …a n-1 ;

  • сортировка выполняется «на том же месте», т.е. в составе данной совокупности.

Будем рассматривать три группы методов сортировки:

а) сортировка Выбором;

б) сортировка Обменом;

в) сортировка Включением.

В каждой группе рассмотрим

  • прямые методы — очевидные, реализующие основную идею, но, может быть, не всегда самые эффективные;

  • модификации прямых методов — несколько улучшенные методы с той же основной идеей.

Меру эффективности метода будем оценивать:

  • по числу сравнений элементов С(n);

  • по числу перемещений элементов M(n);

  • по временной сложности метода T(n);

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

А) Сортировка с помощью прямого Выбора: Идея метода:

0 шаг: min { a0 ,a 1, …a n-1 }  a0

1 шаг: min { a 1, …a n-1 }  a1

……………………………………………………….

(n-2) шаг: min { an-2 ,a n-1 }  a n-2

Cхема алгоритма:

for (int i=0; i<n-1;i++)

{ <определить место k минимального элемента в совокупности { ai ,ai+1 , …a n-1 }>

< переставить минимальный элемент ak с ai >

}

const int n=100;

Пусть: int a[n]; — заданная совокупность.

//сортировка выбором минимального

void selection (int a[], int n)

{for (int i=0;i<n-1;i++)

{int min=a[i] ,m=i;

for(int j=i+1; j<n; j++)

if (a[j]<min) {min=a[j]; m=j;}

a[m]= a[i]; a[i]= min;

} 8 7 6 5 4 3 2 1

} 1 2 6 5 4 3 7 8

1 2 3 5 4 6 7 8

1 2 3 4 5 6 7 8

n-1 +n-3+n-5+…1 =n2 / 4

7 6 5 4 3 2 1

1 6 5 4 3 2 7

1 2 5 4 3 6 7

n-1 + n-3+n-5+… 0=(n2-1)/4 1 2 3 4 5 6 7

Характеристики алгоритмасортировки с помощью прямого Выбора:

Порядок метода О(n2)

Модификации прямого выбора:

1. Модификация.Идея метода: поиск в просматриваемой совокупности максимального элемента и перестановка его с последним элементом.

0 шаг: max { a0 ,a 1, …a n-1 }  an-1

1 шаг: max { a0, …a n-2 }  an-2

……………………………………………………….

(n-2) шаг: max { a0,a1 }  a 1

Cхема алгоритма:

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

{<найти место k максимального элемента в совокупности { a0 ,a1 , …a n-1-i }>

< переставить максимальный элемент ak с an-i+1 >

}

Этот алгоритм описать самим

2. Модификация. Идея метода: Соединить в одном просмотре совокупности поиск максимального и поиск минимального элементов, затем переставить минимальный с первым, а максимальный с последним элементом. При этом просматриваемый сегмент сужается с двух сторон.

Cхема алгоритма:

int t=n/2;

for (int i=0; i<t;i++)

{ <найти место m1 максимального и место m минимального элементов в совокупности { ai ,ai+1 , …a n-i-1 }>

< переставить минимальный элемент am с ai >

if m1 = i then m1 := m;

< переставить максимальный элемент am1 с an-i-1 >

}

//сортировка выбором минимального и максимального

void selection3 (int a [], int n)

{int t=n/2;

for (int i=0; i<t; i++)

{int min = a[i], m = i, max = a[i], m1 = i;

for(int j=i+1 ; j<n-i; j++)

{ if (a[j]<min) { min = a[j]; m = j;}

if (a[j]>max) { max = a[j]; m1 = j;}}

a[m] = a[i]; a[i] = min;

if (m1==i) m1 = m;

a[m1] = a[n-1-i]; a[n-1-i] = max;

}

Б) Сортировка с помощью прямого Обмена: Идея метода

Просматривается каждая пара соседних элементов в совокупности: аj и аj+1 для j =0,1,…n-2. Если элементы пары не находятся в нужном отношении, т.е. : аj > аj+1 , то они переставляются (меняются местами).

Схема алгоритма:

for (int j=0; j<n-1;j++) if (a[j] > a[j+1] ){ < a[j] a[j+1] };

Назовём такой просмотр просмотром «Слева направо» ( ) , а просмотр

for (int j=n-2; j>=0;j--) if ( a[j] > a[j+1] ) { < a[j] a[j+1] }; назовем просмотром Справа налево» ().

Элементы совокупности ассоциируются с пузырьками воздуха в чане с водой: каждый пузырёк со своим весом-значением. Отсюда и название метода пузырьковая сортировка.

Можно отметить, что

  • за один просмотр элементы, вообще говоря, не будут упорядочены;

  • однако, если во время просмотра не было ни одной перестановки, то совокупность упорядочена; можно сделать вывод, что просмотры необходимо повторять, пока есть перестановки;

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

  • за один просмотр самый легкий пузырёк продвинется к своему месту на одну позицию, т.е. если самый легкий пузырек стоял на дне (худший случай), то за (n -1) просмотр он встанет на свое место; отсюда вывод: за (n-1) просмотр совокупность будет упорядочена.

//пузырьковая сортировка

voidbubble(inta[],intn)

{for(inti=0;i<n-1;i++) //n-1 просмотр

for(intj=n-1;j>i;j--) // Просмотры «справа налево» ().

if (a[j-1] > a[j]) {int r = a[j-1] ; a[j-1]= a[j]; a[j]=r;}

}

Характеристики алгоритма сортировки с помощью прямого Обмена:

Порядок метода О(n2)

Модификации прямого Обмена:

1. Модификация. Можно выполнять просмотры «Слева направо» ()

//пузырьковая сортировка1

void bubble1 (int a[ ], int n)

{for (int i=n-1;i>0;i--) // n-1 просмотр

for (int j=0; j<i ;j++) // пока j<i, т.к. тяжелый ->на свое место

if (a[j ] > a[j+1]) {int r = a[j] ; a[j]= a[j+1]; a[j+1]=r;}

}

2. Модификация. Запоминание факта перестановки. Недостатком прямого обмена является выполнение (n-1) просмотра даже в случае, если совокупность упорядочится раньше (также в случае заданной упорядоченной совокупности). Удобно организовать проверку, были ли перестановки элементов во время просмотра и, если не было (т.е. совокупность упорядочена), прекратить просмотры.

Схема алгоритма:

i := 0; p := true;

While ( p) //{пока есть перестановки}

{i := i + 1; //{номер просмотра}

p := false;

for (int j=0; j<n-i ; j++) if ( a[j] > a[j+1]) {int R := a[j]; a[j] := a[j+1]; a[j+1] :=R;

p := true //запоминание факта перестановки

}

}

//запоминание факта перестановки

voidbubble2 (inta[ ],intn)

{int i=0;

bool p=true;

while (p)

{i++; p=false; //i-номер просмотра

for(int j=0; j<n-i; j++)

if(a[j]>a[j+1]) { int r = a[j] ; a[j]= a[j+1]; a[j+1]=r;

p=true; //запоминание факта перестановки

} }

3. Модификация. Запоминание места последней перестановки.

a0 , a1 , … , a L-1 , aL , ……,aj-1 , a j , aj+1 , … ,ar-1 , ar , ar+1 , … ,a n-1

Если в просмотре «Слева направо» ( ) последняя перестановка была

аr аr+1, то элементаr+1 встал на своё место и следующий просмотр можно выполнять на сегменте {a0,a1, … ,ar-1,ar }, т.е. возможно более значительное, чем на 1элемент, сужение сегмента просмотра.

Схема алгоритма

r = n-1;

while (r>0) // {Цикл просмотров}

{int t=0;

for (int j=0;j<r;j++)

if (a[j] > a[j+1]) { int v = a[j]; a[j] = a[j+1]; a[j+1] = v;

t=j; // запоминание места перестановки

}

r=t; }

Аналогично для просмотра «Справа налево» (), когда последняя перестановка была аL аL+1 : написать алгоритм самим.

void bubble3 (int a[], int n)

{int r=n-1;

while (r>0) //цикл просмотров

{int t=0;

for(int j=0; j<r; j++)

if(a[j]>a[j+1]) { int z = a[j] ; a[j]= a[j+1]; a[j+1]=z; t=j;}

r=t; }}

4. Модификация. Чередование просмотров «Слева направо» ( ) и «Справа налево» () с запоминанием в каждом просмотре места последней перестановки — так называемая Шейкерная сортировка.

//чередование просмотров с запоминанием мест последних //перестановок

void bubble4 (int a[], int n)

{int L=0, r=n-2, t=L;

do

{//-->

for (int j=L;j<=r;j++)

if(a[j]>a[j+1])

{int v= a[j]; a[j]=a[j+1]; a[j+1]=v; t=j;}

r=t-1;

// -

for(int j=r;j>=L;j--)

if(a[j]>a[j+1])

{ int v= a[j]; a[j]=a[j+1]; a[j+1]=v; t=j;}

L=t+1; //запоминание места перестановки

}

while (L<=r);

}

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]