Опубликован: 21.03.2012 | Доступ: свободный | Студентов: 2804 / 169 | Оценка: 4.44 / 4.19 | Длительность: 06:43:00
Специальности: Программист
Лекция 5:

Типовые алгоритмы обработки одномерных массивов. Сортировка методом "Пузырька"

< Лекция 4 || Лекция 5 || Лекция 6 >
Аннотация: В лекции продолжено знакомство с типовыми алгоритмами обработки одномерных массивов - рассмотрен типовой алгоритм сортировки элементов массива и разобраны некоторые олимпиадные задачи, которые решаются с использованием сортировки. Цель лекции: научиться применять изученный типовой алгоритм при решении классических задач.
Ключевые слова: массив

Сортировку данным методом рассмотрим на примере. Дан массив (табл.), элементы которого необходимо отсортировать в порядке возрастания:

5 8 4 9 3
Сортировка 'Пузырьком'

Рис. 4.1. Сортировка 'Пузырьком'
Программная реализация на Бейсике Программная реализация на Паскале
. . .  
for j=n  to 2 step  -1
  for i=1  to j-1
    if   a(i)>a(i+1) then swap a(i), a(i+1)
next  i, j
…
. . .  
for j:=n downto 2 do 
  for i:=1 to j-1 do
    if   a[i]>a[i+1] then 
	  begin
	  x:=a[i]; a[i]:= a[i+1]; a[i+1]:=x;
	  end;
. . .  

Задачи, решаемые с использованием сортировки

Задача: Дан ряд целых случайных чисел. Преобразуйте его в ряд чисел, между которыми можно было бы расставить знаки "<" и ">" в чередующемся порядке.

Идея решения: Ряд чисел СОРТИРУЕМ. Меняем местами каждую пару чисел.

Решение задачи на Бейсике:

Input "количество чисел"; n
dim a(n)
for i = 1 to n
  input "введите число"; a(i)
next
rem=====сортируем массив===========
for j=n to 2 step -1
  for i=1 to j-1
	if a(i)>a(i+1) then swap a(i), a(i+1)
next i, j
rem ====меняем местами пару чисел=====
for i = 1 to n-1 step 2
  swap a(i), a(i+1)
next
print
for i=1 to n
  print a(i);
next

Решение задачи на Паскале:

var a: array [1..10] of integer;
  i,j,n,x:integer;
begin
  writeln ('количество чисел'); readln (n);
  for i:= 1 to n do
    begin
	writeln ('введите число'); readln (a[i]);
	end;
  {=====сортируем массив==========}
  for j:=n downto 2 do 
    for i:=1 to j-1 do
	  if a[i]>a[i+1] then 
	  	begin
		x:=a[i];
		a[i]:= a[i+1];
		a[i+1]:=x;
		end;
  {====меняем местами пару чисел====}
  x:=1;
  for i:= 1 to (n div 2) do
    begin
	x:=a[j];
	a[j]:= a[j+1];
	a[j+1]:=x;
	j:=j+2;
	end;
  for i:=1 to n do writeln (a[i]);
end.

Тест:

