Avatar billede snailwalker Nybegynder
15. november 2005 - 17:12 Der er 11 kommentarer og
1 løsning

Problemer med mergesort

void mergesort (int l, int r)
{
    if (r > l)
    {
       
        int mid = (l+r)/2;
        mergesort(l, mid);
        mergesort(mid+1, r);
        merge (l,mid,r);
    }
   
    return;
}

void merge (int l, int mid, int r)
{
    Farmer farmer_temp[5000];
    int i = l;
    int j = mid;
    int k = l;
    //cout << "Merge called, l: " << endl;// << l << " mid: " << mid << " r: " << r << endl;
    while (i<=mid && j<=r)
    {
        if (farmers[i].price < farmers[j].price)
        {
            farmer_temp[k].price = farmers[i].price;
            farmer_temp[k].milk = farmers[i].milk;
            //cout << "i<j " << farmers[i].price << " " << farmers[j].price << endl;
            i++;
           
        }
        else
        {
            farmer_temp[k].price = farmers[j].price;
            farmer_temp[k].milk = farmers[j].milk;
            //cout << "i>j " << farmers[i].price << " " << farmers[j].price << endl;
            j++;
           
        }
        k++;
    }
   
    if (i>mid)
    {
        for (; j<=r; j++, k++)
        {
            farmer_temp[k].price = farmers[j].price;
            farmer_temp[k].milk = farmers[j].milk;
        }
    }
    else
    {
        for (; i<=mid; i++, k++)
        {
            farmer_temp[k].price = farmers[i].price;
            farmer_temp[k].milk = farmers[i].milk;
        }
    }
   
    for (i = l; i<=r; i++)
    {
        farmers[i].price = farmer_temp[i].price;
        farmers[i].milk = farmer_temp[i].milk;
        cout << "Array being copied " << farmer_temp[i].price << " " << farmer_temp[i].milk << " , i: " << i << endl;
    }
   
   
}

Jeg har lavet en lille mergesort funktion som sorter et array af structs efter structmedlemmet pris, men når jeg printer det sorterede array får jeg en del dubletter:

Her er pristallene før de bliver sortet:

5
9
12
4
6
3
19

og her efter:

5
5
5
12
3
6
3

Er der nogle der kan spotte fejlen?
Avatar billede pidgeot Nybegynder
15. november 2005 - 17:29 #1
Jeg tror nok
  mergesort(mid+1, r);
skal være
  mergesort(mid, r);

Men lad mig lige kontrollere op mod mit tilsvarende C# program.
Avatar billede snailwalker Nybegynder
15. november 2005 - 17:31 #2
ifølge det pseudokode eksempel jeg har kodet udfra skal det være

mergesort(l,mid);
mergesort(mid+1,r);
Avatar billede pidgeot Nybegynder
15. november 2005 - 18:11 #3
Hvis jeg ændrer min kode til at bruge din mergesort(), får jeg det her resultat:

Before sort:
35 22 94 31 99 35 8 67 57 36 12 74 13 46 43 54 8 19 55 97 4 50 4 38 25
After sort:
8 13 8 19 22 31 35 35 36 12 43 46 54 55 57 67 74 94 97 4 4 25 38 50 99

Modsat min kode, der giver det her:

Before sort:
70 81 11 17 98 47 72 24 25 23 77 36 63 71 56 9 31 80 0 32 34 89 11 8 77
After sort:
0 8 9 11 11 17 23 24 25 31 32 34 36 47 56 63 70 71 72 77 77 80 81 89 98

Forskellen er at min mergesort() (omdannet til C++) ser sådan ud:
void mergesort (int l, int r)
{
    if (r-1 > l)
    {
        int mid = (l+r)/2;
        mergesort(l, mid);
        mergesort(mid, r);
        merge (l,mid,r);
    }
    return;
}
Avatar billede snailwalker Nybegynder
15. november 2005 - 22:21 #4
Det blev lidt bedre. Med det nye output får jeg:

3 5 6 3 9 9 3

med input

5 9 12 4 6 3 19

så det hjalp stadig ikke helt :S
Avatar billede pidgeot Nybegynder
15. november 2005 - 22:29 #5
Hm... Jeg er ikke sikker, men du kunne jo prøve at udskifte

if (i>mid)
    {
      //....
    }

med en oversættelse af det jeg bruger. Jeg bruger selv while her, men umiddelbart virker det nu som om din kode gør det samme som min. (Men okay, jeg er ikke nogen ørn til C/C++, så jeg kan jo tage fejl.)

Dette burde være korrekt:
while (i != mid)
{
  farmer_temp[k].price = farmers[i].price;
  farmer_temp[k].milk = farmers[i].milk;
  i++; k++;
}
while (j != end)
{
  farmer_temp[k].price = farmers[j].price;
  farmer_temp[k].milk = farmers[j].milk;
  j++; k++;
}
Avatar billede snailwalker Nybegynder
15. november 2005 - 22:31 #6
hmm erstattede min kode:

if (i>mid)
    {
        for (; j<=r; j++, k++)
        {
            farmer_temp[k].price = farmers[j].price;
            farmer_temp[k].milk = farmers[j].milk;
        }
    }
    else
    {
        for (; i<=mid; i++, k++)
        {
            farmer_temp[k].price = farmers[i].price;
            farmer_temp[k].milk = farmers[i].milk;
        }
    }

med det du forslog, men nu gik den helt i stå og printede slet ikke noget :S
Avatar billede snailwalker Nybegynder
15. november 2005 - 22:35 #7
ændrede lige din kode til

while (i < mid) for i kan jo godt være større end mid?

og så virkede den!
Avatar billede snailwalker Nybegynder
15. november 2005 - 22:36 #8
altså ikke at den sorterede dem rigtigt, fik samme output som før, men den skrev da trods alt noget ud!
Avatar billede pidgeot Nybegynder
15. november 2005 - 22:40 #9
Som sagt er jeg ikke den store haj til C/C++, så jeg overser måske noget. Du er velkommen til at kigge på min C# kildekode og se om du kan få noget ud af det: http://pastebin.com/430898

Metoderne du skal kigge på er MergeSort og DoSort. DoSort er det der svarer til Merge - jeg valgte at kalde den DoSort fordi Merge virkede som et forkert navn. :P
Avatar billede snailwalker Nybegynder
15. november 2005 - 23:54 #10
Fik den til at virke nu. Smider du lige et svar?

Tusind tak for hjælpen :)
Avatar billede pidgeot Nybegynder
15. november 2005 - 23:56 #11
Det var så lidt :)

Må man få at vide hvad der var galt? Kunne godt lide at vide hvad jeg missede, det kan jo være jeg kan bruge det senere hen :)
Avatar billede snailwalker Nybegynder
15. november 2005 - 23:59 #12
Jeg ændrede min første whileløkke i merge funktionen så den var

while (i<mid && j<r)
    {

i stedet for

while (i<=mid && j<= r)

så virkede det :)
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester