package ith_element /* ---------------------------------------------------------------- * * IMPORTS * ---------------------------------------------------------------- */ import ( "fmt" "ads/internal/core/logging" "ads/internal/core/metrics" "ads/internal/core/utils" ) /* ---------------------------------------------------------------- * * GLOBAL VARIABLES/CONSTANTS * ---------------------------------------------------------------- */ // /* ---------------------------------------------------------------- * * ALGORITHM find ith smallest * ---------------------------------------------------------------- */ /* Inputs: L = Liste von Zahlen, i = Ordinalzahl Annahmen: - L enthält keine Duplikate. - L enthält mindestens i Elemente. Outputs: Wert des i. kleinste Element in L. Beachte 1.kleinstes <==> Minimum. */ func FindIthSmallest(L []int, i int) int { n := len(L) // extrahiere Wert + Index des Minimums - bedarf n Schritte metrics.AddTimeCost(n) index := utils.ArgMinInt(L) minValue := L[index] // Falls i = 1, dann wird das Minimum gesucht, sonst Minimum entfernen und nach i-1. Element suchen if i == 1 { logging.LogDebug("Das i. kleinste Element wurde gefunden.") return minValue } else { logging.LogDebug(fmt.Sprintf("Entferne Minimum: %[1]v.", minValue)) i = i - 1 L_ := utils.PopIndexListInt(L, index) // entferne Element mit Index = index return FindIthSmallest(L_, i) } } /* ---------------------------------------------------------------- * * ALGORITHM find ith smallest (D & C) * ---------------------------------------------------------------- */ /* Inputs: L = Liste von Zahlen, i = Ordinalzahl Annahmen: - L enthält keine Duplikate. - L enthält mindestens i Elemente. Outputs: Wert des i. kleinste Element in L. Beachte 1.kleinstes <==> Minimum. */ func FindIthSmallestDC(L []int, i int) int { metrics.AddTimeCost() p := L[len(L)-1] // NOTE: Pivotelement kann beliebig gewählt werden // Werte in L in linke und rechte Teillisten um das Pivotelement aufteilen: Ll := []int{} // wird alle Elemente in L < p enthalten Lr := []int{} // wird alle Elemente in L > p enthalten for i := 0; i < len(L); i++ { x := L[i] if x < p { Ll = append(Ll, x) } else if x > p { Lr = append(Lr, x) } } // Fallunterscheidung: if len(Ll) == i-1 { logging.LogDebug(fmt.Sprintf("Es gibt i-1 Elemente vor p=%[1]v. ==> i. kleinste Element = p", p)) return p } else if len(Ll) >= i { logging.LogDebug(fmt.Sprintf("Es gibt >= i Elemente vor p=%[1]v. ==> Suche in linker Hälfte!", p)) return FindIthSmallestDC(Ll, i) } else { logging.LogDebug(fmt.Sprintf("Es gibt < i-1 Elemente vor p=%[1]v. ==> Suche in rechter Hälfte!", p)) i = i - (len(Ll) + 1) return FindIthSmallestDC(Lr, i) } }