Normalerweise unterrichte ich in der Jahrgangsstufe 12 nur die Grundkurse. Im Schuljahr 2018/19 musste ich auch den Leistungskurs unterrichten. Hier geht es im Wesentlichen um die Modellierung mit UML und die Implementation, bei uns in C#.

Wichtige Themen sind hierbei der Begriff „Objekt“ und „Klasse“. Darauf aufbauend geht es um die Beziehungen zwischen Klassen wie Vererbung, Assoziation, Aggregation und Komposition und deren Implementation in C#.

Zur Realisierung von 1-zu-N-Beziehungen sind außer den Arrays aich generische Container-Klassen ein Thema. Wie solch ein „Abstrakter Datentyp“ (ADT) List, Stack oder Queue arbeitet, demonstriere ich mit der Projektmappe Generics. Hierin sind drei eigene Implementationen dieser Container in Form einer Template-Klasse implementiert.
Wer sich das mal ansehen will, findet nachfolgend die Visual-Studio-Projektmappe.

Im Hinblick auf das Suchen und Sortieren wird auch das Thema „Komplexität von Algorithmen“ angesprochen.

Für das Thema „Suchen“ (lineares und binäres Suche) sowie für das Sortieren habe ich Klassen entworfen und Testprogramme geschrieben.
Sowohl die Klassen als auch die Projektmappen stehen hinter den PDFs zum Download bereit.

Zur Demonstration der Sortierverfahren habe ich ein GUI-Programm geschrieben, welche die Algorithmen animiert darstellt. Hier ein Screenshot dazu:

Animation von Sortierverfahren
Vier Sortierverfahren demonstriert

Nachfolgend mein Unterrichtsskript:

using System;

namespace Lineare_Suche
{
    // Der Datentyp T muss das das Interface
    // IComparable implementieren
    public static class LinearSeek<T> where T:IComparable
    {
        public static int FoundIndex { get; private set; }

        public static bool IsFound { get; private set; }

        public static bool Seek(T[] array, T seekelement)
        {
            // Guard Clauses
            if (array == null) throw new ArgumentNullException("array");
            if (seekelement == null) throw new ArgumentNullException("seekelement");

            FoundIndex = 0;
            IsFound = false;

            foreach (T item in array)
            {
                if (item.CompareTo(seekelement) == 0)
                {
                    IsFound = true;
                    break;
                }
                FoundIndex++;
            }
            return IsFound;
        }
    }
}
using System;

namespace Binäre_Suche
{
    public static class BinarySeek<T> where T : IComparable
    {
        public static int FoundIndex { get; private set; }

        public static bool IsFound { get; private set; }

        public static int SeekSteps { get; private set; }

        private static int mitte;

        public static bool SeekIterative(T[] array, T seekelement)
        {
            // Guard Clauses
            if (array == null) throw new ArgumentNullException("array");
            if (seekelement == null) throw new ArgumentNullException("seekelement");

            FoundIndex = 0;
            IsFound = false;
            SeekSteps = 0;

            int unteregrenze = 0;
            int oberegrenze = array.Length - 1;

            while (unteregrenze <= oberegrenze)
            {
                mitte = unteregrenze + (oberegrenze - unteregrenze) / 2;

                // array[mitte] < seekelement --> -1
                // array[mitte] > seekelement --> 1
                // array[mitte] = seekelement --> 0

                int rc = array[mitte].CompareTo(seekelement);
                if (rc == 1)
                    oberegrenze = mitte - 1;
                else if (rc == -1)
                    unteregrenze = mitte + 1;
                else
                {
                    FoundIndex = mitte;
                    IsFound = true;
                    break;
                }
                SeekSteps++;
            }
            return IsFound;
        }

        public static bool SeekRecursive(T[] array, T seekelement)
        {
            // Guard Clauses
            if (array == null) throw new ArgumentNullException("array");
            if (seekelement == null) throw new ArgumentNullException("seekelement");

            FoundIndex = 0;
            IsFound = false;

            return BinarySearch(array, 0, array.Length - 1, seekelement);
        }

