Skip to content

Commit

Permalink
Added chapter 03 and ex06 (#7)
Browse files Browse the repository at this point in the history
  • Loading branch information
thorstendikmann committed May 13, 2024
1 parent ea75b19 commit 2d9c436
Show file tree
Hide file tree
Showing 7 changed files with 399 additions and 0 deletions.
2 changes: 2 additions & 0 deletions src/uebungen/uebung06/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin/u06)
td_add_all_subdirectories()
5 changes: 5 additions & 0 deletions src/uebungen/uebung06/infix/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin/u06)

add_executable(infix_parser infix_parser.cpp)
target_link_libraries(infix_parser stack)
install(TARGETS infix_parser DESTINATION bin/u06)
186 changes: 186 additions & 0 deletions src/uebungen/uebung06/infix/infix_parser.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
#include <iostream>
#include <sstream>
#include <string>
#include <list>
#include <stack>
#include <map>

#include "stack/stack.h"

/**
* Helper function to check if a given string is numeric.
* Note: This cannot handle negative numbers currently.
*
* @param s the string to be checked.
* @return true if the given string is a numeric value.
*/
bool is_numeric(const std::string &s)
{
std::string::const_iterator it = s.begin();
while (it != s.end() && std::isdigit(*it))
++it;
return !s.empty() && it == s.end();
}

/**
* Helper function to print the contents of the stacks "output" and "operators" to std::cout.
*
* @param output copy (!) of the output stack.
* @param operators copy (!) of the operators stack.
*/
void printState(std::stack<std::string> output, std::stack<std::string> operators)
{
std::cout << " output: ";
while (!output.empty())
{
std::cout << "[" << output.top() << "] ";
output.pop();
}
std::cout << " | operators: ";
while (!operators.empty())
{
std::cout << "[" << operators.top() << "] ";
operators.pop();
}
std::cout << std::endl;
}

/**
* Return the precedence of an operator.
* Useful for relatively comparing the precedence of two operators.
*
* @return a numeric value indicating the precedence of the operator. Higher is higher precedence.
*/
std::size_t get_precedence(const std::string &op)
{
// hardcode common operators
std::map<std::string, std::size_t> precedences{{"+", 1}, {"-", 1}, {"*", 2}, {"/", 2}, {"^", 3}};
return precedences[op];
}

/**
* Infix to postix converter function.
*
* Dijkstra's Shunting Yard algorithm.
* - Parse all tokens of the input string (separated by " ")
* - If token is numeric, put numeric token to output stack
* - If token is left "(", put it to operator stack
* - If token is right ")", look for left "(" and put push all operators to output stack
* - Else operator is found. Check for precedence of operator.
* While last operator on stack is higher, push last it to output stack
*
* This will print the resulting postfix notation to std::cout.
*
* References:
* - [https://en.wikipedia.org/wiki/Shunting_yard_algorithm](Shunting yard algorithm - wikipedia)
* - [https://www.youtube.com/watch?v=1VjJe1PeExQ&t=19](The Shunting Yard Algorithm Demystified - youtube)
*
* @param inputStr input in infix notation to be processed.
*/
void infix_to_postfix(std::istringstream &inputStr)
{
std::cout << "Parsing " << inputStr.str() << std::endl;

std::stack<std::string> output;
std::stack<std::string> operators;
std::string str;

while (inputStr >> str)
{
std::cout << " processing " << str;
if (is_numeric(str))
{
// put numeric token to output stack
std::cout << " -> numeric" << std::endl;
output.push(str);
printState(output, operators);
}
else if (str == "(")
{
std::cout << " -> '('" << std::endl;
operators.push(str);
printState(output, operators);
}
else if (str == ")")
{
std::cout << " -> ')'" << std::endl;
// transfer all args to output until left "(" is reached
std::cout << " Looking for left '(' ... " << std::endl;
std::string c;
while (!operators.empty() && c != "(")
{
c = operators.top();
std::cout << " top op: " << c << std::endl;

operators.pop();
if (c != "(")
output.push(c);
}
printState(output, operators);
}
else
{
std::cout << " -> operator" << std::endl;

// if not first operator
if (!operators.empty())
{
// Check precedence of operator
std::string lastOp = operators.top();
while (!operators.empty() && (get_precedence(lastOp) >= get_precedence(str)))
{
// push higher precedence operators to outpus stack
std::cout << " Last op " << lastOp << " precedence is higher than mine " << str << std::endl;
output.push(lastOp);
operators.pop();
if (!operators.empty())
lastOp = operators.top();
}
}

operators.push(str);
printState(output, operators);
}
}

// transfer remaining operators to output.
while (!operators.empty())
{
std::string c = operators.top();
output.push(c);
operators.pop();
}

printState(output, operators);

// print result:
std::cout << " Postfix result: ";
std::string s;
while (!output.empty())
{
s = output.top() + " " + s;
output.pop();
}
std::cout << s << std::endl;
}

