Update Lab6

This commit is contained in:
miti99 committed 2018-10-28 15:51:33 +07:00
1 parent f966748502
commit f8418fa0e6
5 files changed
+553

No files matched your search

+92
View File
@@ -0,0 +1,92 @@
#ifndef AVLNODE_H
#define AVLNODE_H
#include <iostream>
using namespace std;
template <class T>
class AVLNode
{
public:
T data;
int balance = 0;
int height = 1;
AVLNode *parent = nullptr;
AVLNode *left = nullptr;
AVLNode *right = nullptr;
AVLNode();
AVLNode(T data);
~AVLNode();
void update();
void print(int space);
template <class U>
friend ostream &operator << (ostream &os, AVLNode<U> *node);
};
template <class T>
AVLNode<T>::AVLNode()
{
this->balance = 0;
this->height = 1;
this->parent = nullptr;
this->left = nullptr;
this->right = nullptr;
}
template <class T>
AVLNode<T>::AVLNode(T data)
{
this->data = data;
this->balance = 0;
this->height = 1;
this->parent = nullptr;
this->left = nullptr;
this->right = nullptr;
}
template <class T>
AVLNode<T>::~AVLNode()
{
this->parent = nullptr;
delete this->left;
this->left = nullptr;
delete this->right;
this->right = nullptr;
}
template <class T>
void AVLNode<T>::update()
{
int hl = 0;
int hr = 0;
if (this->left != nullptr)
hl = this->left->height;
if (this->right != nullptr)
hr = this->right->height;
this->height = max(hl, hr) + 1;
this->balance = hl - hr;
}
template <class T>
void AVLNode<T>::print(int space)
{
if (space < 0)
return;
for (int i = 0; i < space - this->height; ++i)
cout << "\t";
this->print();
}
template <class T>
ostream &operator << (ostream &os, AVLNode<T> *node)
{
if (node == nullptr)
return os;
os << node->left;
os << node->data;
os << node->right;
return os;
}
#endif // AVLNODE_H
+262
View File
@@ -0,0 +1,262 @@
#ifndef AVLTREE_H
#define AVLTREE_H
#include <stack>
#include "avlnode.h"
template <class T>
class AVLTree
{
private:
AVLNode<T> *root = nullptr;
AVLNode<T> *rotateLeft(AVLNode<T> *node);
AVLNode<T> *rotateRight(AVLNode<T> *node);
int getHeight(AVLNode<T> *node);
void rebalance(AVLNode<T> *node);
public:
AVLTree();
~AVLTree();
bool insert(AVLNode<T> *newNode);
AVLNode<T> *search(T searchData);
bool remove(const T removeData);
void printAsList();
void printNLR();
template <class U>
friend ostream &operator << (ostream &os, AVLTree<U> *tree);
};
template <class T>
AVLTree<T>::AVLTree()
{
this->root = nullptr;
}
template <class T>
AVLTree<T>::~AVLTree()
{
delete this->root;
this->root = nullptr;
}
template <class T>
void AVLTree<T>::rebalance(AVLNode<T> *node)
{
if (node == nullptr)
return;
node->update();
if (node->balance > 1) {
if (node->left->balance < -1)
node->left = rotateLeft(node->left);
node = rotateRight(node);
} else if (node->balance < -1) {
if (node->right->balance > 1)
node->right = rotateRight(node->right);
node = rotateLeft(node);
}
if (node->parent == nullptr)
this->root = node;
else
rebalance(node->parent);
}
template <class T>
AVLNode<T> *AVLTree<T>::rotateLeft(AVLNode<T> *node)
{
AVLNode<T> *temp = node->right;
AVLNode<T> *tmp = temp->left;
AVLNode<T> *parent = node->parent;
temp->parent = parent;
node->right = tmp;
if (tmp != nullptr) {
tmp->parent = node;
}
temp->left = node;
node->parent = temp;
if (parent != nullptr) {
if (parent->left == node)
parent->left = temp;
else
parent->right = temp;
}
node->update();
temp->update();
return temp;
}
template <class T>
AVLNode<T> *AVLTree<T>::rotateRight(AVLNode<T> *node)
{
AVLNode<T> *temp = node->left;
AVLNode<T> *tmp = temp->right;
AVLNode<T> *parent = node->parent;
temp->parent = parent;
node->left = tmp;
if (tmp != nullptr) {
tmp->parent = node;
}
temp->right = node;
node->parent = temp;
if (parent != nullptr) {
if (parent->left == node)
parent->left = temp;
else
parent->right = temp;
}
node->update();
temp->update();
return temp;
}
template <class T>
int AVLTree<T>::getHeight(AVLNode<T> *node)
{
if (node == nullptr)
return 0;
return node->height;
}
template <class T>
bool AVLTree<T>::insert(AVLNode<T> *newNode)
{
if (newNode == nullptr)
return false;
if (this->root == nullptr) {
this->root = newNode;
return true;
}
AVLNode<T> *temp = this->root;
AVLNode<T> *parent;
while (true) {
if (temp->data == newNode->data)
return false;
parent = temp;
bool goLeft = (newNode->data < temp->data);
temp = goLeft ? temp->left : temp->right;
if (temp == nullptr) {
if (goLeft) {
parent->left = newNode;
newNode->parent = parent;
} else {
parent->right = newNode;
newNode->parent = parent;
}
rebalance(parent);
return true;
}
}
}
template <class T>
bool AVLTree<T>::remove(const T removeData)
{
AVLNode<T> *temp = this->root;
while (temp != nullptr) {
if (removeData < temp->data)
temp = temp->left;
else if (removeData > temp->data)
temp = temp->right;
else
break;
}
if (temp == nullptr)
return false;
AVLNode<T> *del = temp;
if (temp->left != nullptr) {
del = temp->left;
while (del->right != nullptr)
del = del->right;
}
AVLNode<T> *parent = nullptr;
if (del == this->root) {
this->root = this->root->right;
if (this->root != nullptr)
this->root->parent = nullptr;
} else if (del != temp) {
temp->data = del->data;
parent = del->parent;
if (parent->left == del)
parent->left = del->left;
else
parent->right = del->left;
if (del->left != nullptr)
del->left->parent = parent;
} else {
parent = del->parent;
if (parent->left == del)
parent->left = del->right;
else
parent->right = del->right;
if (del->right != nullptr)
del->right->parent = parent;
}
if (parent != nullptr)
this->rebalance(parent);
return true;
}
template <class T>
void AVLTree<T>::printNLR()
{
stack<AVLNode<T> *> sAVLNode;
stack<int> sNodeLevel;
sAVLNode.push(this->root);
sNodeLevel.push(0);
while (!sAVLNode.empty()) {
AVLNode<T> *tNode = sAVLNode.top();
sAVLNode.pop();
int tLevel = sNodeLevel.top();
sNodeLevel.pop();
for (int i = 0; i < tLevel; ++i) {
cout << " ";
}
if (tNode == nullptr) {
cout << "NULL" << endl;
continue;
}
cout << tNode->data << "(" << tNode->balance << ")" << endl;
sAVLNode.push(tNode->right);
sNodeLevel.push(tLevel + 1);
sAVLNode.push(tNode->left);
sNodeLevel.push(tLevel + 1);
}
}
template <class T>
AVLNode<T> *AVLTree<T>::search(T searchData)
{
AVLNode<T> *temp = this->root;
while (temp != nullptr) {
if (searchData < temp->data)
temp = temp->left;
else if (searchData > temp->data)
temp = temp->right;
else
return temp;
}
return nullptr;
}
template <class T>
void printLNR(AVLNode<T> *subroot)
{
if (subroot == nullptr)
return;
printLNR(subroot->left);
cout << subroot->data << endl;
printLNR(subroot->right);
}
template <class T>
void AVLTree<T>::printAsList()
{
printLNR(this->root);
}
template <class T>
ostream &operator << (ostream &os, AVLTree<T> *tree)
{
os << tree->root;
return os;
}
#endif // AVLTREE_H
+56
View File
@@ -0,0 +1,56 @@
#ifndef LAB6_H
#define LAB6_H
#include <fstream>
#include <iostream>
#include <sstream>
#include "avltree.h"
#include "phone.h"
AVLTree<Phone> *readPhoneFromFile(string filename)
{
AVLTree<Phone> *newTree = nullptr;
ifstream file;
file.open(filename, ios::in);
if (!file.is_open()) {
cout << "Can't open file!" << endl;
} else {
newTree = new AVLTree<Phone>;
string line;
while (getline(file, line)) {
AVLNode<Phone> *newNode = new AVLNode<Phone>;
string str;
stringstream ss;
ss.str(line);
getline(ss, str, ',');
newNode->data.name = str;
getline(ss, str);
newNode->data.number = str;
newTree->insert(newNode);
}
file.close();
}
return newTree;
}
void writePhoneToFile(string filename, AVLTree<Phone> *tree)
{
ofstream file;
file.open(filename, ios::out);
file << tree;
file.close();
}
void printMenu()
{
cout << "========MENU========" << endl;
cout << "Enter your command:" << endl;
cout << "1. Search phone with name." << endl;
cout << "2. Insert new phone." << endl;
cout << "3. Delete phone with name." << endl;
cout << "4. Print phone list." << endl;
cout << "0. Exit program." << endl;
}
#endif // LAB6_H
+64
View File
@@ -0,0 +1,64 @@
#include <iostream>
#include "lab6.h"
int main()
{
string command = "";
string filename = "phone.csv";
AVLTree<Phone> *phoneTree = readPhoneFromFile(filename);
if (phoneTree == nullptr)
return 1;
while (true) {
system("clear"); // Clear terminal for Linux
printMenu();
getline(cin, command);
if (command == "1") {
cout << "Input full name:" << endl;
string str = "";
getline(cin, str);
Phone searchData(str);
AVLNode<Phone> *searchNode = phoneTree->search(searchData);
if (searchNode == nullptr) {
cout << "Can't file phone with this name!" << endl;
} else {
cout << searchNode->data.name << "'s number is " << searchNode->data.number << endl;
}
} else if (command == "2") {
cout << "Input new name:" << endl;
string str1 = "";
getline(cin, str1);
cout << "Input new number:" << endl;
string str2 = "";
getline(cin, str2);
Phone newData(str1, str2);
AVLNode<Phone> *newNode = new AVLNode<Phone>(newData);
if (newNode == nullptr)
cout << "Error! Out of memory!" << endl;
else if (phoneTree->insert(newNode))
cout << "Insert successful!" << endl;
else
cout << "Error! Duplicate name!" << endl;
} else if (command == "3") {
cout << "Input name to delete:" << endl;
string str = "";
getline(cin, str);
Phone deleteData(str);
if (phoneTree->remove(deleteData))
cout << "Delete successful!" << endl;
else
cout << "Can't found this name! You must input full name!" << endl;
} else if (command == "4") {
cout << phoneTree;
} else if (command == "0") {
cout << "Good Bye!" << endl;
break;
} else {
cout << "Invalid command!" << endl;
}
writePhoneToFile(filename, phoneTree);
cout << "Press Enter to continue" << endl;
cin.get();
}
return 0;
}
+79
View File
@@ -0,0 +1,79 @@
#ifndef PHONE_H
#define PHONE_H
#include <iostream>
using namespace std;
class Phone
{
public:
string name = "";
string number = "";
Phone();
Phone(string name);
Phone(string name, string number);
~Phone();
friend bool operator < (const Phone &l, const Phone &r);
friend bool operator > (const Phone &l, const Phone &r);
friend bool operator == (const Phone &l, const Phone &r);
friend bool operator <= (const Phone &l, const Phone &r);
friend bool operator >= (const Phone &l, const Phone &r);
friend ostream &operator << (ostream &os, const Phone &phone);
};
Phone::Phone()
{
this->name = "";
this->number = "";
}
Phone::Phone(string name)
{
this->name = name;
this->number = "";
}
Phone::Phone(string name, string number)
{
this->name = name;
this->number = number;
}
Phone::~Phone()
{
;
}
bool operator < (const Phone &l, const Phone &r)
{
return l.name < r.name;
}
bool operator > (const Phone &l, const Phone &r)
{
return l.name > r.name;
}
bool operator == (const Phone &l, const Phone &r)
{
return l.name == r.name;
}
bool operator <= (const Phone &l, const Phone &r)
{
return l.name <= r.name;
}
bool operator >= (const Phone &l, const Phone &r)
{
return l.name >= r.name;
}
ostream &operator << (ostream &os, const Phone &phone)
{
os << phone.name << "," << phone.number << endl;
return os;
}
#endif // PHONE_H