From f8418fa0e660534782bae5cb964e8e411895efb6 Mon Sep 17 00:00:00 2001 From: Minh Tien Nguyen Date: Sun, 28 Oct 2018 15:51:33 +0700 Subject: [PATCH] Update Lab6 --- CTDL-GT/Lab6/avlnode.h | 92 +++++++++++++++ CTDL-GT/Lab6/avltree.h | 262 +++++++++++++++++++++++++++++++++++++++++ CTDL-GT/Lab6/lab6.h | 56 +++++++++ CTDL-GT/Lab6/main.cpp | 64 ++++++++++ CTDL-GT/Lab6/phone.h | 79 +++++++++++++ 5 files changed, 553 insertions(+) create mode 100644 CTDL-GT/Lab6/avlnode.h create mode 100644 CTDL-GT/Lab6/avltree.h create mode 100644 CTDL-GT/Lab6/lab6.h create mode 100644 CTDL-GT/Lab6/main.cpp create mode 100644 CTDL-GT/Lab6/phone.h diff --git a/CTDL-GT/Lab6/avlnode.h b/CTDL-GT/Lab6/avlnode.h new file mode 100644 index 0000000..b79c462 --- /dev/null +++ b/CTDL-GT/Lab6/avlnode.h @@ -0,0 +1,92 @@ +#ifndef AVLNODE_H +#define AVLNODE_H + +#include + +using namespace std; + +template +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 + friend ostream &operator << (ostream &os, AVLNode *node); +}; + +template +AVLNode::AVLNode() +{ + this->balance = 0; + this->height = 1; + this->parent = nullptr; + this->left = nullptr; + this->right = nullptr; +} + +template +AVLNode::AVLNode(T data) +{ + this->data = data; + this->balance = 0; + this->height = 1; + this->parent = nullptr; + this->left = nullptr; + this->right = nullptr; +} + +template +AVLNode::~AVLNode() +{ + this->parent = nullptr; + delete this->left; + this->left = nullptr; + delete this->right; + this->right = nullptr; +} + +template +void AVLNode::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 +void AVLNode::print(int space) +{ + if (space < 0) + return; + for (int i = 0; i < space - this->height; ++i) + cout << "\t"; + this->print(); +} + +template +ostream &operator << (ostream &os, AVLNode *node) +{ + if (node == nullptr) + return os; + os << node->left; + os << node->data; + os << node->right; + return os; +} + +#endif // AVLNODE_H diff --git a/CTDL-GT/Lab6/avltree.h b/CTDL-GT/Lab6/avltree.h new file mode 100644 index 0000000..84b4511 --- /dev/null +++ b/CTDL-GT/Lab6/avltree.h @@ -0,0 +1,262 @@ +#ifndef AVLTREE_H +#define AVLTREE_H + +#include +#include "avlnode.h" + +template +class AVLTree +{ +private: + AVLNode *root = nullptr; + AVLNode *rotateLeft(AVLNode *node); + AVLNode *rotateRight(AVLNode *node); + int getHeight(AVLNode *node); + void rebalance(AVLNode *node); +public: + AVLTree(); + ~AVLTree(); + bool insert(AVLNode *newNode); + AVLNode *search(T searchData); + bool remove(const T removeData); + void printAsList(); + void printNLR(); + template + friend ostream &operator << (ostream &os, AVLTree *tree); +}; + +template +AVLTree::AVLTree() +{ + this->root = nullptr; +} + +template +AVLTree::~AVLTree() +{ + delete this->root; + this->root = nullptr; +} + +template +void AVLTree::rebalance(AVLNode *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 +AVLNode *AVLTree::rotateLeft(AVLNode *node) +{ + AVLNode *temp = node->right; + AVLNode *tmp = temp->left; + AVLNode *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 +AVLNode *AVLTree::rotateRight(AVLNode *node) +{ + AVLNode *temp = node->left; + AVLNode *tmp = temp->right; + AVLNode *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 +int AVLTree::getHeight(AVLNode *node) +{ + if (node == nullptr) + return 0; + return node->height; +} + +template +bool AVLTree::insert(AVLNode *newNode) +{ + if (newNode == nullptr) + return false; + if (this->root == nullptr) { + this->root = newNode; + return true; + } + AVLNode *temp = this->root; + AVLNode *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 +bool AVLTree::remove(const T removeData) +{ + AVLNode *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 *del = temp; + if (temp->left != nullptr) { + del = temp->left; + while (del->right != nullptr) + del = del->right; + } + AVLNode *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 +void AVLTree::printNLR() +{ + stack *> sAVLNode; + stack sNodeLevel; + sAVLNode.push(this->root); + sNodeLevel.push(0); + while (!sAVLNode.empty()) { + AVLNode *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 +AVLNode *AVLTree::search(T searchData) +{ + AVLNode *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 +void printLNR(AVLNode *subroot) +{ + if (subroot == nullptr) + return; + printLNR(subroot->left); + cout << subroot->data << endl; + printLNR(subroot->right); +} + +template +void AVLTree::printAsList() +{ + printLNR(this->root); +} + +template +ostream &operator << (ostream &os, AVLTree *tree) +{ + os << tree->root; + return os; +} + +#endif // AVLTREE_H diff --git a/CTDL-GT/Lab6/lab6.h b/CTDL-GT/Lab6/lab6.h new file mode 100644 index 0000000..0b941b5 --- /dev/null +++ b/CTDL-GT/Lab6/lab6.h @@ -0,0 +1,56 @@ +#ifndef LAB6_H +#define LAB6_H + +#include +#include +#include + +#include "avltree.h" +#include "phone.h" + +AVLTree *readPhoneFromFile(string filename) +{ + AVLTree *newTree = nullptr; + ifstream file; + file.open(filename, ios::in); + if (!file.is_open()) { + cout << "Can't open file!" << endl; + } else { + newTree = new AVLTree; + string line; + while (getline(file, line)) { + AVLNode *newNode = new AVLNode; + 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 *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 diff --git a/CTDL-GT/Lab6/main.cpp b/CTDL-GT/Lab6/main.cpp new file mode 100644 index 0000000..60144c2 --- /dev/null +++ b/CTDL-GT/Lab6/main.cpp @@ -0,0 +1,64 @@ +#include + +#include "lab6.h" + +int main() +{ + string command = ""; + string filename = "phone.csv"; + AVLTree *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 *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 *newNode = new AVLNode(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; +} diff --git a/CTDL-GT/Lab6/phone.h b/CTDL-GT/Lab6/phone.h new file mode 100644 index 0000000..810d6fe --- /dev/null +++ b/CTDL-GT/Lab6/phone.h @@ -0,0 +1,79 @@ +#ifndef PHONE_H +#define PHONE_H + +#include + +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