Технический форум

Технический форум (http://www.tehnari.ru/)
-   Delphi, Kylix and Pascal (http://www.tehnari.ru/f43/)
-   -   Помогите исправить, пожалуйста (http://www.tehnari.ru/f43/t92817/)

Стася 03.12.2013 19:05

Помогите исправить, пожалуйста
 
Вложений: 1
Программа, которая у меня получилась то нормально работает, то вместо второго максимального по значению элемента находит просто максимальный( всю голову сломала уже

Вот, что получилось:

Стася 03.12.2013 19:06

Program Variant_5;
Uses Crt;
Const n = 10; {задание размера вектора именованной константой}

Var i, v_min, v_max,i_max, max,i_min, min, i_max_2, max_2, i_min_2, min_2, k, m, a, i1, i2 : Integer;
vector : Array [1..n] Of Integer;

Begin

Randomize; {запуск генератора случайных чисел}
WriteLn('Задайте диапазон случайных чисел');
Write('v_min=');
ReadLn(v_min);
Write('v_max=');
ReadLn(v_max);

For i:=1 To n Do {заполнение вектора случайными числами}
vector[i]:=Random(v_max-v_min + 1) + v_min;

WriteLn;
WriteLn('Исходный вектор:');
For i:=1 To n Do {вывод на экран исходного вектора}
Write(vector[i]:5);
WriteLn;

max:= vector[1]; {пока макс элемент - первый элемент вектора}
i_max:= 1;
min:= vector[1]; {пока мин элемент - первый элемент вектора}
i_min:= 1;

For i:=2 To n Do {поиск начинаем со второго элемента}
Begin

If (vector[i] > max) Then {если очередной элемент больше} {текущего максимального}
Begin
max := vector[i]; {то максимальным элементом}
i_max := i; {становится очередной элемент} {вектора}
End;

If (vector[i] < min) Then {если очередной элемент меньше} {текущего минимального}
Begin
min := vector[i]; {то минимальным элементом}
i_min := i; {становится очередной элемент} {вектора}
End;

End;


max_2:= vector[1];
i_max_2:= 1;
min_2:= vector[1];
i_min_2:= 1;

For i:=2 To n Do
Begin

If (vector[i]<max) and (vector[i]>max_2) Then
Begin
max_2 := vector[i]; {то максимальным элементом}
i_max_2 := i; {становится очередной элемент} {вектора}
End;

If (vector[i]>min)and (vector[i]<min_2) Then
Begin
min_2 := vector[i]; {то минимальным элементом}
i_min_2 := i; {становится очередной элемент} {вектора}
End;

End;

WriteLn;
WriteLn('max_2=', max_2, ' i_max_2=', i_max_2);
WriteLn('min_2=', min_2, ' i_min_2=', i_min_2);

If min=max then write('Решений нет-все элементы равны между собой')
else
begin
If i_min_2<i_max_2 then
Begin
i1:=i_min_2;
i2:=i_max_2;
End
Else
Begin
i2:=i_min_2;
i1:=i_max_2;
End;

a:=n-i2;
m:=(i2-i1) Div 2;
For i:=i1 To m Do
Begin
k:= vector[i1+i];
vector[i1+i]:=vector[i2-i] ;
vector[i2-i]:=k;
End;

WriteLn;
WriteLn('Полученный вектор:');
For i:=1 To n Do {вывод на экран полученного вектора}
Write(vector[i]:5);
WriteLn
End;
End.

Vladimir_S 03.12.2013 20:26

Цитата:

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

Ничего страшного, Стася, всё понятно, сейчас поправим.
Тут есть одна тонкость. Вы применяете следующий алгоритм поиска максимума и минимума: объявляете таковыми первый элемент, а затем, начиная со второго, сравниваете элементы с max и min, и если кто-то из них больше max или меньше min, то он и становится новым max (min). Так вот, пока дело касается ПЕРВЫХ максимумов, это правильно, а вот со вторыми уже может возникнуть ошибка. Представьте себе, что самым максимальным оказался ПЕРВЫЙ ПО СЧЕТУ элемент. И что тогда произойдёт? Вы объявляете его вторым максимумом (max_2), а потом, сравнивая с ним все прочие элементы, получаете невыполнение условия переприсвоения значения max_2 и, следовательно, он так и остается якобы вторым по величине.
Избежать этой ситуации можно, например, так:
Код:

max_2:= min;
 min_2:= max;

 For i:=1 To n Do
  Begin
  If (vector[i]<max) and (vector[i]>max_2) Then
    Begin
    max_2 := vector[i];
    i_max_2 := i;
    End;
  If (vector[i]>min)and (vector[i]<min_2) Then
    Begin
    min_2 := vector[i];
    i_min_2 := i;
    End;
  End;

Обратите внимание: перебор начинается с i=1!!!

Стася 03.12.2013 20:50

Спасибо огромное! Теперь понятно)
А можете еще вот этот момент посмотреть?

begin
If i_min_2<i_max_2 then
Begin
i1:=i_min_2;
i2:=i_max_2;
End
Else
Begin
i2:=i_min_2;
i1:=i_max_2;
End;

a:=i2-i1;
m:= a Div 2;
For i:=i1 To m Do
Begin
k:= vector[i1+i];
vector[i1+i]:=vector[i2-i] ;
vector[i2-i]:=k;
End;
Похоже,где "m:= a Div 2;" тоже ошибка. Когда а без остатка делится - все вроде правильно переворачивается, а в других случаях - на своих местах остается
Как это исправить можно?

Vladimir_S 03.12.2013 20:58

Цитата:

Сообщение от Стася (Сообщение 976598)
А можете еще вот этот момент посмотреть?

Увы, только завтра. Сейчас я выхожу из Сети. А пока был бы признателен, если бы Вы уточнили, что за алгоритм Вы применяете? Что за "поплавок"? Ссылку дайте или своими словами объясните.

Стася 03.12.2013 21:05

Вложений: 1
До прошлой недели я с программированием не сталкивалась особо, поэтому по примеру пыталась сделать:

Стася 03.12.2013 21:07

А в моем задании нужно было между i_min_2 и i_max_2 перевернуть элементы

Vladimir_S 04.12.2013 10:08

Цитата:

Сообщение от Стася (Сообщение 976607)
А в моем задании нужно было между i_min_2 и i_max_2 перевернуть элементы

Ага. Ну теперь я из примера хоть понял, что значит "перевернуть" и что значит "поплавок".
Да, действительно, эта часть программы сделана неверно. Исправил. Кстати, переменная "а" не нужна вовсе - выбросил.
И еще пожелание. С моей точки зрения, любое действие программиста должно быть осмысленным, в частности, присоединение модуля CRT ("uses CRT") следует делать, если Вы реально используете CRT-команды, а в Вашей программе таковые отсутствуют. К сожалению, правда, встречаются горе-преподаватели, которые требуют, чтобы студенты всегда подключали в своих программах этот самый CRT - типа "на всякий случай". Моя бы воля - я бы таких преподов гнал в шею.
Ну ладно, это, как говорится, лирика. Ниже я выложил отлаженную программу. Извините за переход на английский - просто с использованием кириллицы у меня проблемы в плане кодировки, поэтому стараюсь без крайней нужды ее не задействовать. Но это Вы поправите легко. И еще: если не нужно, то в конце оператор Readln можно удалить.
И еще. Увеличил длину массива до 20, потому что при n=10 никак было не попасть в ситуацию, когда i1 и i2 сильно разведены: то они соседние, то через один, а в этом случае "поплавок" не работает и было невозможно проверить.
Код:

Const
 n = 20;

Var
 i, v_min, v_max,i_max, max,i_min, min, i_max_2,
 max_2, i_min_2, min_2, k, m, i1, i2 : Integer;
 vector : Array [1..n] Of Integer;

Begin

 Randomize;
 WriteLn('Random numbers range:');
 Write('v_min=');
 ReadLn(v_min);
 Write('v_max=');
 ReadLn(v_max);

 For i:=1 to n do
  vector[i]:=Random(v_max-v_min + 1) + v_min;

 WriteLn;
 WriteLn('Initial vector:');
 For i:=1 To n Do
  Write(vector[i]:5);
 WriteLn;

 max:= vector[1];
 i_max:= 1;
 min:= vector[1];
 i_min:= 1;

 For i:=2 To n Do
  Begin
  If (vector[i] > max) Then
    Begin
    max := vector[i];
    i_max := i;
    End;

  If (vector[i] < min) Then
    Begin
    min := vector[i];
    i_min := i;
    End;
  End;


 max_2:= min;
 min_2:= max;

 For i:=1 To n Do
  Begin
  If (vector[i]<max) and (vector[i]>max_2) Then
    Begin
    max_2 := vector[i];
    i_max_2 := i;
    End;

  If (vector[i]>min) and (vector[i]<min_2) Then
    Begin
    min_2 := vector[i];
    i_min_2 := i;
    End;
  End;

 WriteLn;
 WriteLn('max_2=', max_2, ' i_max_2=', i_max_2);
 WriteLn('min_2=', min_2, ' i_min_2=', i_min_2);

 If min=max then
  writeln('No solution: all elements are equal')
 else
  begin
  If i_min_2<i_max_2 then
    Begin
    i1:=i_min_2;
    i2:=i_max_2;
    End
  Else
    Begin
    i2:=i_min_2;
    i1:=i_max_2;
    End;

  m:=(i2-i1) Div 2;
  For i:=1 To m Do
    Begin
    k:= vector[i1+i];
    vector[i1+i]:=vector[i2-i] ;
    vector[i2-i]:=k;
    End;

  WriteLn;
  WriteLn('Final vector:');
  For i:=1 To n Do
    Write(vector[i]:5);
  WriteLn
  end;
 Readln
End.


Стася 04.12.2013 10:23

Цитата:

Сообщение от Vladimir_S (Сообщение 976920)
Кстати, переменная "а" не нужна вовсе - выбросил.

ага, это осталось еще от предыдущих неудачных попыток, я вчера убрала ее

Цитата:

Сообщение от Vladimir_S (Сообщение 976920)
правда, встречаются горе-преподаватели, которые требуют, чтобы студенты всегда подключали в своих программах этот самый CRT - типа "на всякий случай"

У нас как раз такой случай, просят вставлять CRT - все-таки программирование не является профильным предметом у нас и дается в очень сжатые сроки

Спасибо большое за помощь) было бы здорово, если бы все преподаватели так понятно объясняли, как вы)


Часовой пояс GMT +4, время: 23:13.

Powered by vBulletin® Version 4.5.3
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.