Sortowanie przez wstawianie - odwołanie do struktury

0

Wiem, mam struktury, ale nie chcę tego algorytmu robić na klasie. ;)
Problem jest taki - mam studentów, którym przypisany jest numer i oceny. Trzeba posortować ich według średniej. Niestety, pewnie źle się odwołuję do pól struktury. Oto program:

 #include <iostream>
#include <cstdlib>

using namespace std;

struct Student
{
int numer;
float oceny[3];
};

float srednia(struct Student s)
{return (s.oceny[0]+s.oceny[1]+s.oceny[2])/3.0;}


int main()
{
struct Student studenci[4];
studenci[0].numer = 1;
studenci[0].oceny[0] = 3; studenci[0].oceny[1] = 3.5; studenci[0].oceny[2] = 5;

studenci[1].numer = 2;
studenci[1].oceny[0] = 4; studenci[1].oceny[1] = 5; studenci[1].oceny[2] = 5;

studenci[2].numer = 3;
studenci[2].oceny[0] = 3; studenci[2].oceny[1] = 4; studenci[2].oceny[2] = 2;

studenci[3].numer = 4;
studenci[3].oceny[0] = 2; studenci[3].oceny[1] = 4; studenci[3].oceny[2] = 2;
for (int i=0; i<4; i++)
{
cout <<studenci[i].numer<<" "<<srednia(studenci[i])<<"\n";
}

for(int i=1; i<4;i++)
{
	int k=i-1;
	float el=srednia(studenci[1]);
	for(k=i-1;k>=0 && srednia(studenci[k])>el; k--)
	{srednia(studenci[k+1]) = srednia(studenci[k]);}
	srednia(studenci[k+1]=el;
	}

return 0;

}

Kompilator błędy pokazuje w tym miejscu:

for(int i=1; i<4;i++)
{
	int k=i-1;
	float el=srednia(studenci[1]);
	for(k=i-1;k>=0 && srednia(studenci[k])>el; k--)
	{srednia(studenci[k+1]) = srednia(studenci[k]);}
	srednia(studenci[k+1]=el;
	} 
0

Masz wymieniać miejscami studentów a nie ich średnie.

0

No dobrze, a możesz mnie naprowadzić, jak zabrać się za to od strony technicznej?
Żeby nie gubić numeru studenta przy sortowaniu tych średnich?

0

Wyobraź sobie to fizycznie, masz przed sobą 4-ch studentów.
Teraz zamiast przestawić dwóch studentów miejscami próbujesz wymienić ich średnie, ba nie zmieniając nawet ocen !!

0

Męczysz. ;) Tym bardziej, że mój mózg chyba poszedł spać. :P
Znaczy się chyba teraz nie bardzo kojarzę - jak wymieniam średnie, to przypadkiem nie zmieniam numeru studenta? Posortowanie samych średnich nie jest dużym problemem, problem w tym, że nie wiem, jak zachować podczas operacji sortowania ten numer studenta (który jest na stałe do niego przypisany).

0

Kopiując studenta - kopiujesz wraz z numerem oraz ocenami. Numer to nie to samo co indeks w tablice.

0

No tak. Niby rozumiem, ale... Może to wstyd, ale ja nadal nie wiem, jak to fizycznie zaimplementować.

0

Zamieniać miejscami studentów, nie ich średnie.

0

Już to gdzieś czytałam. ;)
Dobra, jeszcze raz - ale jak? Żeby wymieniać, to przecież muszę odwołać się do ich średnich, prawda?

0

Powiedz jak to inaczej wytłumaczyć:

struct Student el;
el=studenci[k];
studenci[k]=studenci[k+1];
studenci[k+1]=el;
0

Dobrze, czyli się rozumieliśmy. Próbowałam tak robić.
Oto problematyczny fragment kodu:

struct Student el;
for(int i=1; i<4;i++)
{
	int k=i-1;
	el=studenci[k];
	for(k=i-1;k>=0 && (studenci[k]>el); k--)
	{studenci[k+1] = studenci[k];}
	studenci[k+1]=el;
	} 

