95 lines
2.7 KiB
Go
95 lines
2.7 KiB
Go
package ith_element
|
|
|
|
/* ---------------------------------------------------------------- *
|
|
* IMPORTS
|
|
* ---------------------------------------------------------------- */
|
|
|
|
import (
|
|
"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.Debug("Das i. kleinste Element wurde gefunden.")
|
|
return minValue
|
|
} else {
|
|
logging.Debug("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.Debug("Es gibt i-1 Elemente vor p=%[1]v. ==> i. kleinste Element = p", p)
|
|
return p
|
|
} else if len(Ll) >= i {
|
|
logging.Debug("Es gibt >= i Elemente vor p=%[1]v. ==> Suche in linker Hälfte!", p)
|
|
return FindIthSmallestDC(Ll, i)
|
|
} else {
|
|
logging.Debug("Es gibt < i-1 Elemente vor p=%[1]v. ==> Suche in rechter Hälfte!", p)
|
|
i = i - (len(Ll) + 1)
|
|
return FindIthSmallestDC(Lr, i)
|
|
}
|
|
}
|