-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
34 changed files
with
4,052 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
# AVL 트리 실전 예제 | ||
AVL 트리 실전적인 풀이에서 신경 써야 할 부분은 딱 개이다. <br> | ||
1. RL, LR 등의 판단은 처음 BF가 깨진 곳에서 판단. | ||
2. **BF가 깨진 곳이 부모-자식간에 이어서 여러 곳에서 발생했다면, 아래쪽을 선택해서 재분배한다** | ||
3. LR, RL 회전시 그냥 세 노드에 대해 **중간 값 노드를 루트로 해서, 그 노드를 기준으로 다시 서브트리를 만든다.** | ||
|
||
## 예제 1 | ||
{MAR, MAY, NOV, AUG, APR, JAN, DEC, JUL, FEB, JUN, OCT, SEP} <br> | ||
|
||
기본적으로 책에서 제공된 순서이다. 여러번 연습했다. | ||
![avl1](https://user-images.githubusercontent.com/71186266/206129643-ca66c1e0-50c5-443c-929d-ced7d696c8d9.png) | ||
|
||
|
||
|
||
1. 첫 LR 회전이다. **BF가 깨진 루트를 기준으로** LR로 판단한 것을 확인할 수 있다. | ||
2. MAY, AUG, MAR에 대해 중간값인 MAR이 루트가 되어 새로 트리가 짜인 것을 확인할 수 있다. | ||
3. 왜 MAY 부터 AUG, MAR로 골랐는가? **깨진 곳이 기준이니까** | ||
|
||
|
||
|
||
#### 여기도 중요하다. BF 깨진 곳이 두 곳! | ||
![avl2](https://user-images.githubusercontent.com/71186266/206129645-9c719999-f566-4bd7-9c94-e55f822de919.png) | ||
|
||
|
||
1. **위에서 언급한 것 처럼 MAR, AUG 둘 다 깨졌지만, AUG를 기준으로 회전한다.** | ||
2. **둘 다 깨졌으면 자식쪽!!!** 그래서 **RL회전이라고 부른다!!** | ||
3. AUG, JAN, DEC를 기준으로 회전하는데, 중간값인 DEC를 루트로 새로 서브트리들을 작성한다 | ||
|
||
![avl3](https://user-images.githubusercontent.com/71186266/206129648-9db227a8-c645-4abb-8f02-f94b46bb72ea.png) | ||
|
||
완성된 모습.. | ||
|
||
## 예제 2 | ||
{'NOV', 'APR', 'OCT', 'MAY', 'DEC', 'AUG', 'SEP', 'JAN', 'JUL', 'JUN', 'MAR', 'FEB'}의 순서로 입력이 들어온 상황. <br> | ||
|
||
![KakaoTalk_20221207_172605855](https://user-images.githubusercontent.com/71186266/206127258-74df178f-0901-4c4e-87e6-7b09e65a4db5.jpg) | ||
![RET3](https://user-images.githubusercontent.com/71186266/206127250-103e32e1-b55d-4036-9b40-91298f5261d8.png) | ||
|
||
위의 사진은 직접 그려본 것이고, 아래 사진은 visualizer를 사용한 결과이다. 같은 key값의 집합에 대해, 같은 결과를 만든 것을 확인할 수 있다. | ||
|
||
### 결론: | ||
1. 같은 정책 하의 같은 key 구성이여도 입력 순서가 다르면, 트리가 다를 수 있다. | ||
2. 동일 key값이 존재한다면 동일 key값 처리 정책에 따라 트리가 달라질 수 있다. | ||
|
||
## Reference | ||
- Fundamentals of Data Structures in C++ \<HOROWITZ, SAHNI, MEHTA 저> | ||
- [AVL Tree Visualizer](https://www.cs.usfca.edu/~galles/visualization/AVLtree.html) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
// | ||
// Created by Jinho on 12/14/2022. | ||
// | ||
#include "AVL.h" | ||
|
||
Node::Node(int value) { | ||
data = value; | ||
leftChild = rightChild = NULL; | ||
height = 1; | ||
balanceFactor = 0; | ||
} | ||
|
||
void bstree::visit(Node* ptr) { | ||
cout << ptr->data << "\t"; | ||
if (ptr->leftChild) cout << "left : " << ptr->leftChild->data << '\t'; | ||
else cout << "left : empty\t"; | ||
if (ptr->rightChild) cout << "right : " << ptr->rightChild->data << '\t'; | ||
else cout << "right : empty\t"; | ||
cout << '\n'; | ||
} | ||
|
||
void bstree::show(Node* root) { | ||
cout << '\n'; | ||
queue<Node*> bfsQueue; | ||
bfsQueue.push(root); | ||
Node *nodeNow; | ||
while (!bfsQueue.empty()) { | ||
nodeNow = bfsQueue.front(); | ||
bfsQueue.pop(); | ||
visit(nodeNow); | ||
if (nodeNow->leftChild) bfsQueue.push(nodeNow->leftChild); | ||
if (nodeNow->rightChild) bfsQueue.push(nodeNow->rightChild); | ||
} | ||
} | ||
|
||
Node *bstree::insert(const int value, Node *&nodeNow) { | ||
if (!nodeNow) return nodeNow = new Node(value); | ||
if (value == nodeNow->data) return nodeNow; | ||
if (value < nodeNow->data) nodeNow->leftChild = insert(value, nodeNow->leftChild); | ||
if (value > nodeNow->data) nodeNow->rightChild = insert(value, nodeNow->rightChild); | ||
|
||
setBF(nodeNow); | ||
if (nodeNow->balanceFactor < -1 || nodeNow->balanceFactor > 1) return rotation(nodeNow, value); | ||
return nodeNow; | ||
} | ||
|
||
bool bstree::search(const int key, Node* root) { | ||
cout << root->data; | ||
|
||
if (root->data == key) { | ||
cout << '\n'; | ||
return true; | ||
} | ||
|
||
cout << " -> "; | ||
|
||
Node *nodeNext = key <= root->data ? root->leftChild : root->rightChild; | ||
if (!nodeNext) { | ||
cout << " X (there is no nodes that has value " << key << ") \n"; | ||
return false; | ||
} | ||
|
||
return search(key, nodeNext); | ||
} | ||
|
||
Node *bstree::del(const int key, Node* nodeNow) { | ||
if (!nodeNow) return nodeNow; | ||
if (key < nodeNow->data) nodeNow->leftChild = del(key, nodeNow->leftChild); | ||
else if (key > nodeNow->data) nodeNow->rightChild = del(key, nodeNow->rightChild); | ||
else { | ||
// find the node | ||
if (!nodeNow->leftChild && !nodeNow->rightChild) nodeNow = NULL; | ||
else if (!nodeNow->leftChild) nodeNow = nodeNow->rightChild; | ||
else if (!nodeNow->rightChild) nodeNow = nodeNow->leftChild; | ||
else { | ||
Node *ptr = nodeNow->leftChild; | ||
while (ptr->rightChild) { | ||
ptr = ptr->rightChild; | ||
} | ||
nodeNow->data = ptr->data; | ||
del(nodeNow->data, nodeNow->leftChild); | ||
} | ||
} | ||
if (!nodeNow) return nodeNow; | ||
|
||
setBF(nodeNow); | ||
if (nodeNow->balanceFactor < -1 || nodeNow->balanceFactor > 1) return rotation(nodeNow, key); | ||
return nodeNow; | ||
} | ||
|
||
void bstree::setBF(Node* startNode) { | ||
int leftHeight, rightHeight; | ||
leftHeight = startNode->leftChild ? startNode->leftChild->height : 0; | ||
rightHeight = startNode->rightChild ? startNode->rightChild->height : 0; | ||
startNode->height = leftHeight < rightHeight ? rightHeight + 1 : leftHeight + 1; | ||
startNode->balanceFactor = leftHeight - rightHeight; | ||
} | ||
|
||
Node *bstree::rotation(Node* startNode, int value) { | ||
// 1. LL rotation | ||
Node *tempNode; | ||
if (startNode->leftChild && value <= startNode->leftChild->data) { | ||
tempNode = startNode->leftChild; | ||
rotation(startNode, startNode->leftChild); | ||
return tempNode; | ||
} | ||
|
||
// 2. RR rotation | ||
if (startNode->rightChild && startNode->rightChild->data < value) { | ||
tempNode = startNode->rightChild; | ||
rotation(startNode, startNode->rightChild); | ||
return tempNode; | ||
} | ||
|
||
// 3. LR rotation | ||
if (value <= startNode->data) { | ||
tempNode = startNode->leftChild->rightChild; | ||
rotation(startNode->leftChild, startNode->leftChild->rightChild); | ||
rotation(startNode, startNode->leftChild); | ||
} | ||
|
||
// 4. RL rotation | ||
if (startNode->data < value) { | ||
tempNode = startNode->rightChild->leftChild; | ||
rotation(startNode->rightChild, startNode->rightChild->leftChild); | ||
rotation(startNode, startNode->rightChild); | ||
} | ||
return tempNode; | ||
} | ||
|
||
void bstree::rotation(Node* start, Node* end) { | ||
if (start->leftChild == end) { | ||
start->leftChild = end->rightChild; | ||
end->rightChild = start; | ||
} else { | ||
start->rightChild = end->leftChild; | ||
end->leftChild = start; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
// | ||
// Created by Jinho on 12/14/2022. | ||
// | ||
|
||
#ifndef AVL_H | ||
#define AVL_H | ||
typedef struct Node* nodeptr; | ||
#include <queue> | ||
#include <iostream> | ||
using namespace std; | ||
struct Node { | ||
int data, height, balanceFactor; | ||
Node *leftChild, *rightChild; | ||
Node(int value); | ||
}; | ||
|
||
class bstree { | ||
public: | ||
void visit(Node* ptr); | ||
Node *insert(const int value, Node*& root); | ||
void show(Node* root); | ||
bool search(const int key, Node* root); | ||
Node *del(const int key, Node* root); | ||
void setBF(Node* startNode); | ||
void rotation(Node* start, Node* end); | ||
Node *rotation(Node* startNode, int value); | ||
}; | ||
|
||
#endif //ALGORITHEM_AVL_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
#include "AVL.h" | ||
int main() { | ||
nodeptr root; | ||
int a, choice, findele, delele; | ||
bstree bst; | ||
bool flag = true; | ||
root = NULL; | ||
bst.insert(19, root); | ||
bst.insert(10, root); | ||
bst.insert(46, root); | ||
bst.insert(4, root); | ||
bst.insert(14, root); | ||
bst.insert(37, root); | ||
bst.insert(55, root); | ||
bst.insert(7, root); | ||
bst.insert(12, root); | ||
bst.insert(18, root); | ||
bst.insert(28, root); | ||
bst.insert(40, root); | ||
bst.insert(51, root); | ||
bst.insert(61, root); | ||
bst.insert(21, root); | ||
bst.insert(32, root); | ||
bst.insert(49, root); | ||
bst.insert(58, root); | ||
|
||
while (flag) { | ||
cout << "Enter the choice: (1 : search, 2 : add, 3 : delete, 4 : show, 0 : exit)"; | ||
cin >> choice; | ||
|
||
switch (choice) { | ||
case 1: | ||
cout << "Enter node to search:"; | ||
cin >> findele; | ||
if (root != NULL) bst.search(findele, root); | ||
break; | ||
case 2: | ||
cout << "Enter a new value:"; | ||
cin >> a; | ||
bst.insert(a, root); | ||
bst.show(root); | ||
break; | ||
case 3: | ||
cout << "Enter node to delete:"; | ||
cin >> delele; | ||
bst.del(delele, root); | ||
bst.show(root); | ||
break; | ||
case 4: | ||
if (root != NULL) bst.show(root); | ||
break; | ||
case 0: | ||
cout << "\n\tThank your for using AVL maxTree program\n" << endl; | ||
flag = false; | ||
break; | ||
default: cout << "Sorry! wrong input\n" << endl; break; | ||
} | ||
} | ||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
#include "maxheap.h" | ||
#include <iostream> | ||
int main(int argc, char *argv[]) | ||
{ | ||
int N, i, data; | ||
Maxheap<int> H(10); | ||
if(argc != 2) | ||
{ | ||
cerr << "wrong argument count" << endl; return 1; | ||
} | ||
fstream fin(argv[1]); | ||
if(!fin) | ||
{ | ||
cerr << argv[1] << " open failed" << endl; | ||
return 1; | ||
} | ||
fin >> N; for(i=0; i<N; i++) | ||
{ | ||
fin >> data; | ||
H.Push(data); | ||
} | ||
|
||
cout << H; while(!H.IsEmpty()) | ||
{ | ||
|
||
cout << H.Top() << " " ; H.Pop(); | ||
} | ||
cout << endl; | ||
fin.close(); | ||
return 0; | ||
} |
Oops, something went wrong.