        private static bool BinarySearch(T[] array, int untereGrenze, int obereGrenze, T seekelement)
        {
            if (untereGrenze > obereGrenze)
                return false;
            mitte = untereGrenze + (obereGrenze - untereGrenze) / 2;

            // array[mitte] < seekelement --> -1
            // array[mitte] > seekelement --> 1
            // array[mitte] = seekelement --> 0

            int rc = array[mitte].CompareTo(seekelement);
            if (rc == 1)
            {
                SeekSteps++;
                return BinarySearch(array, untereGrenze, mitte - 1, seekelement);
            }
                
            if (rc == -1)
            {
                SeekSteps++;
                return BinarySearch(array, mitte + 1, obereGrenze, seekelement);
            }

            FoundIndex = mitte;
            IsFound = true;
            return IsFound;
        }
    }
}
using System;

namespace BubbleSort
{
    public enum Direction
    {
        Ascend, Descend
    };

    public struct BubblesortStatistics
    {
        public long Steps;
        public long Exchanges;
    }

    // Der Datentyp T muss das das Interface
    // IComparable implementieren
    public static class Bubblesort<T> where T : IComparable
    {
        private static Direction direction;
        public static Direction Direction
        {
            get { return direction; }
            set { direction = value; }
        }

        private static BubblesortStatistics statistics;

        static Bubblesort()
        {
            direction = Direction.Ascend;
        }

        public static BubblesortStatistics Sort(T[] data, Direction _direction)
        {
            direction = _direction;
            return Sort(data);
        }

        public static BubblesortStatistics Sort(T[] data)
        {
            // Guard Clause
            if (data == null) throw new ArgumentNullException("data");

            foreach (T item in data)
            {
                if (item == null) throw new NullReferenceException();
            }

            statistics.Steps = 0;
            statistics.Exchanges = 0;

            // Temporäres Speicherelement
            // für den Tauschvorgang
            T tmp;
            for (int i = data.Length; i > 1; i--)
            {
                for (int j = 0; j < i - 1; j++)
                {
                    statistics.Steps++;
                    if (direction == Direction.Ascend)
                    {
                        // Aufsteigend sortieren
                        if (data[j].CompareTo(data[j + 1]) > 0)
                        {
                            statistics.Exchanges++;
                            // Es muss getauscht werden
                            tmp = data[j];
                            data[j] = data[j + 1];
                            data[j + 1] = tmp;
                        }
                    }
                    else
                    {
                        // Absteigend sortieren
                        if (data[j].CompareTo(data[j + 1]) < 0)
                        {
                            statistics.Exchanges++;
                            // Es muss getauscht werden
                            tmp = data[j];
                            data[j] = data[j + 1];
                            data[j + 1] = tmp;
                        }
                    }
                }
            }

            return statistics;
        }
    }
}
using System;

namespace InsertionSort
{
    public enum Direction
    {
        Ascend, Descend
    };

    public static class Insertionsort<T> where T : IComparable
    {
        private static int sizeOfArray;

        private static Direction direction;
        public static Direction Direction
        {
            get { return direction; }
            set { direction = value; }
        }

        static Insertionsort()
        {
            direction = Direction.Ascend;
        }

        public static void Sort(T[] data, Direction _direction)
        {
            direction = _direction;
            Sort(data);
        }

        public static void Sort(T[] data)
        {
            sizeOfArray = data.Length;

            T t;
            for (int i = 1; i < sizeOfArray; i++)
            {
                int j = i;
                t = data[j];

                if (direction == Direction.Ascend)
                {
                    while (j > 0)
                    {
                        if (data[j - 1].CompareTo(t) > 0)
                        {
                            data[j] = data[j - 1];
                            j -= 1;
                        }
                        else
                            break;
                    }
                }
                else
                {
                    while ((j > 0) && (data[j - 1].CompareTo(t) < 0))
                    {
                        data[j] = data[j - 1];
                        j -= 1;
                    }
                }

                data[j] = t;
            }
        }
    }
}
using System;

namespace QuickSort
{
    public enum Direction
    {
        Ascend, Descend
    };

    public enum Pivot
    {
        First, Middle, Last
    };


    // basierend auf
    // www.iti.fh-flensburg.de/lang/algorithmen/sortieren/quick/quick.htm
    public static class Quicksort<T> where T : IComparable
    {
        private static int sizeOfArray;

        private static Direction direction;
        public static Direction Direction
        {
            get { return direction; }
            set { direction = value; }
        }

