Laden...

Bubblesort mit generics

Erstellt von Zoomy vor 15 Jahren Letzter Beitrag vor 15 Jahren 4.554 Views
Z
Zoomy Themenstarter:in
22 Beiträge seit 2009
vor 15 Jahren
Bubblesort mit generics

Hallo Forum!

Ich programmiere mittlerweile auf Arbeit eine Menge und stelle immer wieder fest, das man den ein oder anderen Algorithmus, den man im Studium gelernt hat auch dort wieder verwenden kann.
Nun hab ich gedacht, ich schreibe mir eine Klasse, die diese Algorithmen umfasst.
Ich wollte genauso schön einfach, wie im Studium auch, zunächst mit dem Bubblesort anfangen.
Damit er nicht Typen abhängig ist, habe ich gedacht ich schreibe ihn mit einem generic.
Das ganze sieht dann so aus:


public static void BubbleSort<typ>(typ[] feld)
{
    int nr =0;
    bool sort;
    typ tmp;
    do
    {
        sort = true;
        for (int i = 0; i < feld.Length - nr; i++)
        {
            if (feld[i] > feld[i + 1])                          //<- Fehler
            {
                sort = false;
                tmp = feld[i + 1];
                feld[i + 1] = feld[i];
                feld[i] = tmp;
             }
         }
         nr++;
    } while (!sort);
}

Nun habe ich festgestellt, das beim größer Vergleich ein Fehler auftritt.
Der Operator ">" kann nicht auf Operanden vom Typ "typ" und "typ" angewendet werden.
Kann mir da jemand helfen, das zu umgehen?

Würde mich sehr freuen. Besten dank schon mal.

A
138 Beiträge seit 2007
vor 15 Jahren

Hallo,
du musst typ auf Typen einschränken, die das Interface IComparable implementieren, denn beliebige Objekte lassen sich nicht vergleichen bzw. sortieren ([1]).
Dies geht dann mit where:
BubbleSort<typ> where typ : IComparable
(ich weiß nicht ob es auch mit static Methoden so geht)

Dann statt > oder o.ä. muss du ((IComparable)object).CompareTo() verwenden.

[1] Hat man z.B. eine Klasse für die komplexen Zahlen, dann lassen sich diese nicht (sinnvoll/eindeutig) sortieren, da die komplexen Zahlen nicht geordnet sind.
Ebenso kann man sehr sehr komplexe Objekte nur schwer sortieren.

3.971 Beiträge seit 2006
vor 15 Jahren

Generics sind leider nicht im Vergleich zu C++ Templates stark in Ihren Möglichkeiten eingeschränkt. Entweder du machst es wie Andovos beschreibt, mit den ICompareable oder du machst deine Helper-Klasse abstract und implementierst eine Funktion zum Vergleichen, die entsprechend implementiert werden muss.

Es gibt 3 Arten von Menschen, die die bis 3 zählen können und die, die es nicht können...

Z
Zoomy Themenstarter:in
22 Beiträge seit 2009
vor 15 Jahren

Wow das ging ja echt schnell.
Ich werd es mal versuchen. Vielen dank!

Z
Zoomy Themenstarter:in
22 Beiträge seit 2009
vor 15 Jahren

Hallo!

Nach dem ich es gestern noch ausprobiert habe, will ich heute noch meine funktionsfähige Lösung präsentieren.
Ob das nun die beste Lösung ist, weiß ich nicht. Ich hätte eigentlich lieber die Methode anstatt der Klasse als generic, aber so funktioniert es erstmal 😉


public class FabisAlgorithmen<typ> : IComparable<typ>
{
        
    int IComparable<typ>.CompareTo(typ t)
    {
        return ((IComparable)this).CompareTo(t);
    }

    public static void BubbleSort(typ[] feld)
    {
         int nr =1;
         bool sort;
         typ tmp;
         do
         {
             sort = true;
             for (int i = 0; i < feld.Length - nr; i++)
             {
                 if (((IComparable)feld[i]).CompareTo(feld[i + 1])>0)
                 {
                     sort = false;
                     tmp = feld[i + 1];
                     feld[i + 1] = feld[i];
                     feld[i] = tmp;
                 }
              }
              nr++;
          } while (!sort);
     }
}

Sollte jemand noch einen Verbesserungsvorschlag haben, bin ich für alles offen.
Ansonsten hoffe ich, das es vlt jemanden den noch weiter hilft, den im Internet habe ich sonst zu dem Thema nicht alt so viel gefunden.

Einen schönen Sonntag an alle!

1.200 Beiträge seit 2007
vor 15 Jahren

Du kannst auch auf die Methode eine Einschränkung setzen:

public static void BubbleSort<typ>(typ[] feld) where typ : IComparable
{
     //code
}

