Implement simple mergesort

This commit is contained in:
Robin Dietzel 2023-10-31 21:11:31 +01:00
parent a1c81529b9
commit b744c5489d
5 changed files with 95 additions and 5 deletions

View File

@ -28,4 +28,3 @@ RUN env; if [[ ${UBUNTU_VERSION} == "23.04" || ${UBUNTU_VERSION} == "23.10" ]];
ARG GCC_VERSION="13" ARG GCC_VERSION="13"
RUN apt-get -y install gcc-${GCC_VERSION} g++-${GCC_VERSION} RUN apt-get -y install gcc-${GCC_VERSION} g++-${GCC_VERSION}

View File

@ -18,7 +18,9 @@ add_custom_target(task1_7_dataset
${CMAKE_CURRENT_SOURCE_DIR}/dataset.dat ${CMAKE_CURRENT_SOURCE_DIR}/dataset.dat
${CMAKE_CURRENT_BINARY_DIR}/dataset.dat) ${CMAKE_CURRENT_BINARY_DIR}/dataset.dat)
add_executable(task1_7 main.cpp) add_executable(task1_7 main.cpp
mergesort.h)
target_link_libraries(task1_7 target_link_libraries(task1_7
fmt::fmt fmt::fmt
Qt::Core) Qt::Core)

View File

@ -2,7 +2,8 @@
#include <QCoreApplication> #include <QCoreApplication>
#include <QFile> #include <QFile>
#include <vector> #include <vector>
#include <printf.h>
#include <mergesort.h>
/* /*
Create a simple sorting application that uses the mergesort algorithm to sort a Create a simple sorting application that uses the mergesort algorithm to sort a
@ -23,7 +24,7 @@ your predictions and their graphical illustration?
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
QFile file("dataset.dat"); QFile file("dataset.dat");
if(!file.open(QIODevice::ReadOnly | QIODevice::Text)) { if(!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
//qDebug() << "Could not open file"; fmt::print("Could not open file");
return 0; return 0;
} }
@ -39,5 +40,22 @@ int main(int argc, char *argv[]) {
fmt::print("Read {} values from {}\n", dataset.size(), file.fileName().toStdString()); fmt::print("Read {} values from {}\n", dataset.size(), file.fileName().toStdString());
algo::mergesort(dataset.begin(), dataset.end(), [](int32_t a, int32_t b) {
return (a>b);
});
QFile outfile("dataset-sorted.dat");
if(!outfile.open(QIODevice::WriteOnly | QIODevice::Text)) {
fmt::print("Error! Could not create output file");
}
for(auto &val : dataset) {
outfile.write(fmt::format("{}\n", val).c_str());
}
file.close();
outfile.flush();
outfile.close();
return 0; return 0;
} }

0
task1/mergesort.cpp Normal file
View File

71
task1/mergesort.h Normal file
View File

@ -0,0 +1,71 @@
#pragma once
#include <vector>
#include <algorithm>
namespace algo {
template<typename Iterator, typename Comparator>
void merge(Iterator start, Iterator middle, Iterator end, Comparator cmp, Iterator output_start) {
Iterator start_m = start;
Iterator start2 = middle + 1;
//merge from input until one half completes
while (start <= middle && start2 <= end) {
if (cmp(*start, *start2)) {
*output_start = *start;
start++;
} else {
*output_start = *start2;
start2++;
}
output_start++;
}
//try to finish first half
while (start <= middle) {
*output_start = *start;
start++;
output_start++;
}
while (start2 <= end) {
*output_start = *start2;
start2++;
output_start++;
}
const auto nit = std::distance(start_m, end);
for (auto i = 0; i <= nit; i++, start_m++, output_start++) {
*start_m = *output_start;
}
}
template<typename Container, typename Iterator, typename Comparator>
void mergesort_splitup(Container &output_vec, Iterator start, Iterator end, Comparator cmp, Iterator output_start) {
Iterator middle = start;
Iterator output_started_from = output_start;
//move middle iterator litterally to the middle
std::advance(middle, std::distance(start, end) / 2);
//sort the first half within an recursion
mergesort_splitup(output_vec, start, middle, cmp, output_start);
//move output iterator
std::advance(output_start, std::distance(start, middle + 1));
//sort the second half within a recursion
mergesort_splitup(output_vec, middle + 1, end, cmp, output_start);
//merge everything together starting from the complete beginning
merge(start, middle, end, cmp, output_started_from);
}
template<typename Iterator, typename Comparator>
void mergesort(Iterator start, Iterator end, Comparator cmp) {
using valtype = typename std::iterator_traits<Iterator>::value_type;
std::vector<valtype> output_vec(std::distance(start, end));
}
}