Initial commit with cleaned history

This commit is contained in:
2024-09-01 18:09:25 +02:00
commit 208004e9d0
273 changed files with 234697 additions and 0 deletions
+63
View File
@@ -0,0 +1,63 @@
/*
(a) hat eine Zeitkomplexität von O(n), wobei n die Anzahl der Elemente in vec ist.
Das liegt daran, dass jede Operation in der for-Schleife in konstanter Zeit ausgeführt wird
und die Schleife genau n-Mal durchlaufen wird.
*/
int vector_summe(vector<int>& vec){
int sum = 0;
for (unsigned i =0; i < vec.size(); i++){
sum +=vec[i];
}
return sum;
}
/*
(b) hat eine Zeitkomplexität von O(n^2), da es zwei verschachtelte Schleifen gibt,
die jeweils bis zur Größe des Vektors laufen.
Dies bedeutet, dass für jedes Element in vec alle Elemente innerhalb des Elementes einmal betrachtet werden,
was zu n*n Operationen führt.
*/
vector<pair<int, int>> pairs(vector<int>& vec){
vector<pair<int, int>> returnpairs;
pair<int, int> p;
for(unsigned i = 0; i<vec.size(); i++){
for(unsigned j=0; j<vec.size(); j++){
p = {vec[i], vec[j]};
returnpairs.push_back(p);
}
}
return returnpairs;
}
/*
(c) Die Eingabegröße n ist die Größe von vec1 und m ist die Größe von vec2.
Zuerst werden die separate Listen, vec1 und vec2, separat sortiert.
Die Zeitkomplexität für das Sortieren von vec1 ist O(n log n) und O(m log m) für das Sortieren von vec2,
da das die Zeitkomplexität von mergesort ist.
Die anschließenden verschachtelten Schleifen, die über die beiden Vektoren iterieren, haben eine Zeitkomplexität von O(n*m),
da jede Kombination aus Elementen von vec1 und vec2 einmal betrachtet wird.
Daher ist die gesamte Zeitkomplexität O(n log n + m log m + n*m).
Die Anzahl der Operationen entspricht im Wesentlichen der Zeitkomplexität.
*/
vector<pair<int, int>> sorted_pairs(vector<int> vec1, vector<int> vec2){
vector<pair<int, int>> returnpairs;
pair<int, int> p;
mergeSort(vec1);
mergeSort(vec2);
for(unsigned i = 0; i < vec1.size(); i++){
for(unsigned j = 0; j < vec2.size(); j++){
p = {vec1[i], vec2[j]};
returnpairs.push_back(p);
}
}
}
+77
View File
@@ -0,0 +1,77 @@
/* Informatik B - Sommersemester 2023
Vorlesung am 12.05.2023
Katharina Klost
Hilfsfunktionen zum Sortieren, nur zusammen mit der sorting.cpp zu compilieren
*/
#include <iostream>
#include <vector>
#include "hilfsfunktionen.hpp"
namespace hf{
void gebe_aus(std::vector<int>& vec, unsigned start, unsigned end){
if(end>vec.size()){
std::cout << vec.size() << " " << end << std::endl;
return;
}
std::cout << vec[start];
for(unsigned k=start+1; k<end; k++){
std::cout << ", " << vec[k];
}
std::cout << std::endl;
}
void swap(std::vector<int>& elems, unsigned i, unsigned j){
if (i>=elems.size() || j >= elems.size()){
return;
}
int tmp = elems[i];
elems[i] = elems[j];
elems[j] = tmp;
}
unsigned minimumIndex(std::vector<int>& elems, unsigned start, unsigned end){
unsigned min = start;
for(unsigned i = start; i<end; i++){
if(elems[i] < elems[min]){
min = i;
}
}
return min;
}
std::vector<int> copy(std::vector<int>& elems, unsigned start, unsigned end){
std::vector<int> returnVec;
for(unsigned i= start; i<end; i++){
returnVec.push_back(elems[i]);
}
return returnVec;
}
bool generator_started = false;
int zufall(int left, int right) {
// Vor der ersten Zufallszahl muss der Zufallsgenerator gestartet werden.
if (!generator_started) {
srandom(time(NULL));
generator_started = true;
}
return left + random() % (right-left);
}
std::vector<int> sortiertes_array(unsigned size, bool aufsteigend) {
std::vector<int> array(size);
for (unsigned i = 0; i < size; i++)
array[i] = aufsteigend * i + (!aufsteigend) * (size - i - 1);
return array;
}
std::vector<int> zufalls_array(unsigned size) {
std::vector<int> array(size);
for (unsigned i = 0; i < size; i++)
array[i] = zufall(0, size);
return array;
}
}
+66
View File
@@ -0,0 +1,66 @@
/* Informatik B - Sommersemester 2023
Vorlesung am 12.05.2023
Katharina Klost
Headerdatei zu den Hilfsfunktionen zum Sortieren
*/
#include <vector>
// #include "telefonbuch.hpp"
namespace hf{
/*
Voraussetzung: 0 <= start <= end < vec.elems()
Ergebnis: Keins
Effekt: Gibt die Elemente des Vektors im Intervall [start,end) aus
*/
void gebe_aus(std::vector<int>& elems, unsigned start, unsigned end);
/*
Voraussetzung: 0<=start<=end < vec.elems()
Ergebnis: Ein vector, mit alle Elemente im Intervall [start, end)
Effekt: Keiner
*/
std::vector<int> copy(std::vector<int>& elems, unsigned start, unsigned end);
/*
Voraussetzung: 0 <= i,j <= elems.size()
Ergebnis: Keins
Effekt: Tauscht die Einträge and Position i und j
*/
void swap(std::vector<int>& elems, unsigned i, unsigned j);
/*
Voraussetzung: Es gilt 0 <= start <= end < elems.size()
Effekt: Keiner
Ergebni: Index des kleinesten Elements zwischen start und end
*/
unsigned minimumIndex(std::vector<int>& elems, unsigned start, unsigned end);
/*
Voraussetzung: left < right
Ergebnis: Eine Zufallszahl zwischen left(inklusive) und right (exklusive)
Effekt: Keiner
*/
int zufall(int left, int right);
/*
Voraussetzung: Keine
Effekt: Keiner
Ergebnis: Ein sortierter vector ist geliefert. Wenn aufsteigend=true ist der vector aufsteigend sortiert, sonst absteigends
*/
std::vector<int> sortiertes_array(unsigned size, bool aufsteigend);
/*
Voraussetzung: Keine
Effekt: Keiner
Ergebnis: Ein vector mit zufälligen Werten ist geliefert. Hierbei wird jede Zahl gleichverteilt
zufällig zwischen 0 und size gewählt. Doppelte Zahlen sind möglich.
*/
std::vector<int> zufalls_array(unsigned size);
}
+22
View File
@@ -0,0 +1,22 @@
//g++ -std=c++14 -Wall -Wextra -Werror -pedantic ./w5/min.cpp -o ./bin/min && ./bin/min
#include <iostream>
#include <vector>
int min(const std::vector<int>& vec);
int main() {
std::vector<int> testVec = {10, 20, 2, 0, 30};
std::cout << "The minimum value in the vector is: " << min(testVec) << std::endl;
}
int min(const std::vector<int>& vec) {
int minVal = vec[0];
for (unsigned i = 1; i < vec.size(); ++i) {
if (vec[i] < minVal) {
minVal = vec[i];
}
}
return minVal;
}
+39
View File
@@ -0,0 +1,39 @@
/*
clear && g++ -std=c++14 -Wall -Wextra -Werror -pedantic ./w5/turn_min.cpp -o ./bin/turn_min && ./bin/turn_min
Bei jedem Durchlauf halbieren wir die Größe der Eingabe (also n/2),
und wir müssen alle Elemente betrachten, um das Minimum zu finden (also O(n))
Daraus folgt die Rekursionsgleichung: T(n) = T(n/2) + O(n)
Da wir log(n) Runden benötigen und in jeder Runde O(n) Operationen durchführen
beträgt die Gesamtlaufzeit des Algorithmus O(n log n)
*/
#include <iostream>
#include <vector>
std::pair<int, int> TurnMin(std::vector<int>& vec);
int main() {
std::vector<int> vec = {7, 3, 2, 5, 10, -5, 4, 6,2,2,3,4,4,5,6,76,7,78};
auto ergebnis = TurnMin(vec);
std::cout << "Die Gewinnerzahl, nach " << ergebnis.first << " Runden, ist: " << ergebnis.second << std::endl;
}
std::pair<int, int> TurnMin(std::vector<int>& vec) {
int runde = 0;
while (vec.size() > 1) {
std::vector<int> gewinner;
for (unsigned i = 0; i < vec.size(); i += 2) {
if (vec[i] < vec[i + 1]) {
gewinner.push_back(vec[i]);
}
else {
gewinner.push_back(vec[i + 1]);
}
}
vec = gewinner;
runde++;
}
return {runde, vec[0]};
}
+185
View File
@@ -0,0 +1,185 @@
// clear && g++ -std=c++14 -Wall -Wextra -Werror -pedantic ./w5/hilfsfunktionen.cpp ./w5/ultrasort.cpp -o ./bin/ultrasort && ./bin/ultrasort
#include "hilfsfunktionen.hpp"
#include <iostream>
#include <vector>
#include <limits>
bool isSorted(const std::vector<int>& vec);
void insertionSort(std::vector<int>& elems);
void merge(std::vector<int>& first_part, std::vector<int>& second_part, std::vector<int>& elems);
void ultraSort(std::vector<int>& elems);
void ultraSortParam(std::vector<int>& elems, double k);
int main() {
srand(time(NULL));
double time;
std::vector<int> array;
// Runtime (a)
std::cout << "############ RUNTIME (ultraSort) ############ \n";
for (int size = 10000; size <= 100000; size *= 10) {
std::cout << " " << size << " Elemente:" << std::endl;
array = hf::zufalls_array(size);
time = clock();
ultraSort(array);
time = clock() - time;
std::cout << " Zufällig: " << (time/CLOCKS_PER_SEC) << " Sekunden" << std::endl;
array = hf::sortiertes_array(size, true);
time = clock();
ultraSort(array);
time = clock() - time;
std::cout << " Aufsteigend: " << (time/CLOCKS_PER_SEC) << " Sekunden" << std::endl;
array = hf::sortiertes_array(size, false);
time = clock();
ultraSort(array);
time = clock() - time;
std::cout << " Absteigend: " << (time/CLOCKS_PER_SEC) << " Sekunden" << std::endl;
if (isSorted(array)) {
std::cout << " Array is sorted.\n";
} else {
std::cout << " Array is not sorted.\n";
}
}
// Optimal k
std::cout << "############ OPTIMAL K ############ \n";
std::vector<double> k_values = {0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9};
double optimal_k = 0;
double shortest_time = std::numeric_limits<double>::max();
for (double k : k_values) {
array = hf::zufalls_array(10000);
time = clock();
ultraSortParam(array, k);
time = clock() - time;
if (time < shortest_time) {
shortest_time = time;
optimal_k = k;
}
}
std::cout << " Optimal k is " << optimal_k << std::endl;
// Runtime (b)
std::cout << "############ RUNTIME (ultraSortParam) ############ \n";
for (int size = 10000; size <= 100000; size *= 10) {
std::cout << " " << size << " Elemente:" << std::endl;
array = hf::zufalls_array(size);
time = clock();
ultraSortParam(array, optimal_k);
time = clock() - time;
std::cout << " Zufällig: " << (time/CLOCKS_PER_SEC) << " Sekunden" << std::endl;
array = hf::sortiertes_array(size, true);
time = clock();
ultraSortParam(array, optimal_k);
time = clock() - time;
std::cout << " Aufsteigend: " << (time/CLOCKS_PER_SEC) << " Sekunden" << std::endl;
array = hf::sortiertes_array(size, false);
time = clock();
ultraSortParam(array, optimal_k);
time = clock() - time;
std::cout << " Absteigend: " << (time/CLOCKS_PER_SEC) << " Sekunden" << std::endl;
if (isSorted(array)) {
std::cout << " Array is sorted.\n";
} else {
std::cout << " Array is not sorted.\n";
}
}
return 0;
}
bool isSorted(const std::vector<int>& vec) {
for (size_t i = 0; i < vec.size() - 1; ++i) {
if (vec[i] > vec[i + 1]) {
return false;
}
}
return true;
}
void insertionSort(std::vector<int>& elems){
int key=elems[0];
unsigned shiftindex;
for(unsigned i = 1; i<elems.size();i++){
key=elems[i];
for(shiftindex=i; shiftindex>0&&elems[shiftindex-1]>=key;shiftindex--){
elems[shiftindex] = elems[shiftindex-1];
}
elems[shiftindex] = key;
}
}
void merge(std::vector<int>& first_part, std::vector<int>& second_part, std::vector<int>& elems){
unsigned i = 0;
unsigned j = 0;
unsigned begin = 0;
unsigned end = elems.size();
while(begin + i + j < end){
if ( j >= second_part.size() || ((i<first_part.size()) && (first_part[i]<second_part[j]))){
elems[begin+i+j] = first_part[i];
i++;
}
else{
elems[begin+i+j] = second_part[j];
j++;
}
}
}
void ultraSort(std::vector<int>& elems){
if (elems.size() <= 1) {
return;
}
if (elems.size() < 10) {
insertionSort(elems);
return;
}
int groesse_erster_teil = elems.size() / 3;
std::vector<int> erster_teil(elems.begin(), elems.begin() + groesse_erster_teil);
std::vector<int> zweiter_teil(elems.begin() + groesse_erster_teil, elems.end());
insertionSort(erster_teil);
ultraSort(zweiter_teil);
merge(erster_teil, zweiter_teil, elems);
}
void ultraSortParam(std::vector<int>& elems, double k){
if (elems.size() <= 1) {
return;
}
if (elems.size() < 10) {
insertionSort(elems);
return;
}
int groesse_erster_teil = static_cast<int>(k * elems.size());
std::vector<int> erster_teil(elems.begin(), elems.begin() + groesse_erster_teil);
std::vector<int> zweiter_teil(elems.begin() + groesse_erster_teil, elems.end());
insertionSort(erster_teil);
ultraSortParam(zweiter_teil, k);
merge(erster_teil, zweiter_teil, elems);
}