Znowu wywala błąd przy tym:

 for(k=i-1;k>=0 && (studenci[k]>el); k--)

error no match for 'operator>' in 'studenci[k] > el'

1
(studenci[k]>el)

Nie możesz użyć tego operatora w takim kontekście, bo nie masz go zdefiniowanego; Zastanów się jeszcze raz co masz porównać i zrób to bez kombinacji.

1

Powiedziałem że masz przestawiać miejscami studentów a nie średnie - więc teraz owszem przestawiasz miejscami studentów oraz porównujesz też studentów,
porównywać wciąż masz średnie, nie studentów.

0

No dobrze, coś już idzie.
Teraz ta część programu wygląda tak:

for(int i=1; i<4;i++)
{struct Student el;
	int k=i-1;
	el=studenci[k];
	for(k=i-1;k>=0 && srednia(studenci[k])>srednia(studenci[i]); k--)
	{studenci[k+1] = studenci[k];}
	studenci[k+1]=el;
	} 

Jednak nadal mam pewien problem. Winna jest pewnie ta pęta for:

for(k=i-1;k>=0 && srednia(studenci[k])>srednia(studenci[i]); k--)

Podejrzewam, że problem jest tu:

srednia(studenci[k])>srednia(studenci[i])
. Jakaś wskazówka?

0

Rozrysuj sobie to sortowanie na kartce i napisz jeszcze raz.

0

Nie wiem. Nie potrafię znaleźć błędu.
Po wykonaniu tego:

for(int i=1; i<4;i++)
{struct Student el;
	int k=i-1;
	el=studenci[i];
	for(k=i-1;k>=0 && srednia(studenci[k])>srednia(studenci[i]); k--)
	{studenci[k+1] = studenci[k];}
	studenci[k+1]=el;
	} 

Otrzymuję takie wyniki:

3,83
3
2,66
4,66

To samo jest, gdy sortuję tak:

for(int i=1; i<4; i++)
 {
 int j=i;
 struct Student temp=studenci[j];
 while ((j>0) && srednia(studenci[j-1])>srednia(studenci[j]))
    {
    studenci[j]=studenci[j-1];
    j--;
    }
 studenci[j]=temp;}
0

To drugie sortowanie, już wygląda na sensowne i powinno działać.
Może jeszcze gdzieś masz błąd?

1

Załóżmy, że masz tablicę {2, 4, 1}
Pierwsza pętla for nic nie zmienia.
Druga pętla for:

while 4>1 {2, 4, 1} -> {2, 4, 4}
while 2>4 {2, 4, 4} -> {2, 4, 4}
{2, 1, 4}

Przy kolejnych wywołaniach while porównujesz do elementu który został przesunięty.

1
#include <iostream>
using namespace std;

struct Student
  {
   int numer;
   float oceny[3];
   float srednia()const { return (oceny[0]+oceny[1]+oceny[2])/3; }
  };
 

int main()
  {
   Student studenci[]={{1,{3,3.5,5}},{2,{4,5,5}},{3,{3,4,5}},{4,{2,4,2}}};
   for(int i=0;i<sizeof(studenci)/sizeof(*studenci);++i) cout<<studenci[i].numer<<" "<<studenci[i].srednia()<<endl;
   for(int i=1;i<4;++i)
     {
      int k=i;
      Student el=studenci[k];
      for(float sr=el.srednia();(k>0)&&(sr<studenci[k-1].srednia());--k) studenci[k]=studenci[k-1];
      studenci[k]=el;
     }
   cout<<endl;
   for(int i=0;i<sizeof(studenci)/sizeof(*studenci);++i) cout<<studenci[i].numer<<" "<<studenci[i].srednia()<<endl;
   return 0;
  }

http://ideone.com/MK1raf

1 użytkowników online, w tym zalogowanych: 0, gości: 1