int main()
{
// Add some test data
std::list<std::istringstream> inputs = {};
inputs.push_back(std::istringstream("3 + 4"));
inputs.push_back(std::istringstream("1 + 2 * 3"));
inputs.push_back(std::istringstream("3 + 4 * 2"));
inputs.push_back(std::istringstream("3 * 4 + 2"));
inputs.push_back(std::istringstream("( 3 + 4 ) * ( 5 - 6 )"));
inputs.push_back(std::istringstream("( 3 + 4 ) * 2"));
inputs.push_back(std::istringstream("( 36 * 12 ) - 144 * 3"));
inputs.push_back(std::istringstream(" ( ( 36 * 12 ) - ( 144 + 2048 ) ) + 5"));
// // Negative numbers not yet supported.
// inputs.push_back(std::istringstream("13 - -3"));

for (auto it = inputs.begin(); it != inputs.end(); ++it)
{
infix_to_postfix(*it);
}
}
15 changes: 15 additions & 0 deletions src/uebungen/uebung06/sort/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin/u06)

add_executable(exercise_array_sort exercise_array_sort.c)
target_link_libraries(exercise_array_sort
intarray
array_unsort
array_selectionsort
array_bubblesort
array_insertionsort
array_insertionsortinplace
array_mergesort
array_quicksort
array_heapsort
)
install(TARGETS exercise_array_sort DESTINATION bin/u06)
139 changes: 139 additions & 0 deletions src/uebungen/uebung06/sort/exercise_array_sort.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#include "intarray/intarray.h"
#include "array/selectionsort.h"
#include "array/bubblesort.h"
#include "array/insertionsort.h"
#include "array/insertionsortinplace.h"
#include "array/mergesort.h"
#include "array/quicksort.h"
#include "array/heapsort.h"

int main(void)
{
printf("- %s, %d\n", __func__, __LINE__);

{
printf("\n############################# ---------- Part 1 ----------n\n\n");
Array a; // a copy on which we sort
array_init(&a, 10);
Array orig; // the original "unsorted" array
array_init(&orig, 1);

array_push_back(&orig, 7);
array_push_back(&orig, 3);
array_push_back(&orig, 5);
array_push_back(&orig, 2);
array_push_back(&orig, 6);
array_push_back(&orig, 9);
array_push_back(&orig, 1);
array_push_back(&orig, 3);
array_push_back(&orig, 8);
array_resize(&orig, orig.size); // trim to size
array_print(&orig);

printf("#---- Selection Sort\n");
array_deepcopy(&orig, &a);
array_print(&a);
array_sort_selectionsort(&a);
array_print(&a);

printf("#---- Bubble Sort\n");
array_deepcopy(&orig, &a);
array_print(&a);
array_sort_bubblesort(&a);
array_print(&a);

printf("#---- Insertion Sort (inplace)\n");
array_deepcopy(&orig, &a);
array_print(&a);
array_sort_insertionsortinplace(&a);
array_print(&a);

printf("#---- Merge Sort\n");
array_deepcopy(&orig, &a);
array_print(&a);
array_sort_mergesort(&a, 0, a.size - 1);
array_print(&a);

printf("#---- Quick Sort\n");
array_deepcopy(&orig, &a);
array_print(&a);
array_sort_quicksort(&a, 0, a.size - 1);
array_print(&a);

printf("#---- Heap Sort\n");
array_deepcopy(&orig, &a);
array_print(&a);
array_sort_heapsort(&a);
array_print(&a);

// free resources
array_destroy(&a);
array_destroy(&orig);
}
{
printf("\n############################# ---------- Part 2 ----------n\n\n");
Array a; // a copy on which we sort
array_init(&a, 10);
Array orig; // the original "unsorted" array
array_init(&orig, 1);

array_push_back(&orig, 8);
array_push_back(&orig, 1);
array_push_back(&orig, 7);
array_push_back(&orig, 11);
array_push_back(&orig, 16);
array_push_back(&orig, 12);
array_push_back(&orig, 14);
array_push_back(&orig, 5);
array_push_back(&orig, 20);
array_push_back(&orig, 4);
array_resize(&orig, orig.size); // trim to size
array_print(&orig);

printf("#---- Selection Sort\n");
array_deepcopy(&orig, &a);
array_print(&a);
array_sort_selectionsort(&a);
array_print(&a);

printf("#---- Bubble Sort\n");
array_deepcopy(&orig, &a);
array_print(&a);
array_sort_bubblesort(&a);
array_print(&a);

printf("#---- Insertion Sort (inplace)\n");
array_deepcopy(&orig, &a);
array_print(&a);
array_sort_insertionsortinplace(&a);
array_print(&a);

printf("#---- Merge Sort\n");
array_deepcopy(&orig, &a);
array_print(&a);
array_sort_mergesort(&a, 0, a.size - 1);
array_print(&a);

printf("#---- Quick Sort\n");
array_deepcopy(&orig, &a);
array_print(&a);
array_sort_quicksort(&a, 0, a.size - 1);
array_print(&a);

printf("#---- Heap Sort\n");
array_deepcopy(&orig, &a);
array_print(&a);
array_sort_heapsort(&a);
array_print(&a);

// free resources
array_destroy(&a);
array_destroy(&orig);
}

return 0;
}
5 changes: 5 additions & 0 deletions src/uebungen/uebung06/tree_traverse/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin/u06)

add_executable(tree_traverse tree_traverse.cpp)
target_link_libraries(tree_traverse treearray)
install(TARGETS tree_traverse DESTINATION bin/u06)
Loading

0 comments on commit 2d9c436

Please sign in to comment.