Smoothsort Implementierung

Hallo, ich möchte Smoothsort implantieren, weil es für sortierte Listen so schnell ist, und es mit Quicksort vergleichen, aber ich weiß nicht wie. Stabilität ist mir ganz egal, lustig wenn mal was nicht stimmt.

Wie kann ich nur Listen sortieren, deren Objekte Comparable sind? Stichwort: generis.

Wie kann ich Heapfy und Heap-up/-down machen?

Könntet ihr mir den Anfang schreiben oder Tipps/Tricks geben? Das wäre supi.

Euer Cyborg D:

Edit: Gerne möchte ich natürlich auch hierauf verweisen: algorithm - Why isn’t smoothsort more common? - Stack Overflow

Warum ist es nicht mehr common?

Würd ich garnicht unbedingt machen. Nutze lieber gleich einen extra mitgegebenen Comparator.
Nachfolgend die möglichen Signaturen der Methoden für beide Fälle:

public static <T> void smoothSortWithComparator(List<T> list, Comparator<? super T> c) {...}```
Das hab ich übrigens aus der Klasse java.util.Collections abgeschrieben. Wenn Du Dich mit Collections, Sortieren und som Kram beschäftigst, solltest Du evtl von selbst drauf gekommen sein, mal in den Quellcode des JDK zu schauen.

fertigen Java-Code zu Smoothsort gibts auch im Internet,
schon gesehen und aus bestimmen Gründen abzulehnen, die hier auch nicht zu nennen sind,
oder noch nicht gesucht/ gefunden?

[QUOTE=SlaterB]fertigen Java-Code zu Smoothsort gibts auch im Internet,
schon gesehen und aus bestimmen Gründen abzulehnen, die hier auch nicht zu nennen sind,
oder noch nicht gesucht/ gefunden?[/QUOTE]

Doch, der 1. ist komplett, arbeitet aber nur mit byte; der 2. arbeitet mit int, benötigt aber noch viele andere Klassen zur “Überwachung”, die ich aber nicht brauche; der 3. hat eine von drei Methoden implementiert und an die anderen //TODO markiert; der 4. hat eine PDF erstellt, aus der ich den Code nicht einfach übernehmen kann und wo ich gerade am lesen bin.

In dem du Smoothsort implementierst - verzichte auf die Implantation.

Machs wie Java selber:

sort(T[] a, Comparator<? super T> c)

Sorts the specified array of objects according to the order induced by the specified comparator.

In dem du es machst? Was genau ist die Frage - ohne Code ist das Blödsinn.

Nein, und der Algorithmus ist eben etwas komplizierter als Quicksort. Musst dich halt hinsetzen und das in Ruhe ausprogrammieren.

Smoothsort Demystified

Danke, ich möchte hier folgendes einmal von googlecode verlinken:


import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.ListIterator;
import java.util.RandomAccess;

/**
 * Sorts arrays and collections using the <a href="http://en.wikipedia.org/wiki/Smoothsort">
 * Smoothsort</a> algorithm. This algorithm is very similar to heap sort, but it uses a Leonardo
 * heap instead of a binary heap. The way the Leonardo heap is represented in-place in the array
 * or list enables sorting operations to take advantage of partially sorted data (data where there
 * are runs of sorted elements). This gives the algorithm a linear best case.
 *
 * @author Joshua Humphries (jhumphries131@gmail.com)
 */
// TODO: implement me!
// TODO: javadoc
public final class SmoothSort {

   /** Prevents instantiation. */
   private SmoothSort() {
   }
   
   private static final int LEONARDO_NUMBERS_LEN;
   private static final int[] LEONARDO_NUMBERS;
   
   static {
      int lp2 = 1;
      int lp1 = 1;
      ArrayList<Integer> lnums = new ArrayList<Integer>();
      lnums.add(lp2); lnums.add(lp1);
      while (true) {
         long lnext = lp2 + lp1 + 1;
         if (lnext > Integer.MAX_VALUE) {
            // done
            break;
         }
         int lp0 = (int) lnext;
         lnums.add(lp0);
         lp2 = lp1;
         lp1 = lp0;
      }
      
      LEONARDO_NUMBERS_LEN = lnums.size();
      LEONARDO_NUMBERS = new int[LEONARDO_NUMBERS_LEN];
      for (int i = 0, j = 1; i < LEONARDO_NUMBERS_LEN; i++, j <<= 1) {
         LEONARDO_NUMBERS** = lnums.get(i);
      }
   }
   
   /**
    * Describes the structure of the in-place heap in the list. Since a leonardo heap is a
    * set of trees, this structure tracks what order trees are in the heap and where.
    * 
    * @author Joshua Humphries (jhumphries131@gmail.com)
    */
   private static class HeapStructure {
      /**
       * Bitmask of which order trees are present in the heap.
       */
      long trees;
      
      /**
       * The order of the least-significant bit in trees mask.
       */
      int offset;
      
      /**
       * Provides visibility w/out need for synthetic accessor.
       */
      HeapStructure() {
      }
   }
   
   private static <T> void siftDown(List<T> list, Comparator<? super T> comp, int root,
         int treeOrder) {
      // TODO
   }
   
   private static <T> void rectifyRoots(List<T> list, Comparator<? super T> comp, int start,
         int end, HeapStructure structure) {
      // TODO
   }
   
   private static <T> void addToHeap(List<T> list, Comparator<? super T> comp, int start, int end,
         int listLength, HeapStructure structure) {
      if ((structure.trees & 1) != 0) {
         // Due to we encode this bitset, if first bit is zero, heap is empty.
         // So we add a leonardo tree of order 1 (size = 1)
         structure.trees |= 1;
         structure.offset = 1;
      } else if ((structure.trees & 3) == 3) {
         // If last two trees in the heap are sequential, we can trivially merge them and
         // and new item is the root of merged tree.
         structure.trees >>= 2; // shift away lowest two orders
         structure.offset += 2;
         structure.trees |= 1; // and replace with next highest order
      } else if (structure.offset == 1) {
         // Otherwise, if smallest tree is order 1 (structure offset is effectively the order of the
         // smallest tree), then we add a tree of order 0.
         structure.trees <<= 1; // make room for new order of tree
         structure.trees |= 1;
         structure.offset = 0;
      } else {
         // Final case: add new tree of order 1
         structure.trees <<= structure.offset - 1; // make room to push in bit at order 1
         structure.trees |= 1;
         structure.offset = 1;
      }
      // If we know this tree is at its final size, then we can rectify the the tree root with the
      // roots of the prior trees in the heap. Otherwise, we just do a sift-down.
      switch (structure.offset) {
         case 0:
            // if the last heap has order 0, we only rectify if it's the very last element in list
            if (end == listLength - 1) {
               rectifyRoots(list, comp, start, end, structure);
               return;
            }
            break;
            
         case 1:
            // if the last heap has order 1, we can rectify if it's the last element in the list or
            // if it's the next-to-last element in list and won't be merged when we add last element
            if (end == listLength - 1 || (end == listLength - 2 && (structure.trees & 2) == 0)) {
               rectifyRoots(list, comp, start, end, structure);
               return;
            }
            break;
            
         default:
            // otherwise, if there is insufficient room in the list for this tree to be merged
            // into next order tree, then we can rectify
            int elementsRemaining = listLength - 1 - end;
            int elementsNeededForNextOrderTree = LEONARDO_NUMBERS[structure.offset - 1] + 1;
            if (elementsRemaining < elementsNeededForNextOrderTree) {
               rectifyRoots(list, comp, start, end, structure);
               return;
            }
            break;
      }
      
      siftDown(list, comp, end, structure.offset);
   }
   
   private static <T> HeapStructure heapify(List<T> list, Comparator<? super T> comp) {
      HeapStructure structure = new HeapStructure();
      for (int i = 0, len = list.size(); i < len; i++) {
         addToHeap(list, comp, 0, i, len, structure);
      }
      return structure;
   }
   
   private static <T> void rebalance(List<T> list, Comparator<? super T> comp,
         HeapStructure structure, int length) {
      // TODO
   }
   
   private static <T> void sortInPlace(List<T> list, Comparator<? super T> comp) {
      HeapStructure structure = heapify(list, comp);
      for (int i = list.size() - 1; i > 0; i--) {
         rebalance(list, comp, structure, i);
      }
   }
   
   public static <T> void sort(List<T> list) {
      sort(list, CollectionUtils.NATURAL_ORDERING);
   }
   
   public static <T> void sort(List<T> list, Comparator<? super T> comp) {
      if (list instanceof RandomAccess) {
         sortInPlace(list, comp);
      } else {
         ArrayList<T> l = new ArrayList<T>(list);
         sortInPlace(list, comp);
         for (ListIterator<T> srcIter = l.listIterator(), destIter = list.listIterator();
               srcIter.hasNext();) {
            destIter.next();
            destIter.set(srcIter.next());
         }
      }
   }
   
   public static <T> void sort(T[] array) {
      sort(Arrays.asList(array));
   }

   public static <T> void sort(T[] array, Comparator<? super T> comp) {
      sort(Arrays.asList(array), comp);
   }

   public static void sort(int[] array) {
      // TODO
   }

   public static void sort(int[] array, Comparator<? super Integer> comp) {
      // TODO
   }

   public static void sort(byte[] array) {
      // TODO
   }
   
   public static void sort(byte[] array, Comparator<? super Byte> comp) {
      // TODO
   }
   
   public static void sort(short[] array) {
      // TODO
   }
   
   public static void sort(short[] array, Comparator<? super Short> comp) {
      // TODO
   }
   
   public static void sort(char[] array) {
      // TODO
   }
   
   public static void sort(char[] array, Comparator<? super Character> comp) {
      // TODO
   }
   
   public static void sort(long[] array) {
      // TODO
   }
   
   public static void sort(long[] array, Comparator<? super Long> comp) {
      // TODO
   }
   
   public static void sort(float[] array) {
      // TODO
   }
   
   public static void sort(float[] array, Comparator<? super Float> comp) {
      // TODO
   }
   
   public static void sort(double[] array) {
      // TODO
   }

   public static void sort(double[] array, Comparator<? super Double> comp) {
      // TODO
   }
}

Gut, er erstellt die Leonardo Nummern (static), hat eine bestimmte HeapStructure, kann „quasi“ eine Liste mit beliebigem Inhalt sortieren, so das war’s dann, denn: siftDown(), rectifyRoots(), rebalance(), HeapStructure { usw. weiß ich nicht, wie zu implementieren.

Ist dieser Algo sehr schwer im Vergleich zu QS? Bei einer ArrayList hätte ich schon einen Heap, Reihe i, Spalte j : i^2 + j . (so ungefähr)

Das ist keine Frage, sondern eine Feststellung

Auf jeden Fall „schwerer“

Sortiere zuerst mal: gobbledygook, gibberish, claptrap, nonsense, rubbish, balderdash, blather, garbage

Hör auf, der macht das wirklich. :wink:

Ich komm’ damit nicht weiter, ich muss damit nicht weiterkommen, ich lass es.

Eine weiße Entscheidung du getroffen hast mein Junger Padawan.
Entweder es interessiert dich, dann ließt du dich in die Thematik ein, oder es interessiert dich eh nicht und du lässt es bleoben. Scheinbar der einfache Weg, kann ich nicht, will ich nicht, mach ich nicht