#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <vector>
using std::string;
struct node
{
node *p, *left, *right;
int key;
};
void insert(node *&root, const int key)
{
node *newElement = new node();
newElement->key = key;
newElement->left = newElement->right = NULL;
node *y = NULL, *x = root;
while(x)
{
if(key == x->key) exit(EXIT_FAILURE);
y = x;
x = (key < x->key) ? x->left : x->right;
}
newElement->p = y;
if(!y) root = newElement;
else if(key < y->key) y->left = newElement;
else y->right = newElement;
}
void insert(node *&root, std::vector<int> keys)
{
for(int i = 0; i < keys.size(); i++) insert(root, keys[i]);
}
node* search(node *root, const int key)
{
while( (root) && (root->key != key) )
root = (key < root->key) ? root->left : root->right;
if(root == NULL) exit(EXIT_FAILURE);
return root;
}
node* minNode(node *root)
{
while(root->left) root = root->left;
return root;
}
node* maxNode(node *root)
{
while(root->right) root = root->right;
return root;
}
node* prev(node *root)
{
if(root->left) return maxNode(root->left);
else exit(EXIT_FAILURE);
}
node* next(node *root)
{
if(root->right) return minNode(root->right);
else exit(EXIT_FAILURE);
}
void inorder(node *root, std::ostream& os)
{
if(root) {
inorder(root->left, os);
os << root->key << " ";
inorder(root->right, os);
}
}
void postorder(node *root, std::ostream& os)
{
if(root) {
inorder(root->left, os);
inorder(root->right, os);
os << root->key << " ";
}
}
void preorder(node *root, std::ostream& os)
{
if(root) {
os << root->key << " ";
inorder(root->left, os);
inorder(root->right, os);
}
}
node* remove(node *&root, const int key)
{
node *x = search(root, key); // usuwany wezel
node * y = x->p; // rodzic usuwanego wezla
node *z;
if((x->left) && (x->right))
{
z = (rand() % 2) ? remove(root, prev(x)->key) : remove(root, next(x)->key);
z->left = x->left;
if(z->left) z->left->p = z;
z->right = x->right;
if(z->right) z->right->p = z;
}
else z = (x->left) ? x->left : x->right;
if(z) z->p = y;
if(!y) root = z;
else if(y->left == x) y->left = z; else y->right = z;
return x;
}
void remove(node *&root, std::vector<int> keys)
{
for(int i = 0; i < keys.size(); i++) remove(root, keys[i]);
}
int getNumberOfElements(node *root)
{
if(root)
return 1 + getNumberOfElements(root->left) + getNumberOfElements(root->right);
else
return 0;
}
// ---------------- Wyswietlanie danych, operacje na plikach ----------------------
std::vector<int> loadNumbersFromFile(string nazwa)
{
std::ifstream file;
file.open(nazwa);
if(!file) {
std::cout << "\nNie udalo sie otworzyc pliku\n\n";
exit(EXIT_FAILURE);
}
std::vector<int> numbers;
int current;
while(file >> current)
{
numbers.push_back(current);
file.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); // ignoruj to co nie jest liczba
}
return numbers;
}
void buildTree(node *&root, std::vector<int> &numbers)
{
numbers.size() == 1 ? insert(root, numbers[0]) : insert(root, numbers);
}
void displayTreeInfo(node *root, std::ostream& file)
{
if(root == NULL)
{
file << "Brak wezlow";
}
else
{
file << "Elementy drzewa: ";
inorder(root, file);
file << "\nIlosc elementow: " << getNumberOfElements(root) << "\n\n";
file << "Korzen drzewa: " << root->key << std::endl;
file << "Najmniejszy element: " << minNode(root)->key << std::endl;
file << "Najwiekszy element: " << maxNode(root)->key << std::endl << "\n\n";
file << "Elementy drzewa w porzadku postorder: ";
postorder(root, file);
file << std::endl << "Elementy drzewa w porzadku preorder: ";
preorder(root, file);
}
}
void exportTreeToFile(node *root, string nazwa)
{
std::ofstream file;
file.open(nazwa);
if(!file)
{
std::cout << "\nNie udalo sie otworzyc pliku, lub plik zawiera niepoprawne dane\n\n";
exit(EXIT_FAILURE);
}
displayTreeInfo(root, file);
file.close();
}
int main()
{
using namespace std;
node *root = NULL;
char ch = '0';
while(ch != '5')
{
cout << "1. Dodaj nowe elementy\n"
"2. Wyswietl informacje o obecnym drzewie\n"
"3. Usun wezly\n"
"4. Eksportuj informacje do pliku\n"
"5. Zakoncz\n";
cin >> ch; cin.get();
switch(ch)
{
case '1': case '3':
{
vector<int> numbers;
string line;
cout << "\nPodawaj elementy po spacji: ";
getline(cin, line);
istringstream in(line, istringstream::in);
int current;
while (in >> current) numbers.push_back(current);
(ch == '1') ? insert(root, numbers) : remove(root, numbers);
cout << "\nWcisnij, aby wrocic do menu";
cin.get();
break;
}
case '2':
{
displayTreeInfo(root, cout);
cout << "\n\nWcisnij, aby wrocic do menu";
cin.get();
break;
}
case '4':
{
string nazwa;
cout << "Podaj nazwe pliku: ";
cin >> nazwa;
buildTree(root, loadNumbersFromFile(nazwa));
exportTreeToFile(root, nazwa);
std::cout << "\nDane zostaly wyexportowane do podanego pliku.\n\n";
cin.get(); cin.get();
break;
}
}
system("cls");
}
exit(EXIT_SUCCESS);
}