97 lines
2.7 KiB
Go
97 lines
2.7 KiB
Go
|
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)
|
||
|
}
|
||
|
}
|