        private static Pivot pivot;
        public static Pivot Pivot
        {
            get { return pivot; }
            set { pivot = value; }
        }

        private static long RecursionDeepness { get; set; }

        static Quicksort()
        {
            direction = Direction.Ascend;
            pivot = Pivot.Middle;
        }

        public static long Sort(T[] data, Direction _direction)
        {
            RecursionDeepness = 0;
            direction = _direction;
            return Sort(data);
        }

        public static long Sort(T[] data, Direction _direction, Pivot _pivot)
        {
            RecursionDeepness = 0;
            direction = _direction;
            pivot = _pivot;
            return Sort(data);
        }

        public static long Sort(T[] data)
        {
            // Guard clauses
            if (data == null) throw new ArgumentNullException("data");

            foreach (T item in data)
            {
                if (item == null) throw new NullReferenceException();
            }

            sizeOfArray = data.Length;
            QuickSort(data, 0, sizeOfArray - 1);

            return RecursionDeepness;
        }

        private static void QuickSort(T[] data, int untereGrenze, int obereGrenze)
        {
            RecursionDeepness++;

            int i = untereGrenze, j = obereGrenze;

            T x = default(T);

            if (pivot == Pivot.First)
            {
                // Vergleichselement (Pivot) x ist erstes Element
                x = data[untereGrenze];
            }
            else if (pivot == Pivot.Middle)
            {
                // Vergleichselement (Pivot) x liegt in der Mitte
                x = data[untereGrenze + (obereGrenze - untereGrenze) / 2];
            }
            else if (pivot == Pivot.Last)
            {
                // Vergleichselement (Pivot) x ist letztes Element
                x = data[obereGrenze];
            }

            //  Aufteilung
            while (i <= j)
            {
                if (direction == Direction.Ascend)
                {
                    while (data[i].CompareTo(x) == -1) i++;
                    while (data[j].CompareTo(x) == 1) j--;
                    if (i <= j)
                    {
                        Exchange(data, i, j);
                        i++; j--;
                    }

                }
                else
                {
                    while (data[i].CompareTo(x) == 1) i++;
                    while (data[j].CompareTo(x) == -1) j--;
                    if (i <= j)
                    {
                        Exchange(data, i, j);
                        i++; j--;
                    }
                }
            }

            // Rekursion
            if (untereGrenze < j) QuickSort(data, untereGrenze, j);
            if (i < obereGrenze) QuickSort(data, i, obereGrenze);
        }

        private static void Exchange(T[] data, int i, int j)
        {
            T t = data[i];
            data[i] = data[j];
            data[j] = t;
        }
    }
}
using System;

namespace ShellSort
{
    public enum Direction
    {
        Ascend, Descend
    };

    // basierend auf
    // www.iti.fh-flensburg.de/lang/algorithmen/sortieren/shell/shell.htm
    public static class Shellsort<T> where T : IComparable
    {
        private static int sizeOfArray;

        private static Direction direction;
        public static Direction Direction
        {
            get { return direction; }
            set { direction = value; }
        }

        static Shellsort()
        {
            direction = Direction.Ascend;
        }

        public static void Sort(T[] data, Direction _direction)
        {
            direction = _direction;
            Sort(data);
        }

        public static void Sort(T[] data)
        {
            sizeOfArray = data.Length;

            int i, j, columns;
            T t;

            //Spaltenanzahl
            int[] cols = {1391376, 463792, 198768, 86961, 33936,
                          13776, 4592, 1968, 861, 336, 112, 48,
                          21, 7, 3, 1};

            foreach (int colvalue in cols)
            {
                columns = colvalue;
                for (i = columns; i < sizeOfArray; i++)
                {
                    j = i;
                    t = data[j];

                    if( direction==Direction.Ascend)
                    {
                        while ((j >= columns) && (data[j - columns].CompareTo(t) > 0))
                        {
                            data[j] = data[j - columns];
                            j = j - columns;
                        }
                    }
                    else
                    {
                        while ((j >= columns) && (data[j - columns].CompareTo(t) < 0))
                        {
                            data[j] = data[j - columns];
                            j = j - columns;
                        }
                    }

                    data[j] = t;

                }
            }
        }
    }
}