Init
This commit is contained in:
8
P1/ADS_P1_2_Binaerbaum/CMakeLists.txt
Executable file
8
P1/ADS_P1_2_Binaerbaum/CMakeLists.txt
Executable file
@@ -0,0 +1,8 @@
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
|
||||
project(P1_2_Binaerbaum)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
add_executable(P1_2_Binaerbaum main.cpp Tree.cpp TreeNode.cpp TreeTest.cpp)
|
||||
18
P1/ADS_P1_2_Binaerbaum/ExportZielanalyse.csv
Executable file
18
P1/ADS_P1_2_Binaerbaum/ExportZielanalyse.csv
Executable file
@@ -0,0 +1,18 @@
|
||||
A;70;0;0
|
||||
A;20;0;0
|
||||
A;90;0;0
|
||||
A;10;0;0
|
||||
A;60;0;0
|
||||
A;80;0;0
|
||||
A;91;0;0
|
||||
A;40;0;0
|
||||
A;84;0;0
|
||||
A;95;0;0
|
||||
A;30;0;0
|
||||
A;50;0;0
|
||||
A;82;0;0
|
||||
A;86;0;0
|
||||
A;93;0;0
|
||||
A;96;0;0
|
||||
A;92;0;0
|
||||
A;94;0;0
|
||||
|
333
P1/ADS_P1_2_Binaerbaum/Tree.cpp
Executable file
333
P1/ADS_P1_2_Binaerbaum/Tree.cpp
Executable file
@@ -0,0 +1,333 @@
|
||||
/*************************************************
|
||||
* ADS Praktikum 1.2
|
||||
* Tree.cpp
|
||||
* Erweiterung um Hilfsfunktionen gestattet.
|
||||
*************************************************/
|
||||
#include "Tree.h"
|
||||
#include "TreeNode.h"
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <queue>
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
Tree::Tree() {
|
||||
currentNodeChronologcalID = 0;
|
||||
}
|
||||
Tree::~Tree() {
|
||||
while (m_anker != nullptr) {
|
||||
deleteNode(m_anker->getNodeOrderID());
|
||||
}
|
||||
}
|
||||
|
||||
TreeNode* Tree::getAnker() {
|
||||
return m_anker;
|
||||
}
|
||||
|
||||
void Tree::setAnker(TreeNode* node) {
|
||||
m_anker = node;
|
||||
}
|
||||
|
||||
void Tree::addNode(string Name, int Age, double Income, int PostCode) {
|
||||
TreeNode* newNode = new TreeNode { Age + int(Income) + PostCode , currentNodeChronologcalID++, Name, Age, Income, PostCode };
|
||||
TreeNode* ptr = getAnker();
|
||||
TreeNode* tmp = nullptr;
|
||||
|
||||
/*
|
||||
* Allg. Baumaufbau
|
||||
* Anker
|
||||
* klein -> groß
|
||||
*/
|
||||
|
||||
// bis zum passenden Parentknoten traversieren
|
||||
while (ptr != nullptr) {
|
||||
tmp = ptr;
|
||||
// wenn NodeID > ptrID dann rechts sonst links
|
||||
// Dublikate?
|
||||
newNode->getNodeOrderID() > ptr->getNodeOrderID() ?
|
||||
ptr = ptr->getRight() : ptr = ptr->getLeft();
|
||||
}
|
||||
|
||||
if (getAnker() == nullptr)
|
||||
setAnker(newNode);
|
||||
|
||||
// wenn NodeID > tmpID dann rechts sonst links
|
||||
else newNode->getNodeOrderID() > tmp->getNodeOrderID() ?
|
||||
tmp->setRight(newNode) : tmp->setLeft(newNode);
|
||||
}
|
||||
|
||||
bool Tree::deleteNode(int delNodeID) {
|
||||
// Baum ist leer
|
||||
if (!getAnker())
|
||||
return false;
|
||||
|
||||
// Loeschen von Nodes - ab Wurzel
|
||||
if (getAnker()->getNodeOrderID() == delNodeID) {
|
||||
|
||||
// 1. Fall: der Baum bestehet aus 1 Knoten.
|
||||
if (!getAnker()->getRight() && !getAnker()->getLeft()) {
|
||||
delete getAnker();
|
||||
setAnker(nullptr);
|
||||
cout << "+ Datensatz wurde gelöscht.\n";
|
||||
return true;
|
||||
}
|
||||
|
||||
// 2. Fall: Wurzel, mit einem Nachfolger
|
||||
else if ((getAnker()->getRight() && !getAnker()->getLeft()) || (!getAnker()->getRight() && getAnker()->getLeft())) {
|
||||
TreeNode* tmp = getAnker();
|
||||
|
||||
// Nachfolger wird Anker
|
||||
getAnker()->getRight() ?
|
||||
setAnker(getAnker()->getRight()) : setAnker(getAnker()->getLeft());
|
||||
delete tmp;
|
||||
cout << "+ Datensatz wurde gelöscht.\n";
|
||||
return true;
|
||||
}
|
||||
|
||||
// 3. Fall: Wurzel, mit zwei Nachfolger
|
||||
else if (getAnker()->getRight() && getAnker()->getLeft()) {
|
||||
TreeNode* minimumRTB = getAnker()->getRight();
|
||||
TreeNode* minimumParent = nullptr;
|
||||
|
||||
// Minimum von RTB suchen.
|
||||
while (minimumRTB->getLeft() != nullptr) {
|
||||
minimumParent = minimumRTB;
|
||||
minimumRTB = minimumRTB->getLeft();
|
||||
}
|
||||
|
||||
// Minimum von RTB gefunden
|
||||
if (minimumParent != nullptr) {
|
||||
minimumParent->setLeft(minimumRTB->getRight());
|
||||
minimumRTB->setLeft(getAnker()->getLeft());
|
||||
minimumRTB->setRight(getAnker()->getRight());
|
||||
}
|
||||
|
||||
// Minimum von RTB ist RTB-Wurzel (RTB->left == nullptr)
|
||||
else
|
||||
minimumRTB->setLeft(getAnker()->getLeft());
|
||||
|
||||
delete getAnker();
|
||||
setAnker(minimumRTB);
|
||||
cout << "+ Datensatz wurde gelöscht.\n";
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Loeschen von Nodes - Node != Wurzel
|
||||
else {
|
||||
// zu loeschende Node und Parent_Node
|
||||
TreeNode* ptr = getAnker();
|
||||
TreeNode* parent = getAnker();
|
||||
|
||||
// suche zuloeschenden Node
|
||||
while ((ptr->getRight() || ptr->getLeft()) && ptr->getNodeOrderID() != delNodeID && ptr) {
|
||||
parent = ptr;
|
||||
delNodeID < ptr->getNodeOrderID() ?
|
||||
ptr = ptr->getLeft() : ptr = ptr->getRight();
|
||||
}
|
||||
|
||||
// 1. Fall Loeschen von Nodes - ohne Nachfolger
|
||||
if (!ptr->getRight() && !ptr->getLeft()) {
|
||||
parent->getNodeOrderID() < ptr->getNodeOrderID() ?
|
||||
parent->setRight(nullptr) : parent->setLeft(nullptr);
|
||||
delete ptr;
|
||||
cout << "+ Datensatz wurde gelöscht.\n";
|
||||
return true;
|
||||
}
|
||||
|
||||
// 2. Fall Loeschen von Nodes - mit einem Nachfolger
|
||||
else if ((!ptr->getRight() && ptr->getLeft()) || (ptr->getRight() && !ptr->getLeft())) {
|
||||
if (parent->getNodeOrderID() < ptr->getNodeOrderID())
|
||||
ptr->getRight() ?
|
||||
parent->setRight(ptr->getRight()) : parent->setRight(ptr->getLeft());
|
||||
else
|
||||
ptr->getRight() ?
|
||||
parent->setLeft(ptr->getRight()) : parent->setLeft(ptr->getLeft());
|
||||
|
||||
delete ptr;
|
||||
cout << "+ Datensatz wurde gelöscht.\n";
|
||||
return true;
|
||||
}
|
||||
|
||||
// 3. Fall Loeschen von Nodes - mit zwei Nachfolger
|
||||
if (ptr->getRight() != nullptr && ptr->getLeft() != nullptr) {
|
||||
TreeNode* minimumRTB = ptr->getRight();
|
||||
TreeNode* minimumParent = nullptr;
|
||||
|
||||
//Minumum von RTB suchen.
|
||||
while (minimumRTB->getLeft() != nullptr) {
|
||||
minimumParent = minimumRTB;
|
||||
minimumRTB = minimumRTB->getLeft();
|
||||
}
|
||||
|
||||
//Minimum von RTB gefunden
|
||||
if (minimumParent != nullptr) {
|
||||
minimumParent->setLeft(minimumRTB->getRight());
|
||||
minimumRTB->setLeft(ptr->getLeft());
|
||||
minimumRTB->setRight(ptr->getRight());
|
||||
}
|
||||
|
||||
//Minimum von RTB ist RTB-Wurzel (RTB->left == nullptr)
|
||||
else
|
||||
minimumRTB->setLeft(ptr->getLeft());
|
||||
|
||||
//verknuepfe parent von zu loeschende Node
|
||||
parent->getNodeOrderID() < ptr->getNodeOrderID() ?
|
||||
parent->setRight(minimumRTB) :
|
||||
parent->setLeft(minimumRTB);
|
||||
|
||||
delete ptr;
|
||||
cout << "+ Datensatz wurde gelöscht.\n";
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Tree::searchNode(std::string name) {
|
||||
|
||||
// Baum muss vorhanden sein
|
||||
if (getAnker() != nullptr) {
|
||||
bool found = false;
|
||||
TreeNode* ptr = getAnker();
|
||||
TreeNode* node;
|
||||
|
||||
cout << endl <<
|
||||
"ID | Name | Alter | Einkommen | PLZ | OrderID\n"
|
||||
"---+------------+-------+-----------+-------+--------\n";
|
||||
|
||||
queue<TreeNode*> q;
|
||||
q.push(ptr);
|
||||
while (!q.empty()) {
|
||||
node = q.front();
|
||||
q.pop();
|
||||
if (node->getName() == name) {
|
||||
printNode(node);
|
||||
found = true;
|
||||
// break; // damit werden alle Knoten mit dem Namen ausgegeben
|
||||
}
|
||||
if (node->getLeft() != nullptr)
|
||||
q.push(node->getLeft());
|
||||
if (node->getRight() != nullptr)
|
||||
q.push(node->getRight());
|
||||
}
|
||||
|
||||
if (!found)
|
||||
cout << "--------------- Kein Eintrag vorhanden --------------" << endl;
|
||||
return found;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
void Tree::printNode(TreeNode* node) {
|
||||
cout << setw(3) << node->getNodeChronologicalID() << '|' << setw(12) << node->getName() << '|'
|
||||
<< setw(7) << node->getAge() << '|' << setw(11) << node->getIncome() << '|'
|
||||
<< setw(7) << node->getPostCode() << '|' << setw(8) << node->getNodeOrderID() << endl;
|
||||
}
|
||||
|
||||
void Tree::printLevelOrder() {
|
||||
|
||||
TreeNode* root = getAnker();
|
||||
|
||||
// 2 Queues instanzieren
|
||||
std::queue<TreeNode*> q;
|
||||
std::queue<int> nq;
|
||||
|
||||
cout << endl <<
|
||||
"ID | Name | Alter | Einkommen | PLZ | OrderID\n"
|
||||
"---+------------+-------+-----------+-------+--------\n";
|
||||
|
||||
if (root == nullptr) {
|
||||
cout << "--------------- Kein Eintrag vorhanden --------------" << endl;
|
||||
return;
|
||||
}
|
||||
|
||||
// Wurzelknoten und Startniveau in die Queues pushen
|
||||
q.push(root);
|
||||
nq.push(0);
|
||||
|
||||
// vorheriges Niveau merken bzw. den Niveauwechsel irgendwie mitbekommen
|
||||
int prev_niveau = -1;
|
||||
int niveau;
|
||||
|
||||
// Schleife
|
||||
while (!q.empty()) {
|
||||
// Entnahme aus den Queues und loeschen
|
||||
TreeNode* ptr = q.front();
|
||||
q.pop();
|
||||
niveau = nq.front();
|
||||
nq.pop();
|
||||
|
||||
// Ausgabe Niveauwechsel
|
||||
if (prev_niveau != niveau) {
|
||||
std::cout << std::endl << "Niveau " << niveau << ": " << endl;
|
||||
prev_niveau = niveau;
|
||||
}
|
||||
// Ausgabe des Knotens
|
||||
printNode(ptr);
|
||||
|
||||
// Linker Nachfolgeknoten in die Queues
|
||||
if (ptr->getLeft() != nullptr) {
|
||||
q.push(ptr->getLeft());
|
||||
nq.push(niveau + 1);
|
||||
}
|
||||
// Rechter Nachfolgeknoten in die Queues
|
||||
if (ptr->getRight() != nullptr) {
|
||||
q.push(ptr->getRight());
|
||||
nq.push(niveau + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Tree::printPreOrder(TreeNode* ptr) {
|
||||
if (ptr != nullptr) {
|
||||
printNode(ptr);
|
||||
printPreOrder(ptr->getLeft());
|
||||
printPreOrder(ptr->getRight());
|
||||
}
|
||||
}
|
||||
|
||||
void Tree::printPostOrder(TreeNode* ptr) {
|
||||
if (ptr != nullptr) {
|
||||
printPreOrder(ptr->getLeft());
|
||||
printPreOrder(ptr->getRight());
|
||||
printNode(ptr);
|
||||
}
|
||||
}
|
||||
|
||||
void Tree::printInOrder(TreeNode* ptr) {
|
||||
if (ptr != nullptr) {
|
||||
printPreOrder(ptr->getLeft());
|
||||
printNode(ptr);
|
||||
printPreOrder(ptr->getRight());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Tree::printAll() {
|
||||
if (getAnker() != nullptr) {
|
||||
string ausgabeFormat;
|
||||
cout << "Ausgabereihenfolge ?> ";
|
||||
cin >> ausgabeFormat;
|
||||
TreeNode* ptr = getAnker();
|
||||
cout << endl <<
|
||||
"ID | Name | Alter | Einkommen | PLZ | OrderID\n"
|
||||
"---+------------+-------+-----------+-------+--------\n";
|
||||
if (ausgabeFormat == "pre")
|
||||
printPreOrder(getAnker());
|
||||
|
||||
else if (ausgabeFormat == "post")
|
||||
printPostOrder(getAnker());
|
||||
|
||||
else if (ausgabeFormat == "in")
|
||||
printInOrder(getAnker());
|
||||
|
||||
else
|
||||
cout << "falsches Formatkürzel";
|
||||
|
||||
}
|
||||
else
|
||||
cout << "--------------- Kein Eintrag vorhanden --------------\n";
|
||||
}
|
||||
35
P1/ADS_P1_2_Binaerbaum/Tree.h
Executable file
35
P1/ADS_P1_2_Binaerbaum/Tree.h
Executable file
@@ -0,0 +1,35 @@
|
||||
/*************************************************
|
||||
* ADS Praktikum 1.2
|
||||
* Tree.h
|
||||
* Erweiterung um Hilfsattribute und -funktionen gestattet, wenn erforderlich.
|
||||
*************************************************/
|
||||
#pragma once
|
||||
#include "TreeNode.h"
|
||||
#include "catch.h"
|
||||
#include <string>
|
||||
|
||||
using namespace std;
|
||||
|
||||
class Tree {
|
||||
private:
|
||||
TreeNode* m_anker = nullptr;
|
||||
int currentNodeChronologcalID = 0;
|
||||
public:
|
||||
Tree();
|
||||
~Tree();
|
||||
void addNode(std::string Name, int Age, double Income, int PostCode);
|
||||
bool deleteNode(int NodeOrderID);
|
||||
bool searchNode(std::string Name);
|
||||
void printAll();
|
||||
void printNode(TreeNode* node);
|
||||
void printPreOrder(TreeNode* ptr);
|
||||
void printPostOrder(TreeNode* ptr);
|
||||
void printInOrder(TreeNode* ptr);
|
||||
void printLevelOrder();
|
||||
|
||||
TreeNode* getAnker();
|
||||
void setAnker(TreeNode* _anker);
|
||||
// friend-Funktionen sind für die Tests erforderlich und müssen unangetastet
|
||||
// bleiben!
|
||||
friend TreeNode* get_anker(Tree& TN);
|
||||
};
|
||||
86
P1/ADS_P1_2_Binaerbaum/TreeNode.cpp
Executable file
86
P1/ADS_P1_2_Binaerbaum/TreeNode.cpp
Executable file
@@ -0,0 +1,86 @@
|
||||
/*************************************************
|
||||
* ADS Praktikum 1.2
|
||||
* TreeNode.cpp
|
||||
* Erweiterung um Hilfsfunktionen gestattet.
|
||||
*************************************************/
|
||||
#include "TreeNode.h"
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
TreeNode::TreeNode(int nNodePos,
|
||||
int id,
|
||||
string name,
|
||||
int alter,
|
||||
double einkommen,
|
||||
int plz) {
|
||||
this->m_NodeOrderID = nNodePos;
|
||||
this->m_NodeChronologicalID = id;
|
||||
this->m_Name = name;
|
||||
this->m_Age = alter;
|
||||
this->m_Income = einkommen;
|
||||
this->m_PostCode = plz;
|
||||
this->m_left = nullptr;
|
||||
this->m_right = nullptr;
|
||||
}
|
||||
|
||||
|
||||
int TreeNode::getNodeOrderID() const {
|
||||
return m_NodeOrderID;
|
||||
}
|
||||
|
||||
int TreeNode::getNodeChronologicalID() const {
|
||||
return m_NodeChronologicalID;
|
||||
}
|
||||
|
||||
string TreeNode::getName() const {
|
||||
return m_Name;
|
||||
}
|
||||
|
||||
int TreeNode::getAge() const {
|
||||
return m_Age;
|
||||
}
|
||||
|
||||
double TreeNode::getIncome() const {
|
||||
return m_Income;
|
||||
}
|
||||
|
||||
int TreeNode::getPostCode() const {
|
||||
return m_PostCode;
|
||||
}
|
||||
|
||||
TreeNode* TreeNode::getLeft() {
|
||||
return m_left;
|
||||
}
|
||||
TreeNode* TreeNode::getRight() {
|
||||
return m_right;
|
||||
}
|
||||
|
||||
void TreeNode::setNodeOrderID(int noID) {
|
||||
m_NodeOrderID = noID;
|
||||
}
|
||||
|
||||
void TreeNode::setName(string name) {
|
||||
m_Name = name;
|
||||
}
|
||||
|
||||
void TreeNode::setAge(int age) {
|
||||
m_Age = age;
|
||||
}
|
||||
|
||||
void TreeNode::setIncome(double income) {
|
||||
m_Income = income;
|
||||
}
|
||||
|
||||
void TreeNode::setPostCode(int postcode) {
|
||||
m_PostCode = postcode;
|
||||
}
|
||||
|
||||
void TreeNode::setLeft(TreeNode* node) {
|
||||
m_left = node;
|
||||
}
|
||||
|
||||
void TreeNode::setRight(TreeNode* node) {
|
||||
m_right = node;
|
||||
}
|
||||
|
||||
void print();
|
||||
44
P1/ADS_P1_2_Binaerbaum/TreeNode.h
Executable file
44
P1/ADS_P1_2_Binaerbaum/TreeNode.h
Executable file
@@ -0,0 +1,44 @@
|
||||
/*************************************************
|
||||
* ADS Praktikum 1.2
|
||||
* TreeNode.h
|
||||
* Erweiterung um Hilfsattribute und -funktionen gestattet, wenn erforderlich.
|
||||
*************************************************/
|
||||
#pragma once
|
||||
#include <string>
|
||||
|
||||
using namespace std;
|
||||
|
||||
class TreeNode {
|
||||
private:
|
||||
int m_NodeOrderID;
|
||||
int m_NodeChronologicalID;
|
||||
string m_Name;
|
||||
int m_Age;
|
||||
double m_Income;
|
||||
int m_PostCode;
|
||||
|
||||
TreeNode* m_left = nullptr;
|
||||
TreeNode* m_right = nullptr;
|
||||
|
||||
|
||||
public:
|
||||
TreeNode(int, int, string, int, double, int);
|
||||
int getNodeOrderID() const;
|
||||
int getNodeChronologicalID() const;
|
||||
string getName() const;
|
||||
int getAge() const;
|
||||
double getIncome() const;
|
||||
int getPostCode() const;
|
||||
TreeNode* getLeft();
|
||||
TreeNode* getRight();
|
||||
|
||||
void setNodeOrderID(int noID);
|
||||
void setName(string name);
|
||||
void setAge(int age);
|
||||
void setIncome(double income);
|
||||
void setPostCode(int postcode);
|
||||
void setLeft(TreeNode* node);
|
||||
void setRight(TreeNode* node);
|
||||
|
||||
void print();
|
||||
};
|
||||
315
P1/ADS_P1_2_Binaerbaum/TreeTest.cpp
Executable file
315
P1/ADS_P1_2_Binaerbaum/TreeTest.cpp
Executable file
@@ -0,0 +1,315 @@
|
||||
/*************************************************
|
||||
* ADS Praktikum 1.1
|
||||
* Unit-Testdatei
|
||||
* Stand: 12.04.2024
|
||||
*
|
||||
*************************************************
|
||||
* Änderungen untersagt!
|
||||
*************************************************/
|
||||
#include "Tree.h"
|
||||
#include "TreeNode.h"
|
||||
#include "catch.h"
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
using namespace std;
|
||||
|
||||
// Friend-Methode fuer Testroutine
|
||||
TreeNode* get_anker(Tree& Tr)
|
||||
{
|
||||
return Tr.m_anker;
|
||||
}
|
||||
|
||||
/***********************************************
|
||||
* Testroutine des Baums:
|
||||
* - Einfaches Hinzufuegen und Suchen
|
||||
* - Loeschen in unterscheidlicher Ausprägung
|
||||
* + Loeschen ohne Nachfolger
|
||||
* + Loeschen mit einem Nachfolger
|
||||
* + Loeschen mit zwei Nachfolger
|
||||
* + Loeschen der Wurzel
|
||||
* - Hinzufuegen vieler Nodes als Grossbaum
|
||||
*/
|
||||
TEST_CASE("Tree Testing", "[TREE]")
|
||||
{
|
||||
|
||||
Tree* nTree = new Tree();
|
||||
|
||||
SECTION("Hinzufuegen von Nodes und Suche - simple")
|
||||
{
|
||||
|
||||
nTree->addNode("Mayer", 20, 0, 0);
|
||||
nTree->addNode("Mayer2", 10, 0, 0);
|
||||
nTree->addNode("Mayer3", 30, 0, 0);
|
||||
nTree->addNode("Mayer4", 40, 0, 0);
|
||||
nTree->addNode("Mayer5", 35, 0, 0);
|
||||
nTree->addNode("Mayer6", 25, 0, 0);
|
||||
nTree->addNode("Mayer7", 26, 0, 0);
|
||||
|
||||
REQUIRE(nTree->searchNode("Mayer") == true);
|
||||
REQUIRE(nTree->searchNode("Mayer7") == true);
|
||||
REQUIRE(nTree->searchNode("Mayer6") == true);
|
||||
REQUIRE(nTree->searchNode("Mayer5") == true);
|
||||
REQUIRE(nTree->searchNode("Mayer4") == true);
|
||||
REQUIRE(nTree->searchNode("Mayer3") == true);
|
||||
REQUIRE(nTree->searchNode("Mayer2") == true);
|
||||
|
||||
REQUIRE(nTree->searchNode("Mueller") == false);
|
||||
REQUIRE(nTree->searchNode("Mayer99") == false);
|
||||
}
|
||||
|
||||
SECTION("Loeschen von Nodes - ohne Nachfolger")
|
||||
{
|
||||
|
||||
nTree->addNode("Mayer", 20, 0, 0);
|
||||
nTree->addNode("Mayer2", 10, 0, 0);
|
||||
nTree->addNode("Mayer3", 30, 0, 0);
|
||||
nTree->addNode("Mayer4", 40, 0, 0);
|
||||
nTree->addNode("Mayer5", 35, 0, 0);
|
||||
nTree->addNode("Mayer6", 25, 0, 0);
|
||||
nTree->addNode("Mayer7", 26, 0, 0);
|
||||
|
||||
nTree->addNode("Mayer8", 8, 0, 0);
|
||||
REQUIRE(nTree->searchNode("Mayer8") == true);
|
||||
|
||||
TreeNode* tnanker = get_anker(*nTree);
|
||||
|
||||
nTree->deleteNode(8);
|
||||
REQUIRE(tnanker->getLeft()->getLeft() == nullptr);
|
||||
}
|
||||
|
||||
SECTION("Loeschen von Nodes - mit einem Nachfolger")
|
||||
{
|
||||
|
||||
nTree->addNode("Mayer", 20, 0, 0);
|
||||
nTree->addNode("Mayer2", 10, 0, 0);
|
||||
nTree->addNode("Mayer3", 30, 0, 0);
|
||||
nTree->addNode("Mayer4", 40, 0, 0);
|
||||
nTree->addNode("Mayer5", 35, 0, 0);
|
||||
nTree->addNode("Mayer6", 25, 0, 0);
|
||||
nTree->addNode("Mayer7", 26, 0, 0);
|
||||
|
||||
nTree->addNode("Mayer8", 8, 0, 0);
|
||||
nTree->addNode("Mayer9", 7, 0, 0);
|
||||
|
||||
REQUIRE(nTree->searchNode("Mayer8") == true);
|
||||
REQUIRE(nTree->searchNode("Mayer9") == true);
|
||||
|
||||
TreeNode* tnanker = get_anker(*nTree);
|
||||
|
||||
// linke Seite
|
||||
nTree->deleteNode(8);
|
||||
REQUIRE(tnanker->getLeft()->getLeft() != nullptr);
|
||||
REQUIRE(tnanker->getLeft()->getRight() == nullptr);
|
||||
REQUIRE(tnanker->getLeft()->getLeft()->getNodeOrderID() == 7);
|
||||
|
||||
nTree->deleteNode(7);
|
||||
REQUIRE(tnanker->getLeft()->getLeft() == nullptr);
|
||||
REQUIRE(tnanker->getLeft()->getRight() == nullptr);
|
||||
REQUIRE(tnanker->getLeft()->getNodeOrderID() == 10);
|
||||
|
||||
REQUIRE(nTree->searchNode("Mayer8") == false);
|
||||
REQUIRE(nTree->searchNode("Mayer9") == false);
|
||||
|
||||
// rechte Seite
|
||||
nTree->addNode("Mayer8", 8, 0, 0);
|
||||
nTree->addNode("Mayer9", 9, 0, 0);
|
||||
REQUIRE(nTree->searchNode("Mayer8") == true);
|
||||
REQUIRE(nTree->searchNode("Mayer9") == true);
|
||||
|
||||
nTree->deleteNode(8);
|
||||
REQUIRE(tnanker->getLeft()->getLeft() != nullptr);
|
||||
REQUIRE(tnanker->getLeft()->getLeft()->getNodeOrderID() == 9);
|
||||
|
||||
nTree->deleteNode(9);
|
||||
REQUIRE(tnanker->getLeft()->getLeft() == nullptr);
|
||||
REQUIRE(tnanker->getLeft()->getNodeOrderID() == 10);
|
||||
|
||||
REQUIRE(nTree->searchNode("Mayer8") == false);
|
||||
REQUIRE(nTree->searchNode("Mayer9") == false);
|
||||
}
|
||||
|
||||
SECTION("Loeschen von Nodes - mit zwei Nachfolger")
|
||||
{
|
||||
|
||||
nTree->addNode("Mayer", 20, 0, 0);
|
||||
nTree->addNode("Mayer2", 10, 0, 0);
|
||||
nTree->addNode("Mayer3", 30, 0, 0);
|
||||
nTree->addNode("Mayer4", 40, 0, 0);
|
||||
nTree->addNode("Mayer5", 35, 0, 0);
|
||||
nTree->addNode("Mayer6", 25, 0, 0);
|
||||
nTree->addNode("Mayer7", 26, 0, 0);
|
||||
|
||||
TreeNode* tnanker = get_anker(*nTree);
|
||||
|
||||
REQUIRE(tnanker->getNodeOrderID() == 20);
|
||||
REQUIRE(tnanker->getRight()->getNodeOrderID() == 30);
|
||||
REQUIRE(tnanker->getRight()->getLeft()->getNodeOrderID() == 25);
|
||||
REQUIRE(tnanker->getRight()->getLeft()->getRight()->getNodeOrderID() ==
|
||||
26);
|
||||
REQUIRE(tnanker->getRight()->getRight()->getLeft()->getNodeOrderID() ==
|
||||
35);
|
||||
|
||||
nTree->deleteNode(30);
|
||||
REQUIRE(tnanker->getNodeOrderID() == 20);
|
||||
REQUIRE(tnanker->getRight()->getNodeOrderID() == 35);
|
||||
REQUIRE(tnanker->getRight()->getRight()->getNodeOrderID() == 40);
|
||||
REQUIRE(tnanker->getRight()->getRight()->getLeft() == nullptr);
|
||||
REQUIRE(tnanker->getRight()->getRight()->getRight() == nullptr);
|
||||
REQUIRE(tnanker->getRight()->getLeft()->getNodeOrderID() == 25);
|
||||
REQUIRE(tnanker->getRight()->getLeft()->getRight()->getNodeOrderID() ==
|
||||
26);
|
||||
REQUIRE(tnanker->getRight()->getLeft()->getLeft() == nullptr);
|
||||
|
||||
nTree->deleteNode(35);
|
||||
REQUIRE(tnanker->getNodeOrderID() == 20);
|
||||
REQUIRE(tnanker->getRight()->getNodeOrderID() == 40);
|
||||
REQUIRE(tnanker->getRight()->getLeft()->getNodeOrderID() == 25);
|
||||
}
|
||||
|
||||
SECTION("Loeschen von Nodes - ab Wurzel")
|
||||
{
|
||||
|
||||
nTree->addNode("Mayer", 20, 0, 0);
|
||||
nTree->addNode("Mayer2", 10, 0, 0);
|
||||
nTree->addNode("Mayer3", 30, 0, 0);
|
||||
nTree->addNode("Mayer4", 40, 0, 0);
|
||||
nTree->addNode("Mayer5", 35, 0, 0);
|
||||
nTree->addNode("Mayer6", 25, 0, 0);
|
||||
nTree->addNode("Mayer7", 26, 0, 0);
|
||||
|
||||
TreeNode* tnanker = get_anker(*nTree); // Initiale Übergrabe des Ankers
|
||||
|
||||
/*
|
||||
Lösche den Baum schrittweise durch entfernen der Wurzel
|
||||
*/
|
||||
REQUIRE(tnanker->getNodeOrderID() == 20);
|
||||
nTree->deleteNode(20);
|
||||
tnanker = get_anker(
|
||||
*nTree); // Anker hat sich geändert, neue Übergabe erfoderlich
|
||||
|
||||
REQUIRE(tnanker->getNodeOrderID() == 25);
|
||||
REQUIRE(tnanker->getRight()->getNodeOrderID() == 30);
|
||||
REQUIRE(tnanker->getRight()->getLeft()->getNodeOrderID() == 26);
|
||||
REQUIRE(tnanker->getRight()->getRight()->getNodeOrderID() == 40);
|
||||
|
||||
nTree->deleteNode(25);
|
||||
tnanker = get_anker(
|
||||
*nTree); // Anker hat sich geändert, neue Übergabe erfoderlich
|
||||
|
||||
REQUIRE(tnanker->getNodeOrderID() == 26);
|
||||
REQUIRE(tnanker->getRight()->getNodeOrderID() == 30);
|
||||
REQUIRE(tnanker->getRight()->getLeft() == nullptr);
|
||||
REQUIRE(tnanker->getRight()->getRight()->getNodeOrderID() == 40);
|
||||
|
||||
nTree->deleteNode(26);
|
||||
tnanker = get_anker(
|
||||
*nTree); // Anker hat sich geändert, neue Übergabe erfoderlich
|
||||
|
||||
REQUIRE(tnanker->getNodeOrderID() == 30);
|
||||
REQUIRE(tnanker->getRight()->getNodeOrderID() == 40);
|
||||
REQUIRE(tnanker->getRight()->getLeft()->getNodeOrderID() == 35);
|
||||
REQUIRE(tnanker->getRight()->getRight() == nullptr);
|
||||
|
||||
nTree->deleteNode(30);
|
||||
tnanker = get_anker(
|
||||
*nTree); // Anker hat sich geändert, neue Übergabe erfoderlich
|
||||
|
||||
REQUIRE(tnanker->getNodeOrderID() == 35);
|
||||
REQUIRE(tnanker->getRight()->getNodeOrderID() == 40);
|
||||
REQUIRE(tnanker->getRight()->getLeft() == nullptr);
|
||||
REQUIRE(tnanker->getRight()->getRight() == nullptr);
|
||||
|
||||
nTree->deleteNode(35);
|
||||
tnanker = get_anker(
|
||||
*nTree); // Anker hat sich geändert, neue Übergabe erfoderlich
|
||||
|
||||
REQUIRE(tnanker->getNodeOrderID() == 40);
|
||||
REQUIRE(tnanker->getRight() == nullptr);
|
||||
REQUIRE(tnanker->getLeft()->getNodeOrderID() == 10);
|
||||
|
||||
nTree->deleteNode(40);
|
||||
tnanker = get_anker(
|
||||
*nTree); // Anker hat sich geändert, neue Übergabe erfoderlich
|
||||
|
||||
REQUIRE(tnanker->getNodeOrderID() == 10);
|
||||
REQUIRE(tnanker->getRight() == nullptr);
|
||||
REQUIRE(tnanker->getLeft() == nullptr);
|
||||
|
||||
nTree->deleteNode(10);
|
||||
tnanker = get_anker(
|
||||
*nTree); // Anker hat sich geändert, neue Übergabe erfoderlich
|
||||
|
||||
REQUIRE(tnanker == nullptr);
|
||||
}
|
||||
|
||||
SECTION("Hinzufuegen von Nodes - Erzeuge Grossbaum")
|
||||
{
|
||||
|
||||
for (int i = 0; i < 124; i++)
|
||||
{
|
||||
string info = "Name-" + to_string(i);
|
||||
|
||||
// Random Income und PostCode
|
||||
double r = rand() + 1;
|
||||
int PostCode = rand() + 1;
|
||||
nTree->addNode(info, 0, r, PostCode);
|
||||
}
|
||||
nTree->printAll();
|
||||
nTree->printLevelOrder();
|
||||
std::cout << "========================================" << endl;
|
||||
std::cout << "Testausgabe des Grossbaums abgeschlossen" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
/***********************************************
|
||||
* Testroutine des Knotens:
|
||||
* - Einfaches pruefen der Getter und Setter in Ausführung
|
||||
*/
|
||||
TEST_CASE("TreeNode Testing", "[TREENODE]")
|
||||
{
|
||||
|
||||
Tree* smallTree = new Tree();
|
||||
smallTree->addNode("Herzog", 20, 0, 0);
|
||||
TreeNode* ref = get_anker(*smallTree);
|
||||
|
||||
SECTION("Getter von TreeNode - simple")
|
||||
{
|
||||
|
||||
REQUIRE(ref->getName() == "Herzog");
|
||||
REQUIRE(ref->getAge() == 20);
|
||||
REQUIRE(ref->getIncome() == 0);
|
||||
REQUIRE(ref->getLeft() == nullptr);
|
||||
REQUIRE(ref->getRight() == nullptr);
|
||||
REQUIRE(ref->getNodeChronologicalID() == 0);
|
||||
REQUIRE(ref->getNodeOrderID() == 20);
|
||||
REQUIRE(ref->getPostCode() == 0);
|
||||
}
|
||||
|
||||
SECTION("Setter von TreeNode - simple")
|
||||
{
|
||||
|
||||
ref->setAge(22);
|
||||
REQUIRE(ref->getAge() == 22);
|
||||
|
||||
ref->setIncome(1000);
|
||||
REQUIRE(ref->getIncome() == 1000);
|
||||
|
||||
ref->setLeft(nullptr);
|
||||
REQUIRE(ref->getLeft() == nullptr);
|
||||
|
||||
ref->setRight(nullptr);
|
||||
REQUIRE(ref->getRight() == nullptr);
|
||||
|
||||
ref->setName("Kaiser");
|
||||
REQUIRE(ref->getName() == "Kaiser");
|
||||
|
||||
ref->setPostCode(1000);
|
||||
REQUIRE(ref->getPostCode() == 1000);
|
||||
}
|
||||
delete smallTree;
|
||||
}
|
||||
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
// http://www.hashemall.com/
|
||||
// Zeile 1-311 hat den SHA 256 Hashwert:
|
||||
// 2AD58F06D997AD8B7AABE694372CBEDF31F718B975E1F71A87C360B0DFA2B469
|
||||
18182
P1/ADS_P1_2_Binaerbaum/catch.h
Executable file
18182
P1/ADS_P1_2_Binaerbaum/catch.h
Executable file
File diff suppressed because it is too large
Load Diff
128
P1/ADS_P1_2_Binaerbaum/main.cpp
Executable file
128
P1/ADS_P1_2_Binaerbaum/main.cpp
Executable file
@@ -0,0 +1,128 @@
|
||||
/*************************************************
|
||||
* ADS Praktikum 1.2
|
||||
* main.cpp
|
||||
*
|
||||
*************************************************/
|
||||
#define CATCH_CONFIG_RUNNER
|
||||
#include "Tree.h"
|
||||
#include "catch.h"
|
||||
#include <iostream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
///////////////////////////////////////
|
||||
// Hilfsmethoden fürs Menü hier:
|
||||
|
||||
/***************************
|
||||
** Vorgegebene Funktion **
|
||||
***************************
|
||||
"mainscreen_addTreeCSV"
|
||||
|
||||
Importiert CSV Datei in bestehenden Baum.
|
||||
Bei Aufruf in der main() Methode, muss der Pointer auf den Anker des Baums, als Parameter übergeben werden.
|
||||
Es wird die im gleichen Verzeichnis liegende Datei "ExportZielanalyse.csv" geladen.
|
||||
****************************/
|
||||
|
||||
void mainscreen_addTreeCSV(Tree*& ref) {
|
||||
char j;
|
||||
cout << "+ Moechten Sie die Daten aus der Datei ExportZielanalyse.csv "
|
||||
"importieren(j / n) ? >";
|
||||
cin >> j;
|
||||
if (j == 'j') {
|
||||
ifstream csvread;
|
||||
csvread.open("ExportZielanalyse.csv", ios::in);
|
||||
if (!csvread.is_open()) {
|
||||
cout << "Fehler beim Lesen!" << endl;
|
||||
return;
|
||||
}
|
||||
else {
|
||||
string name, age, postcode, income;
|
||||
|
||||
while (!csvread.eof()) {
|
||||
getline(csvread, name, ';');
|
||||
getline(csvread, age, ';');
|
||||
getline(csvread, income, ';');
|
||||
getline(csvread, postcode, '\n');
|
||||
ref->addNode(name, stoi(age), stod(income), stoi(postcode));
|
||||
}
|
||||
csvread.close();
|
||||
}
|
||||
cout << "+ Daten wurden dem Baum hinzugefuegt." << endl;
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
|
||||
int result = Catch::Session().run();
|
||||
|
||||
Tree* Baum = new Tree();
|
||||
int engb;
|
||||
|
||||
while(true){
|
||||
cout << "====================================\n"
|
||||
"1) Datensatz einfuegen, manuell\n"
|
||||
"2) Datensatz einfuegen, CSV Datei\n"
|
||||
"3) Datensatz loeschen\n"
|
||||
"4) Suchen\n"
|
||||
"5) Datenstruktur anzeigen (pre, post, in)\n"
|
||||
"6) Level-Order anzeigen\n"
|
||||
"7) Beenden\n"
|
||||
"?> ";
|
||||
cin >> engb;
|
||||
switch (engb) {
|
||||
case 1: {
|
||||
string name;
|
||||
int alter;
|
||||
double einkommen;
|
||||
int plz;
|
||||
cout << "+ Bitte geben Sie die den Datensatz ein\n"
|
||||
"Name ?> ";
|
||||
cin >> name;
|
||||
cout << "Alter ?> ";
|
||||
cin >> alter;
|
||||
cout << "Einkommen ?> ";
|
||||
cin >> einkommen;
|
||||
cout << "PLZ ?> ";
|
||||
cin >> plz;
|
||||
Baum->addNode(name, alter, einkommen, plz);
|
||||
cout << "+ Ihr Datensatz wurde eingefuegt" << endl;
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
mainscreen_addTreeCSV(Baum);
|
||||
break;
|
||||
}
|
||||
case 3: {
|
||||
int nodeOrderID;
|
||||
cout << "+ Bitte geben Sie den zu loeschenden Datensatz an\n"
|
||||
"OrderID ?> ";
|
||||
cin >> nodeOrderID;
|
||||
Baum->deleteNode(nodeOrderID);
|
||||
break;
|
||||
}
|
||||
case 4: {
|
||||
string name;
|
||||
cout << "+ Bitte geben Sie den zu suchenden Datensatz an\n"
|
||||
"Name ?> ";
|
||||
cin >> name;
|
||||
cout << "+ Fundstellen:\n";
|
||||
Baum->searchNode(name);
|
||||
break;
|
||||
}
|
||||
case 5: {
|
||||
Baum->printAll();
|
||||
break;
|
||||
}
|
||||
case 6: {
|
||||
Baum->printLevelOrder();
|
||||
break;
|
||||
}
|
||||
case 7:{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
};
|
||||
system("PAUSE");
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user