Дано: 5, 2, 1, 8, 0, 67, 100.
Результат: 1, 0, 5, 2, 67, 8, 100
Задачи "Подпоследовательности"
  1. В последовательности чисел выделить все подпоследовательности подряд идущих чисел.

    Идея решения: Ряд чисел СОРТИРУЕМ. Перебираем элементы массива, сравнивая два соседних элемента. Если разница между ними не равна единице, то начинаем печать новой подпоследовательности.

    Решение задачи на Бейсике:

    Input "количество чисел"; n
    dim a(n)
    for i = 1 to n
      input "введите число"; a(i)
    next
    rem====сортируем массив===============
    for j=n  to 2 step  -1
      for i=1  to  j-1
        if   a(i)>a(i+1) then swap a(i), a(i+1)
    next  i, j
    rem ==============================
    print a(1);
    for i = 2 to n
      if a(i) - a (i-1) < > 1 then print
    print a(i) ;
    next
    

    Решение задачи на Паскале:

    var 	a: array [1..10] of integer;
      i,j,n,x: integer;
    begin
      writeln ('количество чисел');
      readln (n);
      for i:= 1 to n do
        begin
    	writeln ('введите число');
    	readln (a[i]);
    	end;
      {=====сортируем массив=============}
      for j:=n  downto 2 do
        for i:=1  to  j-1 do
    	  if   a[i]>a[i+1] then 
    	    begin
    		x:=a[i];
    		a[i:= a[i+1];
    		a[i+1]:=x;
    		end;
      {=============================}
      write (a[1]);
      for i:= 2 to n do
      	begin
        if (a[i]-a[i-1]) <> 1 then writeln;
    	write (a[i]) ;
    	end;
    end.
    

    Тест:

    Дано:

    N=10

    2, 1, 5, 3, 7, 8, 6, 12, 9, 11

    Результат:

    1, 2, 3

    5, 6, 7, 8, 9

    11, 12

  2. В последовательности чисел найти и вывести подпоследовательность подряд идущих чисел наибольшей длины.

    Идея решения: Ряд чисел СОРТИРУЕМ. Перебираем элементы массива, сравнивая два соседних элемента. Если разница между ними равна единице, значит очередное число входит в текущую подпоследовательность. В ячейке К накапливаем ее длину. Применив типовой алгоритм поиска МАКСИМАЛЬНОГО ЭЛЕМЕНТА находим подпоследовательность наибольшей длины.

    Решение задачи на Бейсике:

    Input "количество чисел"; n
    dim a(n)
    for i = 1 to n
      input "введите число"; a(i)
    next
    rem====сортируем массив==============
    for j = n to 2 step -1
      for i = 1 to j - 1
        if a(i) > a(i + 1) then swap a(i), a(i + 1)
    next i, j
    rem =выводим отсортированный массив======
    for i = 1 to n
      print a(i);
    next
    print
    max = 0
    k = 1
    for i = 1 to n - 1
      if a(i + 1) - a(i) = 1 then k = k + 1 else k = 1
      if k > max then max = k: number = i + 1
    next i
    print "максимальная длина="; max
    print "самая длинная подпоследовательность="
    for i=(number-max+1) to number
      print a(i);
    next
    

    Решение задачи на Паскале:

    var a: array [1..10] of integer;
      max,k,number,i,j,n,x: integer;
    begin
      writeln ('количество чисел');
      readln (n);
      for i:= 1 to n do
        begin
    	writeln ('введите число'); readln (a[i]);
    	end;
      {=====сортируем массив================}
      for j:=n  downto 2 do
        for i:=1  to  j-1 do
    	  if   a[i]>a[i+1] then 
    	    begin
    		x:=a[i];
    		a[i]:= a[i+1];
    		a[i+1]:=x;
    		end;
      {================================}
      max:= 0;
      k:= 1;
      for i: = 1 to n-1 do
      	begin
        if a[i+1] - a[i] = 1 then k: = k + 1 
    	else k: = 1;
    	if k > max then 
    	  begin
    	  max: = k;
    	  number: = i + 1;
    	   end;
    	  end;	writeln ( 'максимальная длина=', max);
      writeln ('самая длинная подпоследовательность=');
      for i: = (number - max + 1) to number do
      writeln (a[i]);
    end.
    

    Тест:

    Дано:

    N=10

    2, 1, 5, 3, 7, 8, 6, 12, 9, 11

    Результат:

    Max=5

    5, 6, 7, 8,9

Задача: Ввести предложение. Поменять порядок слов в нем, расположив их в порядке увеличения букв в словах.

Идея решения: Применив типовой алгоритм "РАЗБОРА" ПРЕДЛОЖЕНИЯ НА СЛОВА, помещаем каждое слово в элемент массива. Далее СОРТИРУЕМ массив слов, сравнивая количество букв в словах.

Решение задачи на Бейсике:

input "введите предложение"; a$
n=len (a$)
for i=1 to n
  if mid$(a$,i,1)=" " then k=k+1
next
k=k+1   
dim a$(k)
j=1
for i=1 to n
	if mid$(a$,i,1)=" " then j=j+1 else a$(j)=a$(j)+mid$(a$,i,1)
next
rem=====сортируем массив=======================
for j=k  to 2 step  -1
  for i=1  to  j-1
	 if   len (a(i))>len (a(i+1)) then swap a(i), a(i+1)
next  i, j
rem =======================================
for i=1 to k
  print a(i); " ";
next

Решение задачи на Паскале:

var b:array[1..10] of string;
  a,a1,a2,x: string;
  n,i,j,k: integer;
begin
  writeln ('введите предложение');
  readln (a);
  n:=length (a);
  k:=0;
  for i:=1 to n do
    if copy(a,i,1)=' ' then k:=k+1;
  k:=k+1;
  j:=1 ;
  for i:=1 to n do
    if copy(a,i,1)=' ' then j:=j+1
	else b[j]:=b[j]+copy(a,i,1);
  {=====сортируем массив==============}
  for j:=k downto 2 do 
    for i:=1 to j-1 do
	  if length (b[i])>length (b[i+1]) then 
	    begin
		x:=b[i];
		b[i]:= b[i+1];
		b[i+1]:=x;
		end;
  { ==============================}
  for i:=1 to k do
    writeln (b[i]);
end.

Тест:

Дано: Мой любимый предмет - информатика
Результат: - Мой предмет любимый информатика
Задачи "Сортировка частей массива"

Среди задач на сортировку элементов массива можно выделить большую группу задач, в которых необходимо отсортировать ЧАСТЬ МАССИВА ПО ВОЗРАСТАНИЮ, ЧАСТЬ ПО УБЫВАНИЮ.

Идея решения: Допустим, дан массив А, заполненный положительными и отрицательными целыми числами (рис. 4.2):


Рис. 4.2.

Необходимо отсортировать положительные элементы массива по возрастанию, отрицательные элементы оставить на своих местах.

  • Вводим дополнительный массив В, который заполняем индексами положительных элементов массива А (рис. 4.3):


    Рис. 4.3.
  • Затем используем ТИПОВОЙ АЛГОРИТМ СОРТИРОВКИ, в качестве индексов перебираемых в цикле элементов массива А используем элементы массива В. Данное решение задачи также можно выделить в отдельный типовой алгоритм:

    Программная реализация на Бейсике:

    Input "количество чисел"; n
    dim a(n), b(n)
    for i = 1 to n
      input "введите число"; a(i)
    next
    j=1
    for i=1 to n
      if a(i)>0 then b(j)=i: j=j+1:k=k+1
    next i
    for j=k to 2 step -1
      for i=1 to j-1
    	if a(b(i))>a(b(i+1)) then swap a(b(i)),a(b(i+1))
    next i,j
    for i=1 to n
      print a(i); "  ";
    next i
    

    Программная реализация на Паскале:

    const m=10;
    var	a, b: array [1..m] of integer;
      i, j, n, x, k: integer;
    begin
      writeln ('количество чисел');
      readln (n);
      for i:= 1 to n do
        begin
    	writeln ('введите число');
    	readln (a[i]);
    	end;
      j:=1;
      k:=0;
      for i:=1 to n do
    	if a[i]>0 then
    	  begin
    	  b[j]:=i;
    	  j:=j+1;
    	  k:=k+1;
    	  end;
      for j:=k downto 2 do
         for i:=1 to j-1 do
    	  if a[b[i]]>a[b[i+1]] then 
    	  begin
    	  x:=a[b[i]];
    	  a[b[i]]:=a[b[i+1]];
    	  a[b[i+1]]:=x;
    	  end;
      for i:=1 to n do
        write (a[i],' ');
    end.

    Тест:

    Дано:

    N=9

    -3, 5, -1, 3, 6, -8, 2, -1, -3

    Результат: -3, 2, -1, 3, 5, -8, 6, -1, -3
Ключевые термины
  • Сортировка пузырьком - один из методов упорядочивания элементов одномерного массива.
  • Подпоследовательность - фрагмент последовательности данных, выделенный по определенному признаку.
Краткие итоги

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

При сортировке частей массива (в зависимости от критериев отбора элементов в выбираемой части массива) в качестве индексов перебираемых в цикле элементов исходного массива А используем элементы дополнительного массива В (в нем хранятся индексы выбираемых элементов исходного массива).

Набор для практики

Вопросы.

  • Что происходит за один проход массива при сортировке "Пузырьком"?
  • Объясните зависимость счетчика внутреннего цикла от счетчика внешнего цикла в типовом алгоритме сортировки одномерного массива "Пузырьком".

Упражнения.

  • Символьная строка состоит из цифр и латинских букв. Упорядочьте все цифры в порядке убывания, а буквы в алфавитном порядке, оставляя и те и другие на своих местах.
  • В массиве натуральных чисел все простые числа упорядочьте по возрастанию, составные по убыванию.
  • Найдите в тексте все гласные буквы и расположите их в порядке возрастания номеров алфавита, а все согласные буквы - в порядке убывания номеров алфавита.
  • Ввести предложение. Измените порядок слов в предложении, расположив в алфавитном порядке (по первой букве каждого слова).
< Лекция 4 || Лекция 5 || Лекция 6 >
Александр Абросимов
Александр Абросимов
Россия
Сергей Куниловский
Сергей Куниловский
Россия, Санкт-Петербург