Shift to the left, shift to the right!
Pop up, push down, byte, byte, byte!

YARRRRRR!

Z
Zoomy Themenstarter:in
22 Beiträge seit 2009
vor 15 Jahren

Stimmt, das ist noch viel besser!

Das war dass, was Andavos schon am Anfang meinte, ich bloß nicht richtig verstanden habe, bzw. aus unwissenheit nicht umgesetzt habe.

Viel Dank an alle!

1.200 Beiträge seit 2007
vor 15 Jahren

Ist ja ok, wenn du durch die Implementierung deiner Algorithmen lernen willst. Aber denke dran, dass du, wenn du ein Produkt erstellen willst, besser auf Array.Sort zurückgreifst.

Shift to the left, shift to the right!
Pop up, push down, byte, byte, byte!

YARRRRRR!

Z
Zoomy Themenstarter:in
22 Beiträge seit 2009
vor 15 Jahren

Ja die Methode habe ich auch kennengelernt, als ich nach dem Interface ICloneable gesucht habe.
Mir ging es auch mehr um andere Algorithmen als den Bubblesort. Der hat sich bloß als Anfangsbeispiel angeboten, weil man den nun schon einige male in verschiedenen Sprachen programmiert hat.

Dank eurer Hilfe habe ich aber wirklich einiges gelernt, also hat es sich aufjedenfall gelohnt, vielen dank nochmal 😉

1.361 Beiträge seit 2007
vor 15 Jahren

Hi Zoomy,

vielleicht solltest du auch lieber

public static void BubbleSort<T>(T[] feld) where T: IComparable<T>

nehmen.

Mhh.. vielleicht sollte man auch der Konvention wegen den Typparameter immer in Großbuchstaben schreiben.

Ach und den Cast bei

if (((IComparable)feld[i]).CompareTo(feld[i + 1])>0)

kannst du dir so oder so sparen.

beste Grüße
zommi

3.971 Beiträge seit 2006
vor 15 Jahren

class FabisAlgorithmen<typ> : IComparable<typ>

IComparable gehört auch nicht in deine Hilfsklasse, sondern in die Klassen und Strukturen, die du sortieren willst. Viele Datentypen aus dem .NET Framework implementieren bereits diese Schnittstelle (Int32, Float, Double, Decimal, String, usw.) Bei eigenen Datentypen müsstest du die Schnittstelle entsprechend nachimplementieren.

Es gibt 3 Arten von Menschen, die die bis 3 zählen können und die, die es nicht können...

Z
Zoomy Themenstarter:in
22 Beiträge seit 2009
vor 15 Jahren

Hallo!

Hab eure Beiträge erst jetzt gesehen.

@kleines_eichhoernchen:
Nach dem Hinweis von GMLOD habe ich das so umgeschrieben. Habt ihr beide recht, das ist schöner.

@zommi
Mit dem Cast hast vollkommen recht. Ist mir vorher nicht aufgefallen.
Und wenn ich konsequent bin, muss ich den Typparameter auch groß schreiben.
Auch wenn "T" in der Literatur üblich ist, hab ich mich jetzt für "Typ" entschieden, weil ich es einfach noch lesbarer finde.
(P.S. übrigens schicker name;) und auch ich komme ursprünglich aus Berlin)

Danke euch beiden!

Mein Code sieht nun mittlerweile so aus:


public class FabisAlgorithmen 
{
    public static void BubbleSort<Typ>(Typ[] feld) where Typ : IComparable
    {
         int nr = 1;
         bool sort;
         Typ tmp;
         do
         {
             sort = true;
             for (int i = 0; i < feld.Length - nr; i++)
             {
                 if (feld[i].CompareTo(feld[i + 1]) > 0)
                 {
                     sort = false;
                     tmp = feld[i + 1];
                     feld[i + 1] = feld[i];
                     feld[i] = tmp;
                 }
             }
             nr++;
        } while (!sort);
}

Übrigens will ich noch ein großes Lob an euch alle aussprechen. Im programmieren bin ich recht fit, allerdings programmier ich noch nicht sehr lange in .NET.
Und kenn deswegen viele Möglichkeiten noch nicht. Ihr habt mir alle geholfen ein bisschen besser hinterzusteigen;-)

5.941 Beiträge seit 2005
vor 15 Jahren

Hallo Zoomy

Wenn du nur ein Typparameter hast, solltest du ihn "T" benennen.
Bei mehreren Typparametern gilt dann eine abgeleitete Konvention, bspw.:


public static void Foo<TParameterOne, TParameterTwo>(TParameterOne bar) {
    // ...
}

Gruss Peter

--
Microsoft MVP - Visual Developer ASP / ASP.NET, Switzerland 2007 - 2011