diff --git "a/AVL Tree/AVL \355\212\270\353\246\254 \354\213\244\354\240\204 \354\230\210\354\240\234.md" "b/AVL Tree/AVL \355\212\270\353\246\254 \354\213\244\354\240\204 \354\230\210\354\240\234.md" new file mode 100644 index 0000000..2511b31 --- /dev/null +++ "b/AVL Tree/AVL \355\212\270\353\246\254 \354\213\244\354\240\204 \354\230\210\354\240\234.md" @@ -0,0 +1,47 @@ +# AVL 트리 실전 예제 +AVL 트리 실전적인 풀이에서 신경 써야 할 부분은 딱 개이다.
+1. RL, LR 등의 판단은 처음 BF가 깨진 곳에서 판단. +2. **BF가 깨진 곳이 부모-자식간에 이어서 여러 곳에서 발생했다면, 아래쪽을 선택해서 재분배한다** +3. LR, RL 회전시 그냥 세 노드에 대해 **중간 값 노드를 루트로 해서, 그 노드를 기준으로 다시 서브트리를 만든다.** + +## 예제 1 +{MAR, MAY, NOV, AUG, APR, JAN, DEC, JUL, FEB, JUN, OCT, SEP}
+ +기본적으로 책에서 제공된 순서이다. 여러번 연습했다. +![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'}의 순서로 입력이 들어온 상황.
+ +![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++ \ +- [AVL Tree Visualizer](https://www.cs.usfca.edu/~galles/visualization/AVLtree.html) diff --git "a/AVL Tree/\354\275\224\353\223\234/AVL.cpp" "b/AVL Tree/\354\275\224\353\223\234/AVL.cpp" new file mode 100644 index 0000000..5fbee17 --- /dev/null +++ "b/AVL Tree/\354\275\224\353\223\234/AVL.cpp" @@ -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 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; + } +} diff --git "a/AVL Tree/\354\275\224\353\223\234/AVL.h" "b/AVL Tree/\354\275\224\353\223\234/AVL.h" new file mode 100644 index 0000000..3f9098d --- /dev/null +++ "b/AVL Tree/\354\275\224\353\223\234/AVL.h" @@ -0,0 +1,29 @@ +// +// Created by Jinho on 12/14/2022. +// + +#ifndef AVL_H +#define AVL_H +typedef struct Node* nodeptr; +#include +#include +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 diff --git "a/AVL Tree/\354\275\224\353\223\234/hw12.cpp" "b/AVL Tree/\354\275\224\353\223\234/hw12.cpp" new file mode 100644 index 0000000..2ba6c7a --- /dev/null +++ "b/AVL Tree/\354\275\224\353\223\234/hw12.cpp" @@ -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; +} diff --git a/Heap/Max Heap Code/hw9.cpp b/Heap/Max Heap Code/hw9.cpp new file mode 100644 index 0000000..2c14b67 --- /dev/null +++ b/Heap/Max Heap Code/hw9.cpp @@ -0,0 +1,31 @@ +#include "maxheap.h" +#include +int main(int argc, char *argv[]) +{ + int N, i, data; + Maxheap 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> data; + H.Push(data); + } + + cout << H; while(!H.IsEmpty()) + { + + cout << H.Top() << " " ; H.Pop(); + } + cout << endl; + fin.close(); + return 0; +} diff --git a/Heap/Max Heap Code/maxheap.h b/Heap/Max Heap Code/maxheap.h new file mode 100644 index 0000000..2ae4a5f --- /dev/null +++ b/Heap/Max Heap Code/maxheap.h @@ -0,0 +1,108 @@ +#ifndef MAXHEAP_H +#define MAXHEAP_H +#include + +using namespace std; + +template +class Maxheap { +private: + void ChangeSize1D(int); + T* heap; + int heapSize; + int capacity; +public: + Maxheap(int); + void Push(const T &); + + void Pop(); + bool IsEmpty() {return heapSize == 0;} + T Top() {return heap[1];} + template friend ostream &operator <<(ostream &, Maxheap &); +}; + +template +ostream &operator <<(ostream &os, Maxheap &H) +{ + os << " "; + int i; + for(i=1; i<=H.heapSize; i++) + os << i << ":" << H.heap[i] << " "; + os << endl; + return os; +} + +template +Maxheap::Maxheap(int _capacity = 10) : heapSize(0) +{ + if(_capacity < 1) + throw " Must be > 0"; + capacity = _capacity; + heap = new T[capacity+1]; +} + +template +void Maxheap::ChangeSize1D(int size) +{ + T temp[size+1]; + for (int i = 1; i < capacity; i++) { + temp[i] = heap[i]; + } + heap = temp; + capacity = size; +} + +template +void Maxheap::Push(const T &value) { + if (heapSize == capacity) ChangeSize1D(2*capacity); + + heapSize++; + if (heapSize == 1) { + heap[1] = value; + } else { + T parent = heap[heapSize >> 1]; + + int idx = heapSize; + T child = heap[idx]; + while (idx != 1 && heap[idx / 2] < heap[idx]) { + int temp = heap[idx / 2]; + heap[idx / 2] = heap[idx]; + heap[idx] = temp; + + idx = idx / 2; + } + } +} + +template +void Maxheap::Pop() { + if(heapSize <= 0) { + return; + } else if (heapSize == 1) { + heapSize--; + return heap[1]; + } + heap[1] = heap[heapSize]; + heapSize--; + + int idx = 1; + while(idx*2 <= heapSize) { + int child; + if (idx*2 + 1 > heapSize) { + child = idx * 2; + } else { + child = heap[idx * 2] > heap[idx * 2 + 1] ? idx * 2 : idx * 2 + 1; + } + + if(heap[child] <= heap[idx]) break; + int temp = heap[child]; + heap[child] = heap[idx]; + heap[idx] = temp; + + idx = child; + } +} + + + +#endif diff --git a/Linked List/list.cpp b/Linked List/list.cpp new file mode 100644 index 0000000..f0b3176 --- /dev/null +++ b/Linked List/list.cpp @@ -0,0 +1,65 @@ +#include +#include "list.h" + +ostream& operator<<(ostream& os, IntList& il) { + Node *ptr = il.first; + while (ptr != NULL) { + os << ptr->data << " "; ptr = ptr->link; + } + os << endl; + return os; +} + +void IntList::Push_Back(int e) { + if (!first) + first = last = new Node(e); + else { + last->link = new Node(e); + last = last->link; + } +} +void IntList::Push_Front(int e) { + if (!first) { + first = last = new Node(e); + } else { + Node* new_first = new Node(e); + new_first->link = first; + first = new_first; + } +} +void IntList::Insert(int e) { + if (!first) { + first = last = new Node(e); + } + else if (first->data >= e){ + Push_Front(e); + } + else{ + Node *ptr = first; + + while (ptr->link != NULL && ptr->link->data < e) { + ptr = ptr->link; + } + + if (ptr->link != NULL) { + Node *new_node = new Node(e); + new_node->link = ptr->link; + ptr->link = new_node; + } else Push_Back(e); + } +} + +void IntList::Delete(int e) { + if(first){ + if(first->data == e) { + first = first->link; + } else{ + Node *ptr = first; + while (ptr-> link != NULL && ptr->link->data != e) ptr = ptr->link; + if(ptr->link != NULL) { + if (ptr->link == last) last = ptr; + ptr->link = ptr->link->link; + } + } + } +} diff --git a/Linked List/list.h b/Linked List/list.h new file mode 100644 index 0000000..063069c --- /dev/null +++ b/Linked List/list.h @@ -0,0 +1,21 @@ +using namespace std; +struct Node +{ + Node(int d = 0, Node* l = NULL) : data(d), link(l) { } + int data; + Node * link; +}; + +struct IntList +{ + IntList() { last = first = NULL; } + + void Push_Back(int); // 리스트 뒤에 삽입 중복 허용 + void Push_Front(int); // 리스트 앞에 삽입 중복 허용 + void Insert(int); // 정렬되어 있다는 가정 하에 제 위치에 삽입 + void Delete(int); // 리스트의 원소 삭제 + Node *first; // 첫 노드를 가리킴 + Node *last; // 마지막 노드를 가리킴 +}; + +ostream& operator<< (ostream&, IntList&); diff --git a/Linked List/main.cpp b/Linked List/main.cpp new file mode 100644 index 0000000..84fd849 --- /dev/null +++ b/Linked List/main.cpp @@ -0,0 +1,34 @@ +#include +#include"list.h" +using namespace std; + +int main() { + IntList il; + int input; + + cout<<"==============Input============="<>input; + if(input==-1) break; + il.Insert(input); + cout<>input; + if(input==-1) break; + il.Delete(input); + cout << il; + } + + cout<<"===========Push_Front==========="<>input; il.Push_Front(input); cout<>input; il.Push_Front(input); cout<>input; il.Push_Back(input);cout << il; + cin>>input; il.Push_Back(input);cout << il; + return 0; +} diff --git "a/Permutations \354\213\244\354\240\204 \354\230\210\354\240\234.md" "b/Permutations \354\213\244\354\240\204 \354\230\210\354\240\234.md" new file mode 100644 index 0000000..3d125c1 --- /dev/null +++ "b/Permutations \354\213\244\354\240\204 \354\230\210\354\240\234.md" @@ -0,0 +1,64 @@ +# Permutations 실전 예제 +모든 이진 트리는 **유일한 전위-중위 순서 쌍을 가진다.**
+따라서 전위-중위 순서쌍이 주어진다면 트리를 그릴 수 있다!
+전략은 **서브 트리의 루트를 파악하고, 서브 트리를 계속 그려나가는 것을 계속해서 반복한다!** +1. 전위 순서를 통해 서브 트리의 루트를 확인한다. +2. 중위 순서를 통해 앞서 찾아낸 루트의 왼쪽 서브 트리, 오른쪽 서브 트리를 파악한다. +3. 2번에서 찾아낸 서브트리들의 루트를 전위 순서를 통해 확인한다. +4. 무한 반복.... + +(참고) +- 전위 순열: 이진트리를 전위 순회에 따라 방문한 노드들의 순서 +- 중위 순열: 이진트리를 중위 순회에 따라 방문한 노드들의 순서 + + +## 실전 예제! +주어진 전위 순서와 중위 순서로 원본 트리를 그려보자! +- 전위 순서: A-B-C-D-E-F-G-H-I +- 중위 순서: B-C-A-E-D-G-H-F-I + +1. **전위 순서를 통해 루트가 A임을 파악** +2. **후위 순서에서 A를 찾는다!**
왼편에는 B, C로 구성된 서브 트리! 오른쪽에는 E, D, G, H, F, I로 구성된 서브트리가 있음을 추측할 수 있다. +![1](https://user-images.githubusercontent.com/71186266/205641846-0d014bb0-304a-4082-8059-51422dd22735.png) + +
+ +3. 이후 B-C의 배치를 추측하는데, **전위 순서에서 B가 먼저 나오므로 B가 왼쪽 서브트리의 루트임** + +![2](https://user-images.githubusercontent.com/71186266/205641852-f80c37a3-4b23-483d-b2cc-32228b006374.png) +4. **중위 순서에서 B-C로 발견되므로, 왼쪽을 틀림! 오른쪽과 같이 구성된다는 것을 알 수 있다!** + +![3](https://user-images.githubusercontent.com/71186266/205641854-85309250-07dc-4f66-9011-d7803091fa16.png) +완성된 모습... +

+ +5. **전위 순서를 통해 E-D-G-H-F-I의 루트가 D임을 확인!** +6. 그리고 **중위 순서를 통해 D를 루트로 왼쪽은 E 하나만 있고, 오른쪽은 F-G-H-I가 있음을 추측 가능!** +![4](https://user-images.githubusercontent.com/71186266/205641857-d9d46914-a3a7-484c-a473-85bbf264a5a8.png) + +
+ +7. **전위 순서를 통해 F가 루트임을 확인, 중위 순서를 통해 왼쪽에 G, H 오른 쪽에 I가 옴을 확인** +8. **G-H는 전위 순서를 통해 G가 루트임을 알 수 있었고, 중위 순서를 통해 H는 오른쪽 서브트리에 위치함을 추측 가능하다.** + +![5](https://user-images.githubusercontent.com/71186266/205641861-9f025ad8-a675-438c-be04-9782d17f1911.png) + + +
+ +이렇게 전부 합쳐주면 트리가 완성된다! + +![6](https://user-images.githubusercontent.com/71186266/205641863-e102d1e9-ecea-4733-ab47-79cf2a80f23c.png) + + +## 중위 순열의 갯수 +1. **n개의 노드를 가진 서로 다른 이진트리의 수** +2. **1, 2, ..., n의 전위 순열을 가지는 이진트리로 부터 얻을 수 있는 중위 순열의 수** +3. 1 부터 n까지의 수를 스택에 넣었다가 가능한 모든 방법으로 삭제하여 만들 수 있는 상이한 순열의 수 + + +**노하우는, N개의 노드를 가진 이진 트리가 생길 수 있는 모양꼴을 전부 떠올려 본 다음 숫자를 채워 넣는 것이다. 3개의 경우 5개 정도 된다..** + + +## Reference +- Fundamentals of Data Structures in C++ \ diff --git a/Polynomial/polya.cpp b/Polynomial/polya.cpp new file mode 100644 index 0000000..16651c3 --- /dev/null +++ b/Polynomial/polya.cpp @@ -0,0 +1,92 @@ +#include "polya.h" +#include +using namespace std; + +istream& operator>> (istream& is, Polynomial& p) { + int noofterms; float coef; int exp; + is >> noofterms; + for (int i = 0; i < noofterms; i++) { + is >> coef >> exp; + p.NewTerm(coef, exp); + } + return is; +} + + +ostream& operator<<(ostream& os, Polynomial& p) { + string str; + for(int i = 0; i < p.terms; i++) { + Term termNow = p.termArray[i]; + if (i != 0) { + if(termNow.coef > 0) str += "+"; + else str += "-"; + } + if (termNow.coef != 1 && termNow.coef != -1) str += (abs((int) termNow.coef)) + '0'; + if(i != p.terms - 1) str += "x"; + if (termNow.exp != 1 && termNow.exp != 0) { + str += "^"; + if (termNow.exp < 0) { + str += "(-"; + str += (abs((int) termNow.exp)) + '0'; + str += ")"; + } else { + str += (abs((int) termNow.exp)) + '0'; + } + } + str += " "; + } + return os << str << endl; +} + +Polynomial::Polynomial() :capacity(1), terms(0) { + termArray = new Term[capacity]; +} + +void Polynomial::NewTerm(const float theCoeff, const int theExp) { + if (terms == capacity) { + capacity *= 2; + Term* temp = new Term[capacity]; + copy(termArray, termArray + terms, temp); + delete[] termArray; + termArray = temp; + } + termArray[terms].coef = theCoeff; + termArray[terms++].exp = theExp; +} + +Polynomial Polynomial::operator+(Polynomial& b) { + Polynomial c; + int aPos = 0, bPos = 0; + while ((aPos < terms) && (bPos < b.terms)) { + if (termArray[aPos].exp == b.termArray[bPos].exp) { + float t = termArray[aPos].coef + b.termArray[bPos].coef; + if (t) { + c.NewTerm(t, termArray[aPos].exp); + aPos++; + bPos++; + } + } + else if (termArray[aPos].exp < b.termArray[bPos].exp) { + c.NewTerm(b.termArray[bPos].coef, b.termArray[bPos].exp); + bPos++; + } + else { + c.NewTerm(termArray[aPos].coef, termArray[aPos].exp); + aPos++; + } + } + for (; aPos < terms; aPos++) { + c.NewTerm(termArray[aPos].coef, termArray[aPos].exp); + } + for (; bPos < b.terms; bPos++) { + c.NewTerm(b.termArray[bPos].coef, b.termArray[bPos].exp); + } + return c; +} + +int main() { + Polynomial p1, p2; + cin >> p1 >> p2; + Polynomial p3 = p1 + p2; + cout << p1 << p2 << p3; +} diff --git a/Polynomial/polya.h b/Polynomial/polya.h new file mode 100644 index 0000000..1fbb1ba --- /dev/null +++ b/Polynomial/polya.h @@ -0,0 +1,30 @@ +#ifndef POLYNOMIAL_H +#define POLYNOMIAL_H +#include + +using namespace std; + +class Polynomial; +class Term { + friend class Polynomial; + friend ostream& operator<<(ostream&, Polynomial&); + friend istream& operator>>(istream&, Polynomial&); +private: + float coef; + int exp; +}; + +class Polynomial { +public: + Polynomial(); + Polynomial operator+(Polynomial&); + void NewTerm(const float, const int); + friend ostream& operator<<(ostream&, Polynomial&); + friend istream& operator>>(istream&, Polynomial&); +private: + Term *termArray; + int capacity; + int terms; +}; +#endif + diff --git a/Postfix Traversal/hw5.cpp b/Postfix Traversal/hw5.cpp new file mode 100644 index 0000000..ebaba8f --- /dev/null +++ b/Postfix Traversal/hw5.cpp @@ -0,0 +1,18 @@ +#include +#include +#include +#include "post.h" + +int main(int argc, char *argv[]) { + char line[MAXLEN]; + cout << "[B715152 Jinho Lee hw5 Postfix Result]" << '\n'; + while (cin.getline(line, MAXLEN, '\n')) { + Expression e(line); + try { + Postfix(e); + } + catch (char const *msg) { + cerr << "Exception: " << msg << endl; + } + } +} diff --git a/Postfix Traversal/post.cpp b/Postfix Traversal/post.cpp new file mode 100644 index 0000000..9402125 --- /dev/null +++ b/Postfix Traversal/post.cpp @@ -0,0 +1,186 @@ +#include +#include +#include "post.h" +using namespace std; + +bool Token::operator==(char b) { return len == 1 && str[0] == b; } +bool Token::operator!=(char b) { return len != 1 || str[0] != b; } +Token::Token() {} + +Token::Token(char c) : len(1), type(c) { str = new char[1]; str[0] = c; } // default type = c itself +Token::Token(char c, char c2, int type) : len(2), type(type) { str = new char[2]; str[0] = c; str[1] = c2; } +Token::Token(char* arr, int l, int type = ID) : len(l), type(type){ + str = new char[len + 1]; + for (int i = 0; i < len; i++) str[i] = arr[i]; + str[len] = '\0'; + + if (type == NUM) { + ival = arr[0] - '0'; + for (int i = 1; i < len; i++) ival = ival * 10 + arr[i] - '0'; + } else if (type == ID) ival = 0; + else throw "must be ID or NUM"; +} + +bool Token::IsOperand() { return type == ID || type == NUM; } + + +ostream& operator<<(ostream& os, Token token) { + if (token.type == UMINUS) os << "-u"; + else if (token.type == NUM) os << token.ival; + else for (int i = 0; i < token.len; i++) os << token.str[i]; + os << " "; + return os; +} + +bool GetID(Expression& expression, Token& token) { + char expString[MAXLEN]; int idLen = 0; + char c = expression.str[expression.pos]; + + if (!(c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z')) return false; + expString[idLen++] = c; + expression.pos++; + while ((c = expression.str[expression.pos]) + >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c >= '0' && c <= '9') { + expString[idLen++] = c; + expression.pos++; + } + expString[idLen] = '\0'; + token = Token(expString, idLen, ID); // return an ID + return true; +} + +bool GetInt(Expression& expression, Token& token) { + char expIntString[MAXLEN]; int intLen = 0; + char c = expression.str[expression.pos]; + + if (!('0' <= c && c <= '9')) return false; + expIntString[intLen++] = c; + expression.pos++; + while ('0' <= (c = expression.str[expression.pos]) && c <= '9') { + expIntString[intLen++] = c; + expression.pos++; + } + expIntString[intLen] = '\0'; + token = Token(expIntString, intLen, NUM); + return true; +} + + +void SkipBlanks(Expression& e) { + char c; + while (e.pos < e.len && ((c = e.str[e.pos]) == ' ' || c == '\t')){ + e.pos++; + } +} + +bool TwoCharOp(Expression& expression, Token& token) { + char c = expression.str[expression.pos]; + char c2 = expression.str[expression.pos + 1]; + + int op = -1; // LE GE EQ NE AND OR UMINUS + if(c2 == '=') { + if (c == '<') op = LE; + else if (c == '>') op = GE; + else if (c == '=') op = EQ; + else if (c == '!') op = NE; + } + else if (c == '&' && c2 == '&') op = AND; + else if (c == '|' && c2 == '|') op = OR; + else if (c2 == '-') op = UMINUS; + + if(op == -1) return false; + + token = Token(c, c2, op); expression.pos += 2; + return true; +} + +bool OneCharOp(Expression& e, Token& tok) { + char c = e.str[e.pos]; + if (c == '-' || c == '!' || c == '*' || c == '/' || c == '%' || + c == '+' || c == '<' || c == '>' || c == '(' || c == ')' || c == '=') { + tok = Token(c); + e.pos++; + return true; + } + return false; +} + + +Token NextToken(Expression& expression, bool INFIX = true) { + static bool oprrFound = true; + Token token; + SkipBlanks(expression); // skip blanks if any + if (expression.pos == expression.len) { // No more token left in this expression + if (INFIX) oprrFound = true; + return Token('#'); + } + + if (GetID(expression, token) || GetInt(expression, token)) { + if (INFIX) oprrFound = false; + return token; + } + + if (TwoCharOp(expression, token) || OneCharOp(expression, token)) { + if (token.type == '-' && INFIX && oprrFound) { + token = Token('-', 'u', UMINUS); + } + if (INFIX) oprrFound = true; + return token; + } + throw "Illegal Character Found"; +} + +int icp(Token& t) { // in-coming priority + switch (t.type) { + case '(': return 0; + case '!': case UMINUS: return 1; + case '*': case '/': case '%': return 2; + case '+': case '-': return 3; + case '<': case '>': case LE: case GE: return 4; + case EQ: case NE: return 5; + case AND: return 6; + case OR: return 7; + case '=': return 8; + case '#': return 9; + } + return 0; +} + +int isp(Token& t) { // in-stack priority + int type = t.type; //stack 에서의 우선순위 결정 + switch (t.type) { + case '!': case UMINUS: return 1; + case '*': case '/': case '%': return 2; + case '+': case '-': return 3; + case '<': case '>': case LE: case GE: return 4; + case EQ: case NE: return 5; + case AND: return 6; + case OR: return 7; + case '=': return 8; + case '#': return 9; + case '(': return 10; + } + return 0; +} + +void Postfix(Expression expression) { + stack st; + st.push(Token('#')); + Token tokenNow = NextToken(expression); + while(tokenNow.type != '#') { + if(tokenNow.type == NUM || tokenNow.type == ID) cout << tokenNow; + else if (tokenNow.type == '(') st.push(tokenNow); + else if (tokenNow.type == ')') { + while(st.top().type != '#' && st.top().type != '(') { cout << st.top(); st.pop(); } + st.pop(); + } + else { + int priorityNow = icp(tokenNow); + while (st.top().type != '#' && isp(st.top()) <= priorityNow) { cout << st.top(); st.pop(); } + st.push(tokenNow); + } + tokenNow = NextToken(expression); + } + while (st.top().type != '#') { cout << st.top(); st.pop(); } + cout << '\n'; +} diff --git a/Postfix Traversal/post.h b/Postfix Traversal/post.h new file mode 100644 index 0000000..523788a --- /dev/null +++ b/Postfix Traversal/post.h @@ -0,0 +1,68 @@ + +#ifndef POSTFIX_H +#define POSTFIX_H + +// token types for non one-char tokens +#define ID 257 + +#define NUM 258 + +#define EQ 259 + +#define NE 260 + +#define GE 261 + +#define LE 262 + +#define AND 263 + +#define OR 264 + + +#define UMINUS 265 + +#define MAXLEN 80 +struct Expression { + +Expression(char* s) : str(s), pos(0) + +{ for (len = 0; str[len] != '\0'; len++); } +char* str; + +int pos; +int len; + +}; + +struct Token { + +bool operator==(char); +bool operator!=(char); + +Token(); + +Token(char); // 1-char token: type equals the token itself +Token(char, char, int); // 2-char token(e.g. <=) & its type(e.g.LE) + +Token(char*, int, int); //operand with its length & type(defaulted to ID) +bool IsOperand(); // true if the token type is ID or NUM + +int type; // ascii code for 1-char op; predefined for other tokens +char* str; // token value + +int len; // length of str + +int ival; // used to store an integer for type NUM; init to 0 for ID + +}; + +using namespace std; + +ostream& operator<<(ostream&, Token t); + +Token NextToken(Expression&, bool); // 2nd arg = true for infix expression + +void Postfix(Expression expression); +#endif + diff --git "a/Sorting Algorithm/\353\213\244\354\226\221\355\225\234 sorting algorithms cpp code.cpp" "b/Sorting Algorithm/\353\213\244\354\226\221\355\225\234 sorting algorithms cpp code.cpp" new file mode 100644 index 0000000..d24c98a --- /dev/null +++ "b/Sorting Algorithm/\353\213\244\354\226\221\355\225\234 sorting algorithms cpp code.cpp" @@ -0,0 +1,237 @@ +// +// Created by Jinho on 2023-05-13. +// + +#include +#include +#include +#include +#include +#include +#include + + +#define MAX_ARRAY_NUMBER 100 +using namespace std; + +class SortingAlgorithm { +public: + SortingAlgorithm(int _size) { + size = _size; + } + + void selectionSort(); + void insertionSort(); + void bubbleSort(); + void shellSort(); + void mergeSort(); + void quickSort(); + void radixSort(); + + void printArray(); + +private: + int size; + int *arr; + void generateRandomArray(); + void mergeSort(int start, int end); + void quickSort(int start, int end); +}; + +void SortingAlgorithm::generateRandomArray() { + arr = new int[size]; + for (int i = 0; i < size; i++) { + arr[i] = rand() % MAX_ARRAY_NUMBER; + } + printArray(); +} + +void SortingAlgorithm::selectionSort() { + cout << "============ selectionSort ============\n"; + generateRandomArray(); + + int minNumber, minIdx; + for (int select = 0; select < size; select++) { + minNumber = MAX_ARRAY_NUMBER; + for (int i = select; i < size; i++) { + if (minNumber > arr[i]) { + minNumber = arr[i]; + minIdx = i; + } + } + swap(arr[select], arr[minIdx]); + } + + printArray(); +} + +void SortingAlgorithm::printArray() { + for (int i = 0; i < size; i++) { + cout << arr[i] << " "; + } + cout << "\n\n"; +} + +void SortingAlgorithm::insertionSort() { + cout << "============ insertionSort ============\n"; + generateRandomArray(); + + int j, temp; + for (int i = 1; i < size; i++) { + temp = arr[i]; + for (j = i - 1; j >= 0; j--) { + if (arr[j] > temp) { + arr[j + 1] = arr[j]; + continue; + } + break; + } + arr[j + 1] = temp; + } + + printArray(); +} + +void SortingAlgorithm::bubbleSort() { + cout << "============ bubbleSort ============\n"; + generateRandomArray(); + + for (int i = 0; i < size; i++) { + for (int j = 0; j < size - 1; j++) { + if (arr[j] > arr[j + 1]) { + swap(arr[j], arr[j + 1]); + } + } + } + + printArray(); +} + +void SortingAlgorithm::shellSort() { + cout << "============ shellSort ============\n"; + generateRandomArray(); + + int gap; + for (gap = size / 2; gap > 0; gap /= 2) { + if (gap % 2 == 0) { + gap++; + } + + for (int k = 0; k < gap; k++) { + int j, temp; + for (int i = k + gap; i < size; i += gap) { + temp = arr[i]; + for (j = i - gap; j >= k && temp < arr[j]; j -= gap) { + arr[j + gap] = arr[j]; + } + arr[j + gap] = temp; + } + } + } + + printArray(); +} + +void SortingAlgorithm::mergeSort() { + cout << "============ mergeSort ============\n"; + generateRandomArray(); + + mergeSort(0, size - 1); + + printArray(); +} + +void SortingAlgorithm::mergeSort(int start, int end) { + if (start == end) return; + + int mid = (start + end) / 2; + mergeSort(start, mid); + mergeSort(mid + 1, end); + + int *tempArr = new int[size]; + int i = start, j = mid + 1, k = start; + while (i <= mid && j <= end) { + if (arr[i] < arr[j]) { + tempArr[k++] = arr[i++]; + } else { + tempArr[k++] = arr[j++]; + } + } + + while (i <= mid) { + tempArr[k++] = arr[i++]; + } + while (j <= end) { + tempArr[k++] = arr[j++]; + } + + for (i = start; i <= end; i++) { + arr[i] = tempArr[i]; + } +} + +void SortingAlgorithm::quickSort() { + cout << "============ quickSort ============\n"; + generateRandomArray(); + + quickSort(0, size - 1); + printArray(); +} + +void SortingAlgorithm::quickSort(int start, int end) { + if (start >= end) return; + + int pivotValue = arr[start]; + int pivot = start; + + for (int j = start + 1; j <= end; j++) { + if (arr[j] < pivotValue) { + swap(arr[j], arr[++pivot]); + } + } + swap(arr[start], arr[pivot]); + quickSort(start, pivot - 1); + quickSort(pivot + 1, end); +} + +void SortingAlgorithm::radixSort() { + cout << "============ radixSort ============\n"; + generateRandomArray(); + + int temp = MAX_ARRAY_NUMBER, ten = 0; + while (temp > 0) { + temp /= 10; + ten++; + } + queue que[10]; + + // 자릿수 + for (int idx = 0; idx < ten; idx++) { + for (int j = 0; j < size; j++) { + que[(arr[j] / (int) pow((int) 10, (int) idx)) % 10].push(arr[j]); + } + int newIdx = 0; + for (int j = 0; j < 10; j++) { + while (!que[j].empty()) { + arr[newIdx++] = que[j].front(); + que[j].pop(); + } + } + } + + printArray(); +} + + +int main() { + srand((unsigned int) (time(0))); + + SortingAlgorithm sortingAlgorithm = SortingAlgorithm(10); + sortingAlgorithm.selectionSort(); + sortingAlgorithm.insertionSort(); + sortingAlgorithm.bubbleSort(); + sortingAlgorithm.shellSort(); + sortingAlgorithm.mergeSort(); + sortingAlgorithm.quickSort(); + sortingAlgorithm.radixSort(); +} diff --git a/Subway Problem/hw10.cpp b/Subway Problem/hw10.cpp new file mode 100644 index 0000000..2003635 --- /dev/null +++ b/Subway Problem/hw10.cpp @@ -0,0 +1,38 @@ +#include "subway.h" + +int main(int argc, char *argv[]) +{ + argc = 3; + int numLine, line1, line2, cost; + string src, dst; + + if(argc != 3) { + cerr << "Argument Count is " << argc << endl << "Argument must be " << argc << endl; + return 1; + } + + fstream fin(argv[1]); + if(!fin) { + cerr << argv[1] << " open failed " << endl; + return 1; + } + + fin >> numLine; + while (numLine--) { + fin >> line1 >> src >> line2 >> dst; + setStation(line1, src, line2, dst); + } + fin.close(); + + fstream fin2(argv[2]); + if(!fin2) { + cerr << argv[2] << " open failed" << endl; + return 1; + } + fin2 >> line1 >> src; + fin2 >> line2 >> dst; + fin2.close(); + + initDijkstra(line1, src, line2, dst); + return 0; +} diff --git a/Subway Problem/subway.cpp b/Subway Problem/subway.cpp new file mode 100644 index 0000000..d844ed4 --- /dev/null +++ b/Subway Problem/subway.cpp @@ -0,0 +1,151 @@ +#include "subway.h" + +map stationToIdx; +vector connected[110]; +int costTo[2][110]; +Station idxToStation[110]; +int stationCnt = 0; + +int getAbs(int num) { + return num < 0 ? num*(-1) : num; +} + +string toString(int num) { + int ten = num / 10; + int left = num % 10; + string numStr; + numStr += (char) (ten + '0'); + numStr += (char) (left + '0'); + return numStr; +} + +int getStationIdx(int line, string &src) { + if (stationToIdx.find(src) == stationToIdx.end() || stationToIdx[src].line[line] == -1) { + idxToStation[stationCnt].line = line; + idxToStation[stationCnt].station = src; + idxToStation[stationCnt].prevIdx = -1; + stationToIdx[src].line[line] = stationCnt++; + } + + return stationToIdx[src].line[line]; +} + +void setStation(int line1, string &src, int line2, string &dst) { + int station1 = getStationIdx(line1, src); + int station2 = getStationIdx(line2, dst); + if (line1 != line2) return; + connected[station1].push_back(station2); + connected[station2].push_back(station1); +} + +void Heap::push(Node *node) { + heap.push_back(node); + if (size() == 1) return; + temp = size(); + while (temp != 1 && heap[temp / 2 - 1]->costNow < heap[temp - 1]->costNow) { + swap(heap[temp / 2 - 1], heap[temp - 1]); + temp /= 2; + } +} + +void Heap::pop() { + if (empty()) return; + swap(heap.front(), heap.back()); + heap.pop_back(); + if (empty()) return; + temp = 1; + int child; + + while (temp * 2 < size()) { + child = temp * 2; + if (temp * 2 + 1 < size() && heap[temp * 2]->costNow < heap[temp * 2 + 1]->costNow) child++; + if (heap[child] <= heap[temp]) break; + swap(heap[child], heap[temp]); + temp = child; + } +} + + +void traceStation(int dstIdx) { + stack st; + Station *stationNow; + while (dstIdx != -1) { + stationNow = &idxToStation[dstIdx]; + if (st.empty() || st.top() != stationNow->station) st.push(stationNow->station); + dstIdx = stationNow->prevIdx; + } + while (!st.empty()) { + cerr << st.top() << endl; + st.pop(); + } +} + +void dijkstra(int sourceIdx, int destinationIdx, int step) { + Heap *heapTree = new Heap; + heapTree->push(new Node(sourceIdx, 0, -1)); + + int idxNow; + Station *stationNow; + + while (!heapTree->empty()) { + Node *nodeNow = heapTree->top(); + heapTree->pop(); + idxNow = nodeNow->stationIdx; + + if (costTo[step][idxNow] <= nodeNow->costNow) continue; + costTo[step][idxNow] = nodeNow->costNow; + stationNow = &idxToStation[idxNow]; + stationNow->prevIdx = nodeNow->stationPrev; + + if (idxNow == destinationIdx) continue; + + // �ֱ� + for (int line = 1; line < 10; line++) { + if (stationToIdx[stationNow->station].line[line] == -1) continue; + if (line == stationNow->line) continue; + heapTree->push(new Node(stationToIdx[stationNow->station].line[line], nodeNow->costNow + 30, idxNow)); + } + for (int i = 0; i < connected[idxNow].size(); i++) { + heapTree->push(new Node(connected[idxNow][i], nodeNow->costNow + 60, idxNow)); + } + } +} + +void printTimeNoNewline(int time) { + int second = time % 60; + cerr << time / 60 << ":" << toString(second) << endl; +} + +void getMiddleStation() { + int ans = INF; + int cost[2]; + string stationName; + for (int i = 0; i < stationCnt; i++) { + for (int j = 0; j < stationCnt; j++) { + if (idxToStation[i].station != idxToStation[j].station) continue; + if (ans < getAbs(costTo[0][i] - costTo[1][j])) continue; + ans = getAbs(costTo[0][i] - costTo[1][j]); + cost[0] = costTo[0][i]; + cost[1] = costTo[1][j]; + stationName = idxToStation[i].station; + } + } + cerr << stationName << " //middle point" << endl; + + int first = cost[0] >= cost[1] ? 0 : 1; + printTimeNoNewline(cost[first]); + printTimeNoNewline(cost[1 - first]); +} + +void initDijkstra(int line1, string &src, int line2, string &dst) { + for (int i = 0; i < 2; i++) for (int j = 0; j < 110; j++) costTo[i][j] = INF; + + int sourceIdx = stationToIdx[src].line[line1]; + int destinationIdx = stationToIdx[dst].line[line2]; + dijkstra(sourceIdx, destinationIdx, 0); + traceStation(destinationIdx); + printTimeNoNewline(costTo[0][destinationIdx]); + + dijkstra(destinationIdx, sourceIdx, 1); + getMiddleStation(); +} diff --git a/Subway Problem/subway.h b/Subway Problem/subway.h new file mode 100644 index 0000000..f961588 --- /dev/null +++ b/Subway Problem/subway.h @@ -0,0 +1,53 @@ +// +// Created by Jinho on 11/18/2022. +// + +#ifndef SUBWAY_H +#define SUBWAY_H +#define INF 98765432 + +#include +#include +#include +#include +#include +#include + +using namespace std; + +struct Station { + int line, prevIdx; + string station; + + Station() { line = -1; station = ""; prevIdx = -1;} +}; + +struct idxArrayWrapper { + int line[10]; + idxArrayWrapper() { + for (int i = 0; i < 10; i++) line[i] = -1; + } +}; + +struct Node { + int stationIdx, costNow, stationPrev; + + Node(int stationIdx, int costNow, int stationPrev) + : stationIdx(stationIdx), costNow(costNow), stationPrev(stationPrev) {} +}; + +class Heap { + int temp; +public: + vector heap; + void pop(); + Node* top() { return heap.front(); } + int size() { return heap.size(); } + bool empty() { return heap.empty(); } + void push(Node*); +}; + +void setStation(int line1, string &src, int line2, string &dst); +void initDijkstra(int line1, string& src, int line2, string& dst); + +#endif //SUBWAY_H diff --git a/Tree Traversal/README.md b/Tree Traversal/README.md new file mode 100644 index 0000000..1bf5393 --- /dev/null +++ b/Tree Traversal/README.md @@ -0,0 +1,84 @@ +# 7. Tree Traversal +트리 순회를 처리하는 bt.h 헤더파일을 완성하시오 +## 1. 재귀를 하는 Preorder, Inorder, Postorder 만들기 +```cpp +template +void Tree::Preorder(Node *node_now) { + cout << node_now->data << " "; + if (node_now->leftChild) Preorder(node_now->leftChild); + if (node_now->rightChild) Preorder(node_now->rightChild); +} + +template +void Tree::Inorder(Node *node_now) { + if (node_now->leftChild) Inorder(node_now->leftChild); + cout << node_now->data << " "; + if (node_now->rightChild) Inorder(node_now->rightChild); +} + +template +void Tree::Postorder(Node *node_now) { + if (node_now->leftChild) Postorder(node_now->leftChild); + if (node_now->rightChild) Postorder(node_now->rightChild); + cout << node_now->data << " "; +} +``` + +## 2. 재귀 없이 스택을 이용하여 트리를 순회하는 StackPreorder, StackPostorder, Levelorder 완성하기 +StackPostorder가 은근히 어렵게 느껴졌다.
+왼쪽 노드를 방문한 다음 오른쪽 노드를 방문해야 하는데, +스택에 넣어주다 보니 왼쪽 노드를 방문한 다음 오른쪽 노드를 방문하기 전에 중앙 노드를 방문해버린다.
+제출 시간이 임박하기도 해서 간단하게 자식 노드들을 모두 제거한 버전의 중앙 노드를 다시 넣어줬다.
+이렇게 구현하면 스택의 작동상 "자식 노드가 없는 경우 출력하라"를 통해 왼쪽 자식, 오른쪽 자식, 자기 자신 순서로 방문할 수가 있었다. +```cpp +void StackPreorder() { + init(); + stack*> st; + Node* node_now = root; + while(1) { + while(node_now) { + cout << node_now->data << " "; + st.push(node_now); + node_now = node_now->leftChild; + } + if(st.empty()) break; + node_now = st.top(); + st.pop(); + node_now = node_now->rightChild; + } +} +void StackPostorder() { + init(); + stack*> st; + Node* node_now = root; + while(1) { + while(node_now) { + st.push(node_now); + node_now = node_now->leftChild; + } + if(st.empty()) break; + node_now = st.top(); + st.pop(); + if (node_now->rightChild) { + Node* ptr = new Node(node_now->data); + st.push(ptr); + } else { + cout << node_now->data << " "; + } + node_now = node_now->rightChild; + } +} +void Levelorder() { + init(); + queue*> que; + Node* node_now = root; + que.push(root); + while(!que.empty()) { + node_now = que.front(); + que.pop(); + cout << node_now->data << " "; + if(node_now->leftChild) que.push(node_now->leftChild); + if(node_now->rightChild) que.push(node_now->rightChild); + } +} +``` diff --git a/Tree Traversal/bt.h b/Tree Traversal/bt.h new file mode 100644 index 0000000..e9de303 --- /dev/null +++ b/Tree Traversal/bt.h @@ -0,0 +1,121 @@ +#ifndef TREE_H +#define TREE_H +#include +#include +#include +#include + +using namespace std; + +template struct Node { + Node(T d, Node *left=0, Node *right=0) + : data(d), leftChild(left), rightChild(right) { } + + Node *leftChild; + T data; + Node *rightChild; +}; + +template class Tree { +public: + bool check[100]; + Tree() { root = 0; } // empty tree + void Insert(T &value) { Insert(root, value); } + void Preorder() { Preorder(root); } + void Inorder() { Inorder(root); } + void Postorder() { Postorder(root); } + void init() { memset(check, false, sizeof(check)); } + void StackPreorder() { + init(); + stack*> st; + Node* node_now = root; + while(1) { + while(node_now) { + cout << node_now->data << " "; + st.push(node_now); + node_now = node_now->leftChild; + } + if(st.empty()) break; + node_now = st.top(); + st.pop(); + node_now = node_now->rightChild; + } + } + void StackPostorder() { + init(); + stack*> st; + Node* node_now = root; + while(1) { + while(node_now) { + st.push(node_now); + node_now = node_now->leftChild; + } + if(st.empty()) break; + node_now = st.top(); + st.pop(); + if (node_now->rightChild) { + Node* ptr = new Node(node_now->data); + st.push(ptr); + } else { + cout << node_now->data << " "; + } + node_now = node_now->rightChild; + } + } + void Levelorder() { + init(); + queue*> que; + Node* node_now = root; + que.push(root); + while(!que.empty()) { + node_now = que.front(); + que.pop(); + cout << node_now->data << " "; + if(node_now->leftChild) que.push(node_now->leftChild); + if(node_now->rightChild) que.push(node_now->rightChild); + } + } + +private: + void Visit(Node *); + void Insert(Node* &, T &); + void Preorder(Node *); + void Inorder(Node *); + void Postorder(Node *); + + Node *root; +}; + +template +void Tree::Visit(Node *ptr) { cout << ptr->data << " "; } + +template +void Tree::Insert(Node* &ptr, T &value) { //Insert 의 helper 함수 + if (ptr==0) ptr = new Node(value); + else if (value < ptr->data) Insert(ptr->leftChild, value); + else if (value > ptr->data) Insert(ptr->rightChild, value); + else cout << endl << "Duplicate value " << value << " ignored\n"; +} +template +void Tree::Preorder(Node *node_now) { + cout << node_now->data << " "; + if (node_now->leftChild) Preorder(node_now->leftChild); + if (node_now->rightChild) Preorder(node_now->rightChild); +} + +template +void Tree::Inorder(Node *node_now) { + if (node_now->leftChild) Inorder(node_now->leftChild); + cout << node_now->data << " "; + if (node_now->rightChild) Inorder(node_now->rightChild); +} + +template +void Tree::Postorder(Node *node_now) { + if (node_now->leftChild) Postorder(node_now->leftChild); + if (node_now->rightChild) Postorder(node_now->rightChild); + cout << node_now->data << " "; +} + + +#endif diff --git a/binary tree, heap sort database.cpp b/binary tree, heap sort database.cpp new file mode 100644 index 0000000..3bdc637 --- /dev/null +++ b/binary tree, heap sort database.cpp @@ -0,0 +1,268 @@ +#include +#include + +using namespace std; + +void charPointerCopy(char *ori, char *target) { + while ((*ori++ = *target++) != '\0'); +} + +// 원본이 더 크면 1 작으면 -1 +int compareByName(char *ori, char *target) { + int index = 0; + while (index < 9) { + if (ori[index] == '\0' && target[index] == '\0') { + return 0; + } + + if (ori[index] == '\0') { + return 1; + } + + if (target[index] == '\0') { + return -1; + } + + if (ori[index] > target[index]) { + return 1; + } else if (ori[index] < target[index]) { + return -1; + } + + index++; + } + return 0; +} + +bool equals(char *left, char *right) { + int index = 0; + while (index < 9) { + if (left[index] == '\0' && right[index] == '\0') { + return true; + } else if (left[index] == '\0' || right[index] == '\0') { + return false; + } else if (left[index] != right[index]) { + return false; + } + index++; + } + return false; +} + +class Student { +public: + char name[10]; + int score; + Student *leftChild, *rightChild; + + Student(char *_name, int _score) { + charPointerCopy(name, _name); + score = _score; + leftChild = rightChild = NULL; + } +}; + +class Students { + +public: + Students(Student *student) { + studentSize = 1; + root = student; + generateMockStudent(10); + } + + void insertRecord(char *name, int score); + void listByName(char *name); + + void sortByNameWithInOrder(); + void sortByScoreWithPriorityQueue(); + +private: + int studentSize; + Student *root; + + void generateMockStudent(int studentCount); + void inOrderSearch(Student *studentNow); + void inOrderSearch(Student *studentNow, char *name); + void inOrderSearch(Student *studentNow, int target); + Student *findParentsByName(char *name); + + void pushToPriorityQueue(Student *studentNow); +}; + +Student *Students::findParentsByName(char *name) { + Student *ptr = root; + + int temp; + while (1) { + temp = compareByName(ptr->name, name); + if (temp >= 0 && ptr->leftChild != NULL) { + ptr = ptr->leftChild; + } else if (temp < 0 && ptr->rightChild != NULL) { + ptr = ptr->rightChild; + } else { + return ptr; + } + } +}; + +void Students::insertRecord(char *name, int score) { + + Student *student = new Student(name, score); + Student *ptr = findParentsByName(name); + + if (compareByName(ptr->name, name) >= 0) { + ptr->leftChild = student; + } else { + ptr->rightChild = student; + } + studentSize++; +} + +int idx; +int findIdx; +void Students::inOrderSearch(Student *studentNow, char *name) { + if (studentSize < idx) { + findIdx = -1; + return; + } + + if (studentNow->leftChild) inOrderSearch(studentNow->leftChild, name); + if (compareByName(studentNow->name, name) != 0) { + idx++; + } else { + findIdx = idx; + } + if (studentNow->rightChild) inOrderSearch(studentNow->rightChild, name); + + return; +} + +Student findStudent = Student("", -1); +void Students::inOrderSearch(Student *studentNow, int target) { + if (studentSize < idx) { + return; + } + if (studentNow->leftChild) inOrderSearch(studentNow->leftChild, target); + if (idx == target) { + findStudent = Student(studentNow->name, studentNow->score); + return; + } else { + idx++; + } + if (studentNow->rightChild) inOrderSearch(studentNow->rightChild, target); +} + +void Students::inOrderSearch(Student *studentNow) { + if (studentSize < idx) { + return; + } + + if (studentNow->leftChild != NULL) inOrderSearch(studentNow->leftChild); + cout << "idx : " << idx++ << " -> name : " << studentNow->name << ", score : " << studentNow->score << '\n'; + if (studentNow->rightChild != NULL) inOrderSearch(studentNow->rightChild); +} + +void Students::listByName(char *name) { + idx = 1; + inOrderSearch(root, name); + if (findIdx == -1) { + cout << "no user error\n"; + return; + } + + idx = 1; + inOrderSearch(root, findIdx); + + if (findStudent.score == -1 || !equals(findStudent.name, name)) { + cout << "no user error\n"; + return; + } + + printf("index : %d -> name : %s, score : %d\n", findIdx, findStudent.name, findStudent.score); +} + +void Students::sortByNameWithInOrder() { + idx = 1; + inOrderSearch(root); + return; +} + +auto compare = [](Student s1, Student s2) { return s1.score > s2.score; }; +priority_queue, decltype(compare)> que(compare); + +void Students::pushToPriorityQueue(Student *studentNow) { + if (studentSize < idx) { + return; + } + + if (studentNow->leftChild) pushToPriorityQueue(studentNow->leftChild); + que.push(Student(studentNow->name, studentNow->score)); + idx++; + if (studentNow->rightChild) pushToPriorityQueue(studentNow->rightChild); +} + +void Students::sortByScoreWithPriorityQueue() { + idx = 1; + pushToPriorityQueue(root); + + idx = 1; + while (!que.empty()) { + printf("%d -> name : %s, score : %d\n", idx++, que.top().name, que.top().score); + que.pop(); + } +} + +void Students::generateMockStudent(int studentCount) { + + int randNumTemp, lowerUpperTemp; + char nameTemp[10]; + for (int i = 0; i < studentCount; i++) { + randNumTemp = rand() % 8 + 1; + // 아스키 a ~ z -> 97 ~ 122 + lowerUpperTemp = 97; + for (int j = 0; j < randNumTemp; j++) { + + nameTemp[j] = rand() % 25 + lowerUpperTemp; + } + nameTemp[randNumTemp] = '\0'; + + insertRecord(nameTemp, rand()%100); + } +} + +int main() { + + char command[20]; + int scoreBuffer; + char nameBuffer[20] = "jinho"; + char insert[20] = "insert"; + char list[20] = "list"; + char sortName[20] = "sort1"; + char sortScore[20] = "sort2"; + char print[20] = "print"; + char exit[20] = "exit"; + Students students = Students(new Student(nameBuffer, 100)); + + while (1) { + scanf("%s", &command); + printf("%s\n", command); + if (equals(command, insert)) { + scanf("%s %d", &nameBuffer, &scoreBuffer); + students.insertRecord(nameBuffer, scoreBuffer); + } else if (equals(command, list)) { + scanf("%s", &nameBuffer); + students.listByName(nameBuffer); + } else if (equals(command, sortName)) { + students.sortByNameWithInOrder(); + } else if (equals(command, sortScore)) { + students.sortByScoreWithPriorityQueue(); + } else if (equals(command, print)) { + students.sortByNameWithInOrder(); + } else if (equals(command, exit)) { + break; + } else { + printf("there is no command like that\n"); + } + } +} diff --git a/compare sorting performance/DataStructureHomeWork11.m b/compare sorting performance/DataStructureHomeWork11.m new file mode 100644 index 0000000..63d644a --- /dev/null +++ b/compare sorting performance/DataStructureHomeWork11.m @@ -0,0 +1,69 @@ +X1 = [50, 100, 200, 300, 500, 1000, 3000, 5000, 10000, 30000]; +X2 = [50, 100, 200, 300, 500, 1000, 3000, 5000, 10000, 30000]; +X3 = [50, 100, 200, 300, 500, 1000, 3000, 5000, 10000, 30000]; +X4 = [50, 100, 200, 300, 500, 1000, 3000, 5000, 10000, 30000]; +insertion_d = [0.00000, 0.00000, 0.00000, 0.00000, 0.00001, 0.00001, 0.00005, 0.00005, 0.00009, 0.00028]; +quick_d = [0.00001, 0.00003, 0.00013, 0.00022, 0.00063, 0.00241, 0.02193, 0.06016, 0.24103, 2.17110]; +naturalMerge_d= [0.00000, 0.00000, 0.00000, 0.00000, 0.00001, 0.00001, 0.00002, 0.00004, 0.00008, 0.00024]; +heap_d = [0.00002, 0.00002, 0.00007, 0.00007, 0.00015, 0.00027, 0.00093, 0.00186, 0.00380, 0.01277]; + +figure(1); +xlabel('n') +ylabel('t') +ylim([0, 2.2]); +plot(X1, insertion_d, "-*", X2, quick_d, "-*", X3, naturalMerge_d, "-*", X4, heap_d, "-*"); +text(25000, insertion_d(1, 10), 'insertion'); +text(25000, quick_d(1, 10), 'quick'); +text(25000, naturalMerge_d(1, 10), 'naturalMerge'); +text(25000, heap_d(1, 10), 'heap'); +text(5000, 2, 'decreasing case'); + + +insertion_p = [0.00001, 0.00003, 0.00014, 0.00029, 0.00078, 0.00313, 0.02867, 0.08021, 0.32357, 2.92061]; +quick_p = [0.00001, 0.00003, 0.00011, 0.00023, 0.00063, 0.00247, 0.02235, 0.06025, 0.24156, 2.17806]; +naturalMerge_p= [0.00000, 0.00000, 0.00000, 0.00000, 0.00001, 0.00001, 0.00007, 0.00004, 0.00021, 0.00044]; +heap_p = [0.00001, 0.00002, 0.00003, 0.00005, 0.00010, 0.00021, 0.00070, 0.00107, 0.00245, 0.00831]; + + +figure(2); +xlabel('n') +ylabel('t') +ylim([0, 3]); +plot(X1, insertion_p, "-*", X2, quick_p, "-*", X3, naturalMerge_p, "-*", X4, heap_p, "-*"); +text(25000, insertion_p(1, 10), 'insertion'); +text(25000, quick_p(1, 10), 'quick'); +text(25000, naturalMerge_p(1, 10), 'naturalMerge'); +text(25000, heap_p(1, 10), 'heap'); +text(5000, 2.5, 'partially sorted case'); + +insertion_r = [0.00001, 0.00002, 0.00010, 0.00022, 0.00057, 0.00184, 0.01964, 0.04525, 0.25879, 2.87219]; +quick_r = [0.00001, 0.00003, 0.00010, 0.00023, 0.00061, 0.00225, 0.02125, 0.05862, 0.23631, 2.15285]; +naturalMerge_r= [0.00000, 0.00000, 0.00000, 0.00000, 0.00001, 0.00001, 0.00003, 0.00004, 0.00008, 0.00024]; +heap_r = [0.00001, 0.00002, 0.00004, 0.00006, 0.00011, 0.00028, 0.00081, 0.00172, 0.00278, 0.00886]; + +figure(3); +xlabel('n') +ylabel('t') +ylim([0, 3]); +plot(X1, insertion_r, "-*", X2, quick_r, "-*", X3, naturalMerge_r, "-*", X4, heap_r, "-*"); +text(25000, insertion_r(1, 10), 'insertion'); +text(25000, quick_r(1, 10), 'quick'); +text(25000, naturalMerge_r(1, 10), 'naturalMerge'); +text(25000, heap_r(1, 10), 'heap'); +text(5000, 2.5, 'random case'); + +insertion_s = [0.00001, 0.00003, 0.00017, 0.00029, 0.00077, 0.00326, 0.03082, 0.08536, 0.33903, 2.93344]; +quick_s = [0.00001, 0.00003, 0.00011, 0.00023, 0.00071, 0.00249, 0.02180, 0.06035, 0.24118, 2.17860]; +naturalMerge_s= [0.00000, 0.00000, 0.00000, 0.00000, 0.00001, 0.00001, 0.00002, 0.00004, 0.00008, 0.00032]; +heap_s = [0.00001, 0.00002, 0.00003, 0.00005, 0.00014, 0.00021, 0.00063, 0.00104, 0.00258, 0.00846]; + +figure(4); +xlabel('n') +ylabel('t') +ylim([0, 3]); +plot(X1, insertion_s, "-*", X2, quick_s, "-*", X3, naturalMerge_s, "-*", X4, heap_s, "-*"); +text(25000, insertion_s(1, 10), 'insertion'); +text(25000, quick_s(1, 10), 'quick'); +text(25000, naturalMerge_s(1, 10), 'naturalMerge'); +text(25000, heap_s(1, 10), 'heap'); +text(5000, 2.5, 'sorted case'); diff --git a/compare sorting performance/hw11.cpp b/compare sorting performance/hw11.cpp new file mode 100644 index 0000000..e453e92 --- /dev/null +++ b/compare sorting performance/hw11.cpp @@ -0,0 +1,51 @@ +#include +#include +#include +#include +#include "sort.h" + +using namespace std; +int* getArray(char *file); + +struct timeval start_t, end_t; +int N, i; +using namespace std; + +int main(int argc, char *argv[]) +{ + int T = atoi (argv[1]); + cout << "T=" << T << endl; + double result[4], diff_t; + + if (argc < 3) { + cerr << "worng argument count" << endl; + return 1; + } + + int *arr[4], temp, *arrForMerge; + cout << "--INS--|--QUICK--|--NATIMG--|--HEAP--|" << endl; + for (i = 2; i < T + 2; i++) { + arr[0] = arr[1] = arr[2] = arr[3] = getArray(argv[i]); + result[0] = insertionSort(arr[0], N, start_t, end_t); + result[1] = quickSort(arr[1], 0, N-1, start_t, end_t); + result[2] = mergeSort(arr[2], N, start_t, end_t); + result[3] = heapSort(arr[1], N, start_t, end_t); + + cout.precision(5); + cout << fixed; + + for (int j = 0; j < 4; j++) { + cout << result[j] << "|"; + } + cout << "N=" << N << endl; + } +} + +int* getArray(char *file) { + fstream fin(file); + fin >> N; + int *arr = new int[N]; + for(int j=0; j< N; j++) fin >> arr[j]; + fin.close(); + return arr; +} diff --git a/compare sorting performance/sort.h b/compare sorting performance/sort.h new file mode 100644 index 0000000..74044bb --- /dev/null +++ b/compare sorting performance/sort.h @@ -0,0 +1,193 @@ +// +// Created by Jinho on 12/2/2022. +// + +#ifndef ALGORITHEM_SORT_H +#define ALGORITHEM_SORT_H +#define MAXNODE 100001 +#include + +using namespace std; + +double getResult(struct timeval start_t, struct timeval end_t) { + return (double)(end_t.tv_sec-start_t.tv_sec)+ ((double)(end_t.tv_usec-start_t.tv_usec)/1000000); +} + +void insertionSort(int *arr, int N) { + int value; + for(int i = 1; i < N ; i++){ + value = arr[i]; + for(int j = i - 1 ; j >= 0 ; j--){ + if(arr[j] <= value){ + arr[j+1] = arr[j]; + continue; + } + arr[j+1] = value; + break; + } + } +} + +double insertionSort(int *arr, int N, struct timeval start_t, struct timeval end_t) { + gettimeofday(&start_t, NULL); + insertionSort(arr, N); + gettimeofday(&end_t, NULL); + return getResult(start_t, end_t); +} + +void quickSort(int *arr, int start, int end) { + if(start >= end) return; + + int pivot = start; + int i = pivot+1; + int j = end; + + while(i<=j){ + while(i <= end && arr[i]<=arr[pivot]) ++i; + while(j>start && arr[j]>arr[pivot]) --j; + + if(i>=j) break; + + if(i != j) swap(arr[i], arr[j]); + } + + if(pivot != j) swap(arr[pivot], arr[j]); + + quickSort(arr, start, j-1); + quickSort(arr, j+1, end); +} + +double quickSort(int *arr, int start, int end, struct timeval start_t, struct timeval end_t) { + gettimeofday(&start_t, NULL); + quickSort(arr, start, end); + gettimeofday(&end_t, NULL); + return getResult(start_t, end_t); +} + +void mergeSort(int *num, int size) { + int left[size], right[size], leftSize = 0, rightSize = 0; + int cur = num[0], p = 0; + for (int i = 0; i < size; i++) { + if (num[i] < cur) p ^= 1; + if (p == 0) { + left[leftSize++] = cur = num[i]; + continue; + } + right[rightSize++] = cur = num[i]; + } + + if (rightSize == 0) return; + mergeSort(left, leftSize); + mergeSort(right, rightSize); + + int leftIdx = 0, rightIdx = 0, arrayIdx = 0; + while (leftIdx < leftSize && rightIdx < rightSize) { + if (left[leftIdx] < right[rightIdx]) num[arrayIdx++] = left[leftIdx++]; + else num[arrayIdx++] = right[rightIdx++]; + } + while (leftIdx < leftSize) num[arrayIdx++] = left[leftIdx++]; + while (leftIdx < leftSize) num[arrayIdx++] = left[leftIdx++]; +} + +double mergeSort(int *num, int size, struct timeval start_t, struct timeval end_t) { + gettimeofday(&start_t, NULL); + mergeSort(num, size); + gettimeofday(&end_t, NULL); + return getResult(start_t, end_t); +} + +struct Node { + int data; + Node *parent, *child[2]; +}; + +struct Heap { + Node *root; + int size; + + void init(); + Node* get_node(int data); + Node* find_node(int idx); + void push(int data); + void pop(); + bool empty() { return size == 0; } + int top() { return root->data; } +} heap; + +void Heap::init() { + root = NULL; + size = 0; +} + +Node* Heap::get_node(int data) { + Node *node = new Node; + node->data = data; + node->parent = node->child[0] = node->child[1] = NULL; + return node; +} + +Node* Heap::find_node(int idx) { + if(idx > size) return NULL; + if(idx == 1) return root; + return find_node(idx >> 1)->child[idx & 1]; +} + +void Heap::push(int data) { + if (size >= MAXNODE) return; + + Node *node = get_node(data); + size++; + + if (size == 1) { + root = node; + return; + } + Node *parent = find_node(size >> 1); + parent->child[size & 1] = node; + node->parent = parent; + while (node != root && node->parent->data < node->data) { + int temp = node->parent->data; + node->parent->data = node->data; + node->data = temp; + + node = node->parent; + } +} + +void Heap::pop() { + if(size <= 1) { + size = 0; + return; + } + + Node *node = find_node(size); + root->data = node->data; + node->parent->child[size & 1] = NULL; + size--; + node = root; + + while(node->child[0] != NULL) { + Node *child; + if(node->child[1] == NULL) child = node->child[0]; + else child = node->child[0]->data < node->child[1]->data ? node->child[1] : node->child[0]; + + if(child->data < node->data) break; + int temp = child->data; + child->data = node->data; + node->data = temp; + + node = child; + } +} + +double heapSort(int *arr, int N, struct timeval start_t, struct timeval end_t) { + heap.init(); + gettimeofday(&start_t, NULL); + for (int i = 0; i < N; i++) heap.push(arr[i]); + while (!heap.empty()) { heap.pop(); } + for (int i = N - 1; i >= 0 && !heap.empty(); i--, heap.pop()) arr[i] = heap.top(); + gettimeofday(&end_t, NULL); + return getResult(start_t, end_t); +} + +#endif //ALGORITHEM_SORT_H diff --git a/infixToPostfix, postfixCalculator, dfs.cpp b/infixToPostfix, postfixCalculator, dfs.cpp new file mode 100644 index 0000000..f587269 --- /dev/null +++ b/infixToPostfix, postfixCalculator, dfs.cpp @@ -0,0 +1,388 @@ +#include +#include +#include + +#define DIV 6 +//#define TEST_MATLAB +//#define TEST_MAZE_GEN +#define TEST_MAZE_OUT + +using namespace std; +int maze[6][6] = { + {0, 0, 0, 0, 0, 0}, + {1, 1, 1, 1, 1, 0}, + {0, 1, 0, 1, 0, 0}, + {0, 0, 0, 1, 1, 1}, + {0, 0, 0, 1, 0, 0}, + {0, 0, 0, 0, 0, 0}, +}; +int dy[DIV] = {0, 0, -1, 1, 0}; +int dx[DIV] = {1, -1, 0, 0, 0}; + +#ifdef TEST_MATLAB +bool equals(char *left, char *right) { + int index = 0; + while (index < 9) { + if (left[index] == '\0' && right[index] == '\0') { + return true; + } else if (left[index] == '\0' || right[index] == '\0') { + return false; + } else if (left[index] != right[index]) { + return false; + } + index++; + } + return false; +} + +bool contains(char *ori, char target) { + for (int i = 0; i < strlen(ori); i++) { + if (ori[i] == '\0') { + return false; + } + + if (ori[i] == target) { + return true; + } + } + return false; +} + +int prec(char operation) { + switch (operation) { + case '(' : case ')': return 0; + case '^' : return 1; + case '+' : case '-': return 2; + case '*' : case '/': return 3; + } + return -1; +} + +char *convertInfixToPostfix(char exp[]) { + stack st; + char chNow, *ret; + int expLength = strlen(exp); + + int idx = 0; + ret = (char *)malloc(sizeof(char) * expLength); + printf("- infix to postfix result : "); + + for (int i = 0; i < expLength; i++) { + chNow = exp[i]; + switch (chNow) { + case ' ': + break; + case '(': + st.push(chNow); + break; + case ')': + while (!st.empty() && st.top() != '(') { + printf("%c", st.top()); + ret[idx++] = st.top(); + st.pop(); + } + + if (st.empty()) { + printf("error! wrong exp\n", st.top()); + break; + } + + st.pop(); + + break; + case '+': case '-': case '*': case '/': case '^': + while (!st.empty() && prec(chNow) <= prec(st.top())) { + printf("%c", st.top()); + ret[idx++] = st.top(); + st.pop(); + } + st.push(chNow); + break; + default: + printf("%c", chNow); + ret[idx++] = chNow; + break; + } + } + + while (!st.empty()) { + printf("%c", st.top()); + ret[idx++] = st.top(); + st.pop(); + } + + printf("\n"); + ret[idx] = '\0'; + return ret; +} + +int calculatePostfix(char exp[]) { + int temp, idx = 0, expLength = strlen(exp); + stack st; + while (idx < expLength) { + // 숫자인 경우 48 ~ 57 + if (48 <= exp[idx] && exp[idx] <= 57) { + st.push(exp[idx++] - '0'); + continue; + } + + // 연산자인 경우 + int num1, num2; + num1 = st.top(); + st.pop(); + num2 = st.top(); + st.pop(); + + switch (exp[idx++]) { + case '+': st.push(num2 + num1); break; + case '-': st.push(num2 - num1); break; + case '*': st.push(num2 * num1); break; + case '/': st.push(num2 / num1); break; + // 제곱의 경우 + default: + temp = 1; + for (int i = 0; i < num1; i++) { + temp *= num2; + } + st.push(temp); + } + } + return st.top(); +} + +int calculateExp(char exp[]) { + char *postfixExp = convertInfixToPostfix(exp); + return calculatePostfix(postfixExp); +} + +void getArray(char exp[]) { + int idx = 0, expLength = strlen(exp); + while (idx < expLength && exp[idx] != '[') { + idx++; + } + + stack st; + while (exp[idx] != ';') { + + if (48 <= exp[idx] && exp[idx] <= 57) { + st.push(exp[idx++] - '0'); + continue; + } + idx++; + } + + int arrayLength = st.size(); + int arr[2][arrayLength]; + + while (!st.empty()) { + arr[0][st.size() - 1] = st.top(); + st.pop(); + } + + idx++; + int idx2 = 0; + while (idx < expLength && exp[idx] != ']') { + if (48 <= exp[idx] && exp[idx] <= 57) { + arr[1][idx2++] = exp[idx++] - '0'; + continue; + } + idx++; + } + + // 3가지 연산 구현 + printf("array parse done\n"); + for (int i = 0; i < 2; i++) { + for (int j = 0; j < arrayLength; j++) { + printf("%d ", arr[i][j]); + } + printf("\n"); + } + printf("\n"); + + printf("moack Array 1 for plus minus\n"); + int mockArray[2][arrayLength]; + for (int i = 0; i < 2; i++) { + for (int j = 0; j < arrayLength; j++) { + mockArray[i][j] = rand() % 10; + printf("%d ", mockArray[i][j]); + } + printf("\n"); + } + printf("\n"); + + // 더하기 + printf("===array plus===\n"); + for (int i = 0; i < 2; i++) { + for (int j = 0; j < arrayLength; j++) { + printf("%d ", arr[i][j] + mockArray[i][j]); + } + printf("\n"); + } + printf("\n"); + + // 뺴기 + printf("===array minus===\n"); + for (int i = 0; i < 2; i++) { + for (int j = 0; j < arrayLength; j++) { + printf("%d ", arr[i][j] - mockArray[i][j]); + } + printf("\n"); + } + printf("\n"); + + // 곱하기 + printf("moack Array 2 for multiply\n"); + int mockArray2[arrayLength][2]; + for (int i = 0; i < arrayLength; i++) { + for (int j = 0; j < 2; j++) { + mockArray2[i][j] = rand() % 10; + printf("%d ", mockArray2[i][j]); + } + printf("\n"); + } + printf("\n"); + + printf("===array multiply===\n"); + int temp; + for (int i = 0; i < 2; i++) { + for (int j = 0; j < 2; j++) { + temp = 0; + for (int k = 0; k < arrayLength; k++) { + temp += (arr[i][k] * mockArray2[k][j]); + } + printf("%d ", temp); + } + printf("\n"); + } + printf("\n"); +} + +void go () { + char command[100]; + while (1) { + printf("command :"); + gets(command); + + if (equals(command, "end")) { + break; + } + + if (equals(command, "script")) { + // 미구현 + continue; + } + + // 배열의 경우 + if (contains(command, '[')) { + getArray(command); + continue; + } + + // 수식인 경우 + printf("- calculate result : %d\n", calculateExp(command)); + } +} +#endif + +#ifdef TEST_MAZE_GEN + +bool stop; +int saveY = 1, saveX = 0; + +bool makeMaze(int y, int x) { + if (stop || (y == 3 && x == 5)) { + return stop = true; + } + + int idx; + while (1) { + idx = rand() % DIV; + if (idx >= 4) return false; + if (0 > y + dy[idx] || y + dy[idx] > 5) return false; + if (0 > x + dx[idx] || x + dx[idx] > 5) return false; + break; + } + saveY = y + dy[idx]; + saveX = x + dx[idx]; + maze[saveY][saveX] = 1; + return makeMaze(saveY, saveX); +} + +void go() { + memset(maze, 0, sizeof(maze)); + saveY = 1, saveX = 0; + maze[saveY][saveX] = 1; + stop = false; + while (!makeMaze(saveY, saveX)) { + stop = false; + } + + for (int i = 0; i < 6; i++) { + for (int j = 0; j < 6; j++) { + printf("%d ", maze[i][j]); + } + printf("\n"); + } +} +#endif + +#ifdef TEST_MAZE_OUT +bool check[6][6]; +pair from[6][6]; +void go() { + // 현재 좌표, 이전 좌표 + stack, pair>> st; + st.push({{1, 0}, {-1, -1}}); + check[0][0] = true; + while (!st.empty()) { + pair, pair> top = st.top(); + st.pop(); + int yNow = top.first.first; + int xNow = top.first.second; + check[yNow][xNow] = true; + from[yNow][xNow] = {top.second.first, top.second.second}; + + if (yNow == 3 && xNow == 5) { + break; + } + + for (int i = 0; i < 4; i++) { + int nextY = yNow + dy[i]; + int nextX = xNow + dx[i]; + + if (0 > nextY || nextY > 5) continue; + if (0 > nextX || nextX > 5) continue; + if (check[nextY][nextX] || maze[nextY][nextX] == 0) continue; + + st.push({{nextY, nextX}, {yNow, xNow}}); + } + } + + int y = 3, x = 5; + stack> trace; + while (y != -1 && x != -1) { + trace.push({y, x}); + tie(y, x) = from[y][x]; + } + + int idx = 0; + while (!trace.empty()) { + if (idx++ % 5 != 0) { + printf(" -> "); + } + + trace.top(); + printf("{%d, %d}", trace.top().first, trace.top().second); + trace.pop(); + + if (idx % 5 == 0) { + printf("\n"); + } + } +} +#endif + +int main() { + srand((unsigned int)time(NULL)); + go(); +} diff --git a/linked list, stack, queue, bst, graph.cpp b/linked list, stack, queue, bst, graph.cpp new file mode 100644 index 0000000..e157e28 --- /dev/null +++ b/linked list, stack, queue, bst, graph.cpp @@ -0,0 +1,276 @@ +#include +#include +#include +#include +#include + +#define NODE_SIZE 100 +using namespace std; + +struct Node { + int val = -1; + Node *next; +} nodePool[NODE_SIZE]; + +struct List { +private: + Node head = Node(); + int nodeCnt = 0; + +public: + int get(int _idx) { + Node *ptr = &head; + int idx = _idx; + while(ptr->next && idx >= 0) { + ptr = ptr->next; + idx--; + } + + if (idx > -1) { + cout << "list is smaller than " << _idx << '\n'; + return -1; + } else { + return ptr->val; + } + } + + void push(int val) { + Node *ptr = &head; + while(ptr->next) { + ptr = ptr->next; + } + nodePool[nodeCnt].val = val; + ptr->next = &nodePool[nodeCnt++]; + } + + void print() { + if (!head.next) { + cout << "null list\n"; + return; + } + Node *ptr = &head; + while(ptr->next) { + ptr = ptr->next; + cout << ptr->val << " "; + } + cout << '\n'; + } +} list; + +void listTest() { + + cout << "================ list example ================\n"; + list.print(); + + int temp; + for (int i = 0; i < 10; i++) { + temp = rand() % 100 + 1; + cout << "list push number : " << temp << '\n'; + list.push(temp); + } + cout << "----------------------------------------------\n"; + for (int i = 0; i < 10; i++) { + temp = rand() % 10; + cout << "list get " << temp <<" node : " << list.get(temp) << '\n'; + } + + cout << "====== list print all ======\n"; + list.print(); + cout << "================ END ================\n\n\n"; +} + +void stackTest() { + stack st; + cout << "================ stack example ================\n"; + int temp; + for (int i = 0; i < 10; i++) { + temp = rand() % 100 + 1; + cout << "stack push number : " << temp << '\n'; + st.push(temp); + } + cout << "----------------------------------------------\n"; + while (!st.empty()) { + cout << "stack pop number : " << st.top() << '\n'; + st.pop(); + } + cout << "================ END ================\n\n\n"; +} + +void queueTest() { + queue que; + cout << "================ queue example ================\n"; + int temp; + for (int i = 0; i < 10; i++) { + temp = rand() % 100 + 1; + cout << "queue push number : " << temp << '\n'; + que.push(temp); + } + cout << "----------------------------------------------\n"; + while (!que.empty()) { + cout << "queue pop number : " << que.front() << '\n'; + que.pop(); + } + cout << "================ END ================\n\n\n"; +} + +void priorityQueueTest() { + priority_queue que; + cout << "================ priority queue example ================\n"; + int temp; + for (int i = 0; i < 10; i++) { + temp = rand() % 100 + 1; + cout << "priority queue push number : " << temp << '\n'; + que.push(temp); + } + cout << "----------------------------------------------\n"; + while (!que.empty()) { + cout << "priority queue pop number : " << que.top() << '\n'; + que.pop(); + } + cout << "================ END ================\n\n\n"; +} + +struct TreeNode { + int val = -1; + TreeNode *left = nullptr, *right = nullptr; +} treeNodePool[100]; + +struct BST { +private: + TreeNode root = TreeNode(); + int size = 0, idx; + int treeNodeCnt = 0; + + void search(TreeNode *node) { + if (size < idx) { + return; + } + + if (node->left != nullptr) search(node->left); + +// if (node->val != -1) { + cout << "idx : " << idx++ << ", val : " << node->val << '\n'; +// } + + if (node->right != nullptr) search(node->right); + } + +public: + void push(int val) { + size++; + TreeNode *ptr = &root; + while (1) { + if (ptr->val > val) { + if (ptr->left) { + ptr = ptr->left; + } else { + treeNodePool[treeNodeCnt].val = val; + ptr->left = &treeNodePool[treeNodeCnt++]; + return; + } + } else { + if (ptr->right) { + ptr = ptr->right; + } else { + treeNodePool[treeNodeCnt].val = val; + ptr->right = &treeNodePool[treeNodeCnt++]; + return; + } + } + } + } + + void search() { + idx = 0; + if (root.right) { + search(root.right); + return; + } + cout << "null search tree\n"; + } +} bst; + +void binarySearchTreeExample() { + cout << "================ binary search tree example ================\n"; + bst.search(); + int temp; + for (int i = 0; i < 10; i++) { + temp = rand() % 100 + 1; + cout << "binary search tree push number : " << temp << '\n'; + bst.push(temp); + } + cout << "====== binary search tree inorder search! ======\n"; + bst.search(); + cout << "================ END ================\n\n\n"; +} + +int board[5][5] = { + {0, 1, 0,0,0}, + {0, 1, 0,1,0}, + {0, 1, 0,1,0}, + {0, 1, 0,1,0}, + {0, 0, 0,1,0}, +}; +int dy[4] = {1, -1, 0, 0}; +int dx[4] = {0, 0, 1, -1}; + +void graphExample() { + cout << "================ graph example - bfs maze ================\n"; + cout << "======== MAZE ========\n"; + + for (int i = 0; i < 5; i++) { + for (int j = 0; j < 5; j++) { + cout << board[i][j] << " "; + } + cout << '\n'; + } + + bool check[5][5]; + memset(check, false, sizeof (check)); + queue, int>> que; + + pair start = {0, 0}; + pair end = {4, 4}; + + que.push({start, 0}); + check[start.first][start.second] = true; + + pair nodeNow, nextNode; + int distNow; + while (!que.empty()) { + nodeNow = que.front().first; + distNow = que.front().second; + que.pop(); + + if (nextNode.first == end.first && nextNode.second == end.second) { + cout << "arrived! " << end.first << ", " << end.second << " -> dist : " << distNow << '\n'; + cout << "================ END ================\n"; + return; + } + + for (int i = 0; i < 4; i++) { + nextNode.first = nodeNow.first + dy[i]; + nextNode.second = nodeNow.second + dx[i]; + + if (0 > nextNode.first || nextNode.first >= 5 + || 0 > nextNode.second || nextNode.second >= 5) continue; + if (check[nextNode.first][nextNode.second]) continue; + cout << nodeNow.first << ", " << nodeNow.second << ", dist : " << distNow << " -> " << distNow + 1 << '\n'; + check[nextNode.first][nextNode.second] = true; + que.push({nextNode, distNow + 1}); + } + } + + cout << "can't reach to destination!\n"; + cout << "================ END ================\n"; +} + +int main() { + srand((unsigned int) (time(0))); + listTest(); + stackTest(); + queueTest(); + priorityQueueTest(); + binarySearchTreeExample(); + graphExample(); +} diff --git a/mini database - hashTable ver.cpp b/mini database - hashTable ver.cpp new file mode 100644 index 0000000..8730d25 --- /dev/null +++ b/mini database - hashTable ver.cpp @@ -0,0 +1,189 @@ +// +// Created by Jinho on 2023-05-13. +// + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define INIT_STUDENT_NUM 10 +#define BUCKET_COUNT 1 << 10 +#define DIV (BUCKET_COUNT - 1) +#define MAX_ARRAY_NUMBER 100 +using namespace std; + +class Student { +public: + string name; + int score; + Student *next; + Student() { + name = "head"; + score = -1; + next = nullptr; + } + + Student(string _name, int _score) { + name = _name; + score = _score; + next = nullptr; + } +}; + +class Students { +public: + Students() { + initBucket(); + } + + void insertRecord(string &name, int score); + void deleteByName(string &name); + void listByName(string &name); + void printStudentsInfo(); + +private: + int studentSize; + Student hashTable[BUCKET_COUNT]; + + void generateMockStudent(int studentCount); + Student *findPrevStudent(string &name); + int getKey(string &name); + void initBucket(); +}; + +void Students::initBucket() { + studentSize = 0; + for (int i = 0; i < BUCKET_COUNT; i++) { + hashTable[i].next = nullptr; + } + generateMockStudent(INIT_STUDENT_NUM); +} + +void Students::insertRecord(string &name, int score) { + Student *newStudent = new Student(name, score); + int key = getKey(name); + Student *ptr = &hashTable[key]; + while (ptr->next) { + ptr = ptr->next; + } + ptr->next = newStudent; + studentSize++; +} + +void Students::deleteByName(string &name) { + Student *ptr = findPrevStudent(name); + if (ptr->next == nullptr) { + cout << "there is no user name '" << name << "'\n"; + return; + } + + cout << "delete user name : " << ptr->next->name << ", score : " << ptr->next->score << '\n'; + ptr->next = ptr->next->next; + studentSize--; +} + +void Students::listByName(string &name) { + Student* ptr; + ptr = findPrevStudent(name); + if (ptr->next == nullptr) { + cout << "there is no user name '" << name << "'\n"; + return; + } + + cout << "find user name : " << ptr->next->name << ", score : " << ptr->next->score << '\n'; +} + +void Students::generateMockStudent(int studentCount) { + + int randNumTemp; + string nameTemp; + for (int i = 0; i < studentCount; i++) { + randNumTemp = rand() % 8 + 1; + nameTemp = ""; + // 아스키 97 ~ 122 + for (int j = 0; j < randNumTemp; j++) { + nameTemp += rand() % 25 + 97; + } + insertRecord(nameTemp, rand() % 100); + } +} + +void Students::printStudentsInfo() { + + cout << "============ student count is " << studentSize << "]! print student info ============" << '\n'; + Student *ptr; + int cnt = 1; + for (int i = 0; i < BUCKET_COUNT; i++) { + if (!hashTable[i].next) continue; + ptr = hashTable[i].next; + while (ptr) { + cout << cnt++ << ". name : " << ptr->name << ", score : " << ptr->score << '\n'; + ptr = ptr->next; + } + } +} + +int Students::getKey(string &name) { + long long key = 5381; + for (char ch : name) { + key = ((key * 26) + key) + ch - 'a' + 1; + } + return (int) (key & DIV); +} + +Student *Students::findPrevStudent(string &name) { + int key = getKey(name); + Student *ptr = &hashTable[key]; + while (ptr->next) { + if (ptr->next->name == name) { + return ptr; + } + ptr = ptr->next; + } + return ptr; +} + +int main() { + srand((unsigned int) (time(0))); + string command; + int scoreBuffer; + string nameBuffer; + + string insert = "insert"; + string listName = "listName"; + string deleteByName = "delete"; + string print = "print"; + string exit = "exit"; + Students students = Students(); + + while (1) { + command = ""; + cin >> command; + cout << command << '\n'; + if (command == insert) { + cin >> nameBuffer >> scoreBuffer; + students.insertRecord(nameBuffer, scoreBuffer); + } else if (command == listName) { + cin >> nameBuffer; + students.listByName(nameBuffer); + } else if (command == deleteByName) { + cin >> nameBuffer; + students.deleteByName(nameBuffer); + } else if (command == print) { + students.printStudentsInfo(); + } else if (command == exit) { + break; + } else { + printf("there is no command like that\n"); + } + } +} diff --git a/mini database.cpp b/mini database.cpp new file mode 100644 index 0000000..f13327f --- /dev/null +++ b/mini database.cpp @@ -0,0 +1,353 @@ +#include +#include +#include + +#define INIT_STUDENT_NUM 10 +#define FILE_NAME_STRING "hw1db.txt" + +using namespace std; + +void charPointerCopy(char *ori, char *target) { + while ((*ori++ = *target++) != '\0'); +} + + +bool compareToName(char *left, char *right) { + int index = 0; + while (index < 8) { + if (left[index] == '\0') { + return true; + } + + if (right[index] == '\0') { + return false; + } + + if (left[index] > right[index]) { + return true; + } else if (left[index] < right[index]) { + return false; + } + + index++; + } + + return false; +} + +bool equals(char *left, char *right) { + int index = 0; + while (index < 9) { + if (left[index] == '\0' && right[index] == '\0') { + return true; + } else if (left[index] == '\0' || right[index] == '\0') { + return false; + } else if (left[index] != right[index]) { + return false; + } + index++; + } + return false; +} + +struct Student { + int num; + char name[10]; + int score; +}; + +class Students { + +public: + Students() { + studentSize = INIT_STUDENT_NUM; + maxSize = 2 * INIT_STUDENT_NUM; + students = (Student *) malloc(maxSize * sizeof(Student)); + generateMockStudent(studentSize); + } + + void insertRecord(int index, char *name, int score); + void deleteByName(char *name); + void listByName(char *name); + + void sortByName(); + void sortByScore(); + + void readDB(char name[]); + void writeDB(char name[]); + + void printStudentsInfo(); + +private: + int maxSize; + int studentSize; + Student *students; + + void validateFileNotNull(FILE *file); + void generateMockStudent(int studentCount); + void resizeArrayDouble(); + int getRecordIndexByNameMatchFirst(char *name); + Student parseStudentInfo(char *studentInfoString, int index); +}; + +void Students::resizeArrayDouble() { + maxSize *= 2; + Student *temp = (Student *) malloc(maxSize * sizeof(Student)); + for (int i = 0; i < studentSize; i++) { + temp[i] = students[i]; + } + students = temp; +} + +void Students::insertRecord(int index, char *name, int score) { + if (studentSize == maxSize) { + resizeArrayDouble(); + } + + Student *temp = (Student *) malloc(maxSize * sizeof(Student)); + for (int i = index; i < studentSize; i++) { + temp[i] = students[i]; + } + + students[index].num = index; + charPointerCopy(students[index].name, name); + students[index].score = score; + + for (int i = index; i < studentSize; i++) { + students[i + 1] = temp[i]; + students[i + 1].num = i + 1; + } + studentSize++; +} + +int Students::getRecordIndexByNameMatchFirst(char *name) { + for (int index = 0; index < studentSize; index++) { + if(!equals(students[index].name, name)) { + continue; + } + return index; + } + printf("no user\n"); + return -1; +} + +void Students::deleteByName(char *name) { + int targetIndex = getRecordIndexByNameMatchFirst(name); + if (targetIndex == -1) { + return; + } + + Student *temp = (Student *) malloc(maxSize * sizeof(Student)); + for (int i = targetIndex + 1; i < studentSize; i++) { + temp[i] = students[i]; + } + + for (int i = targetIndex + 1; i < studentSize; i++) { + students[i - 1] = temp[i]; + students[i - 1].num = i - 1; + } + studentSize--; +} + +void Students::listByName(char *name) { + int targetIndex = getRecordIndexByNameMatchFirst(name); + if (targetIndex == -1) { + return; + } + + printf("%d,%s,%d\n", students[targetIndex].num, students[targetIndex].name, students[targetIndex].score); +} + +void Students::validateFileNotNull(FILE *file) { + if (file == NULL) { + printf("file open error %s\n", "hw1db.txt"); + exit(-1); + } +} + +void Students::writeDB(char *name) { + FILE *file = fopen(name, "wt"); + validateFileNotNull(file); + + for (int i = 0; i < studentSize; i++) { + fprintf(file, "%d,%s,%d\n", students[i].num, students[i].name, students[i].score); + } + + fclose(file); +} + +Student Students::parseStudentInfo(char *studentInfoString, int index) { + char buffer[20]; + int idx = 0; + Student student = Student(); + student.num = index; + bool findName = false; + + int i; + for (i = 0; studentInfoString[i] != '\n'; i++) { + if (!findName && studentInfoString[i] != ',') { + continue; + } else if (!findName) { + findName = true; + } else if (findName && studentInfoString[i] != ',') { + buffer[idx++] = studentInfoString[i]; + } else { + buffer[idx] = '\0'; + charPointerCopy(student.name, buffer); + break; + } + } + + int score = 0; + for (i++; studentInfoString[i] != '\n'; i++) { + score *= 10; + score += studentInfoString[i] - '0'; + } + student.score = score; + return student; +} + + +void Students::generateMockStudent(int studentCount) { + + int randNumTemp, lowerUpperTemp; + char nameTemp[10]; + for (int i = 0; i < studentCount; i++) { + randNumTemp = rand() % 8 + 1; + // 아스키 65 ~ 90 A ~ Z + // 아스키 97 ~ 122 + for (int j = 0; j < randNumTemp; j++) { + lowerUpperTemp = rand() % 2; + if (lowerUpperTemp == 0) { + lowerUpperTemp = 65; + } else { + lowerUpperTemp = 97; + } + + nameTemp[j] = rand() % 25 + lowerUpperTemp; + } + nameTemp[randNumTemp] = '\0'; + + students[i].num = i; + charPointerCopy(students[i].name, nameTemp); + students[i].score = rand() % 100; + } + + writeDB(FILE_NAME_STRING); +} + +void Students::readDB(char *name) { + FILE *file = fopen(name, "rt"); + validateFileNotNull(file); + + int index = 0; + char currentLine[30]; + while (fgets(currentLine, sizeof(currentLine), file) != NULL) { + students[index] = parseStudentInfo(currentLine, index); + index++; + } + + fclose(file); +} + +void Students::sortByScore() { + Student temp; + for (int i = 1; i < studentSize; i++) { + temp = students[i]; + + int j = i - 1; + for (; j >= 0; j--) { + if (students[j].score > temp.score) { + students[j + 1] = students[j]; + continue; + } + break; + } + students[j + 1] = temp; + } +} + +void Students::sortByName() { + Student temp; + for (int i = 1; i < studentSize; i++) { + temp = students[i]; + + int j = i - 1; + for (; j >= 0; j--) { + if (compareToName(students[j].name, temp.name)) { + students[j + 1] = students[j]; + continue; + } + break; + } + students[j + 1] = temp; + } +} + +void Students::printStudentsInfo() { + for (int i = 0; i < studentSize; i++) { + printf("%d,%s,%d\n", students[i].num, students[i].name, students[i].score); + } + printf("\n"); +} + + + +int main() { + Students students = Students(); + students.readDB(FILE_NAME_STRING); + + char command[20]; + int indexBuffer, scoreBuffer; + char nameBuffer[20]; + + while (1) { + scanf("%s", &command); + if (equals(command, "insert")) { + scanf("%d %s %d", &indexBuffer, &nameBuffer, &scoreBuffer); + students.insertRecord(indexBuffer, nameBuffer, scoreBuffer); + } else if (equals(command, "delete")) { + scanf("%s", &nameBuffer); + students.deleteByName(nameBuffer); + } else if (equals(command, "list ")) { + scanf("%s", &nameBuffer); + students.listByName(nameBuffer); + } else if (equals(command, "sort name")) { + students.sortByName(); + } else if (equals(command, "sort score")) { + students.sortByScore(); + } else if (equals(command, "read")) { + scanf("%s", &nameBuffer); + students.readDB(nameBuffer); + } else if (equals(command, "write")) { + scanf("%s", &nameBuffer); + students.writeDB(nameBuffer); + } else if (equals(command, "print")) { + students.printStudentsInfo(); + } else if (equals(command, "exit")) { + break; + } else { + printf("there is no command like that\n"); + } + } + + +// students.printStudentsInfo(); +// +// students.sortByName(); +// students.printStudentsInfo(); +// +// students.sortByScore(); +// students.printStudentsInfo(); + + /* insert, delete, list + students.insertRecord(0, "oneone", 11); + students.insertRecord(0, "twotwo", 12); + students.insertRecord(0, "threethree", 13); + students.printStudentsInfo(); + + students.deleteByName("twotwo"); + students.printStudentsInfo(); + + students.listByName("oneone"); */ +} diff --git a/stack preorder, postorder.cpp b/stack preorder, postorder.cpp new file mode 100644 index 0000000..07ac904 --- /dev/null +++ b/stack preorder, postorder.cpp @@ -0,0 +1,89 @@ +#include +#include + +using namespace std; + +struct TreeNode { + int val = -1; + TreeNode *leftChild = nullptr, *rightChild = nullptr; +}; + +TreeNode *root; +TreeNode nodePool[10]; + +void initTree() { + + int idx = 1; + TreeNode *rootNode = &nodePool[idx]; + rootNode->val = idx; + root = rootNode; + + while (idx < 4) { + TreeNode *leftChild = &nodePool[idx*2]; + TreeNode *rightChild = &nodePool[idx*2 + 1]; + leftChild->val = idx*2; + rightChild->val = idx*2 + 1; + + nodePool[idx].leftChild = leftChild; + nodePool[idx].rightChild = rightChild; + idx++; + } +} + +// root을 1등으로, 꼴지로 +void traversalPreOrder() { + printf("========== traversalPreOrder ==========\n"); + stack st; + TreeNode *nodeNow = root; + while (1) { + while (nodeNow != nullptr) { + printf("PreOrder val : %d\n", nodeNow->val); + st.push(nodeNow); + nodeNow = nodeNow->leftChild; + } + if (st.empty()) { + break; + } + nodeNow = st.top(); + st.pop(); + nodeNow = nodeNow->rightChild; + } + printf("\n"); +} + +void traversalPostOrder() { + printf("========== traversalPostOrder ==========\n"); + stack st; + TreeNode *nodeNow = root; + while (1) { + while (nodeNow) { + st.push(nodeNow); + // 왼쪽 자식을 전부 넣어 준다. + nodeNow = nodeNow->leftChild; + } + if (st.empty()) { + break; + } + + nodeNow = st.top(); + st.pop(); + if (nodeNow != nullptr && nodeNow->rightChild != nullptr) { + // 오른쪽 자식이 있다면 일단 현재 노드 데이터를 스택에 넣는다. + TreeNode *mockNode = new TreeNode(); + mockNode->val = nodeNow->val; + st.push(mockNode); + } else { + printf("PostOrder val : %d\n", nodeNow->val); + } + nodeNow = nodeNow->rightChild; + } + printf("\n"); +} + +int main() { + + // PreOrder PostOrder 테스트 + initTree(); + traversalPreOrder(); + traversalPostOrder(); +} diff --git a/stack, queue implemented by linked list, and maze escape.cpp b/stack, queue implemented by linked list, and maze escape.cpp new file mode 100644 index 0000000..b7a5982 --- /dev/null +++ b/stack, queue implemented by linked list, and maze escape.cpp @@ -0,0 +1,216 @@ +#include +#include + +#define NODE_CNT 10000 +using namespace std; + +int maze[6][6] = { + {0, 0, 0, 0, 0, 0}, + {1, 1, 1, 1, 1, 0}, + {0, 1, 0, 1, 0, 0}, + {0, 0, 0, 1, 1, 1}, + {0, 0, 0, 1, 0, 0}, + {0, 0, 0, 0, 0, 0}, +}; +int dy[4] = {0, 0, -1, 1}; +int dx[4] = {1, -1, 0, 0}; + +// Stack +struct StackNode { + int val = -1; + StackNode *next = nullptr; +}; + +int sNodeCnt; +StackNode sNodePool[NODE_CNT]; + +StackNode *getStackNode(int val) { + sNodePool[sNodeCnt].val = val; + return &sNodePool[sNodeCnt++]; +} + +// top의 바로 뒤에 계속 붙이자 +struct Stack { +private: + StackNode topNode; + int stackSize; + +public: + Stack() { + stackSize = 0; + topNode.val = -1; + topNode.next = nullptr; + } + + int top() { + if (stackSize == 0) { + printf("[ERROR] : stack is empty!\n"); + return -1; + } + return topNode.next->val; + } + + void push(int val) { + StackNode *newNode = getStackNode(val); + if (topNode.next == nullptr) { + topNode.next = newNode; + newNode->next = nullptr; + } else { + newNode->next = topNode.next; + topNode.next = newNode; + } + stackSize++; + } + + void pop() { + if (stackSize == 0) { + printf("[ERROR] : stack is empty!\n"); + return; + } + + if (topNode.next->next == nullptr) { + topNode.next = nullptr; + } else { + topNode.next = topNode.next->next; + } + stackSize--; + } + + int size() { + return stackSize; + } +}; + +// Queue +struct QueueNode { + int val = -1; + QueueNode *next = nullptr, *prev = nullptr; +}; + +int qNodeCnt; +QueueNode qNodePool[NODE_CNT]; + +QueueNode *getQueueNode(int val) { + qNodePool[qNodeCnt].val = val; + return &qNodePool[qNodeCnt++]; +} + +struct Queue { +private: + QueueNode head, tail; + int qSize; + +public: + Queue() { + qNodeCnt = qSize = 0; + head.val = tail.val = -1; + head.next = &tail; + tail.prev = &head; + tail.next = head.prev = nullptr; + } + + // head next next tail + int front() { + if (qSize != 0 && tail.prev != &head) { + return tail.prev->val; + } + printf("[ERROR] : queue is empty!\n"); + return -1; + } + + void push(int val) { + QueueNode *newNode = getQueueNode(val); + newNode->next = head.next; + newNode->next->prev = newNode; + head.next = newNode; + newNode->prev = &head; + + qSize++; + } + + void pop() { + if (qSize == 0 || tail.prev == &head) { + printf("[ERROR] : queue is empty!\n"); + return; + } + + tail.prev->prev->next = &tail; + tail.prev = tail.prev->prev; + qSize--; + } + + int size() { + return qSize; + } +}; + +// 미로 탈출 +bool check[36]; +void escapeMaze(int start, int end) { + + Stack stack = Stack(); + stack.push(start); + check[start] = true; + while (stack.size() > 0) { + int top = stack.top(); + stack.pop(); + + check[top] = true; + if (top == end) { + printf("find {%d, %d}! -> escape!\n", top / 6, top % 6); + return; + } + + int yNow = top / 6; + int xNow = top % 6; + printf("node now : {%d, %d}\n", yNow, xNow); + + for (int i = 0; i < 4; i++) { + int nextY = yNow + dy[i]; + int nextX = xNow + dx[i]; + + if (0 > nextY || nextY > 5) continue; + if (0 > nextX || nextX > 5) continue; + if (check[nextY * 6 + nextX] || maze[nextY][nextX] == 0) continue; + + stack.push(nextY * 6 + nextX); + } + } +} + +int main() { + + + Stack stack = Stack(); + Queue queue = Queue(); + + for (int i = 1; i <= 5; i++) { + stack.push(i); + queue.push(i); + } + + printf("stack size : %d\n", stack.size()); + for (int i = 1; i<= 6; i++) { + int top = stack.top(); + if (top != -1) { + printf("stack top : %d\n", top); + } + + stack.pop(); + } + printf("stack size : %d\n", stack.size()); + + printf("queue size : %d\n", queue.size()); + for (int i = 1; i<= 6; i++) { + int front = queue.front(); + if (front != -1) { + printf("queue front : %d\n", front); + } + queue.pop(); + } + printf("queue size : %d\n", queue.size()); + + // 미로 탈출 예제 + pair start = {1, 0}, end = {3, 5}; + escapeMaze(start.first * 6 + start.second, end.first * 6 + end.second); +} diff --git a/total spanning tree, dfs, bfs.cpp b/total spanning tree, dfs, bfs.cpp new file mode 100644 index 0000000..5cd3d58 --- /dev/null +++ b/total spanning tree, dfs, bfs.cpp @@ -0,0 +1,121 @@ +// +// Created by Jinho on 2023-05-04. +// + +#include +#include +#include + +using namespace std; + +class Edge { +public: + int to; + int cost; + Edge(int _to, int _cost) { + to = _to; + cost = _cost; + } +}; + +class Node { +public: + vector link = vector(); +} nodePool[10]; +bool check[10]; + +int getNumber(char ch) { + return ch - 'a'; +} + +int graphCnt = 0; +int minCost = 987654321; +void dfs(int nodeCnt, int nodeNumberNow, int costNow, vector &path) { + if (nodeCnt == 0) { + graphCnt++; + cout << "path : "; + for (int p : path) { + cout << (char ) ('a' + p) << " -> "; + } + cout << "(cost : "; + if (minCost >= costNow) { + minCost = costNow; + cout << minCost << " -> " << costNow; + } else { + cout << costNow; + } + cout << "), (minCost : " << minCost << ")\n"; + return; + } + + for (int i = 0; i < nodePool[nodeNumberNow].link.size(); i++) { + Edge edgeNow = nodePool[nodeNumberNow].link[i]; + + if (check[edgeNow.to]) continue; + + check[edgeNow.to] = true; + path.emplace_back(edgeNow.to); + dfs(nodeCnt - 1, edgeNow.to, costNow + edgeNow.cost, path); + path.pop_back(); + check[edgeNow.to] = false; + } +} + + +int dist[10]; +queue que; +void bfs(int start) { + + que.push(start); + check[start] = true; + while (!que.empty()) { + int nodeNow = que.front(); + que.pop(); + + for (Edge edge : nodePool[nodeNow].link) { + if (check[edge.to]) continue; + check[edge.to] = true; + dist[edge.to] = dist[nodeNow] + edge.cost; + que.push(edge.to); + cout << (char) (nodeNow + 'a') << " -> " << (char ) (edge.to + 'a') << '\n'; + } + } +} + +int main() { + + nodePool[getNumber('a')].link.emplace_back(Edge(getNumber('b'), 29)); + nodePool[getNumber('a')].link.emplace_back(Edge(getNumber('f'), 10)); + + nodePool[getNumber('b')].link.emplace_back(Edge(getNumber('a'), 29)); + nodePool[getNumber('b')].link.emplace_back(Edge(getNumber('c'), 16)); + nodePool[getNumber('b')].link.emplace_back(Edge(getNumber('g'), 15)); + + nodePool[getNumber('c')].link.emplace_back(Edge(getNumber('b'), 16)); + nodePool[getNumber('c')].link.emplace_back(Edge(getNumber('d'), 12)); + + nodePool[getNumber('d')].link.emplace_back(Edge(getNumber('c'), 12)); + nodePool[getNumber('d')].link.emplace_back(Edge(getNumber('e'), 22)); + nodePool[getNumber('d')].link.emplace_back(Edge(getNumber('g'), 18)); + + nodePool[getNumber('e')].link.emplace_back(Edge(getNumber('d'), 22)); + nodePool[getNumber('e')].link.emplace_back(Edge(getNumber('f'), 27)); + nodePool[getNumber('e')].link.emplace_back(Edge(getNumber('g'), 25)); + + nodePool[getNumber('f')].link.emplace_back(Edge(getNumber('a'), 10)); + nodePool[getNumber('f')].link.emplace_back(Edge(getNumber('e'), 27)); + + nodePool[getNumber('g')].link.emplace_back(Edge(getNumber('b'), 15)); + nodePool[getNumber('g')].link.emplace_back(Edge(getNumber('d'), 18)); + nodePool[getNumber('g')].link.emplace_back(Edge(getNumber('e'), 25)); + +// bfs(getNumber('a')); +// return 0; + + vector path = vector(); + path.emplace_back(getNumber('a')); + check[getNumber('a')] = true; + dfs(6, getNumber('a'), 0, path); + cout << "total spanning tree : " << graphCnt << '\n'; +} + diff --git "a/\354\265\234\354\206\214 \354\212\244\355\214\250\353\213\235 \355\212\270\353\246\254 \352\265\254\354\204\261 \354\230\210\354\240\234.md" "b/\354\265\234\354\206\214 \354\212\244\355\214\250\353\213\235 \355\212\270\353\246\254 \352\265\254\354\204\261 \354\230\210\354\240\234.md" new file mode 100644 index 0000000..0552dde --- /dev/null +++ "b/\354\265\234\354\206\214 \354\212\244\355\214\250\353\213\235 \355\212\270\353\246\254 \352\265\254\354\204\261 \354\230\210\354\240\234.md" @@ -0,0 +1,59 @@ +# 최소 스패닝 트리 구성 예제 +예제는 크루스칼과 프림을 중심으로 살펴보자.
+여기서는 구체적인 코드나 원리보다는, 그냥 스패닝 트리를 만들어 가는 과정을 살펴볼 것이다.
+크루스칼과 프림의 큰 차이점은, 전체 그래프 어디서든 최소 비용 간선을 고르는 것과, 이미 만들어진 트리와 연결된 트리 중에서 고르는 것의 차이가 있다.
+ +## 1. Kruscal Algorithm +[크루스칼 개념 설명 바로가기]() + +1. 전체에서 최소 비용 간선 부터 만들어간다. +2. 사이클을 만들 경우 트리에 추가하지 않는다. + +### Kruscal 예시 +![kruscal 1](https://user-images.githubusercontent.com/71186266/205679653-6d3fd4f1-3ba8-42be-9b98-cbf01269de07.png) +1. 전체에서 가장 비용이 작은 10으로 시작을 끊는다. +2. 12, 14, 16 순으로 (f)까지 계속 완성 +3. **3번 노드와 6번 노드를 이어주는 18의 차례이나, 사이클을 형성하므로 폐기** +4. 다음으로 큰 숫자인 22를 선택한다 +5. **4, 6 노드를 잇는 24 코스트 간선도 사이클을 형상하므로 고르지 않음** +6. 계속 진행하여 완성.. + +
+ + +## 2. Prim Algorithm +1. 시작 노드를 정한다. +2. 이미 완성된 트리의 **노드들과 연결된 간선 중 최소 비용 간선을 꺼낸다.** +3. 간선의 두 노드가 모두 트리에 속해있다면, 그 간선은 버린다. + +
+ +프림은 모든 수행을 마치고 최소 스패닝 트리가 완성되지 않을 수도 있다!
+**즉, 수행이 끝나고도 n-1개의 간선이 사용되지 않을 수도 있다!! (주의)** + +### Prime 예시 1 - 3에서 시작 +![prim 3](https://user-images.githubusercontent.com/71186266/205679658-13adf572-37f4-4948-94c6-f8034029e343.png) + +노드 3에서 부터 시작한다. +1. 3과 이어진 12, 18, 22 중에 가장 코스트가 작은 12 간선 부터 시작한다 +2. 2번 노드가 추가되면서 16 코스트 간선이 추가 +3. 이런 방식이 계속 반복된다. +4. **c에서 원래는 3번 6번 노드를 잇는 18이 선택 되는 것이 옳으나, 사이클을 형성하므로 22 코스트인 3-4 노드가 선택됐다.** + +### Prime 예시 2 - 6에서 시작 :star: +![prim6](https://user-images.githubusercontent.com/71186266/205679660-1cdce0ad-9fde-4f65-968f-d4a9c6b8c7ef.jpg) + +직접 해본 예제 +1. 6번 노드에서 시작한다. +2. 위와 같은 진행. 완성된 트리와 이어져있는 간선들 중 가장 코스트가 작은 것을 고른다 +3. 사이클을 만들면 다음 간선을 살핀다 +4. 계속 반복.. + + +## 3. Solin Alogritm +각 단계에서 여러 간선을 동시에 선택한다.
+포레스트 안의 각 트리에 대해 하나의 간선을 선택한다. 선택하는 간선은 한 트리에 오직 하나의 정점만 속해야 한다. 선택된 간선은 구축중인 신장트리에 추가하고 오직 하나의 트리만이 존재하거나, 더 이상 선택할 간선이 없을 때 종료한다.
+복잡하지만 성능이 좋다! + +## Reference +- Fundamentals of Data Structures in C++ \ diff --git "a/\355\235\254\354\206\214 \355\226\211\353\240\254 array, list.md" "b/\355\235\254\354\206\214 \355\226\211\353\240\254 array, list.md" new file mode 100644 index 0000000..bc92624 --- /dev/null +++ "b/\355\235\254\354\206\214 \355\226\211\353\240\254 array, list.md" @@ -0,0 +1,104 @@ + +# 희소행렬 +아마도, 희소 행렬의 연산과 희소 리스트로의 변화가 관찰 포인트가 되지 않을까? + + +## 1. 희소 행렬 Array +### 1.1 행렬의 전치 +#### 기존 알고리즘 +```c++ +for (int i = 0; i < row; i++) + for (int j = 0; j < columns; j++) + b[j][i] = a[i][j]; +``` +당연히 O(row*columns) + +#### terms로 개선한 알고리즘 +**O(terms*cols)**
+그냥 열마다 terms만큼 움직이고, 다 찾으면 엄춘다는 장점이 있는 듯 + +```c++ +int (terms > 0) +{ + int currentB = 0; + for (int c = 0; c < cols; c++) + { + for (int i = 0; i < terms; i++) + { + if (smArray[i].col == c) + { + b.smArray[currentB].row = c; + b.smArray[currentB].col = smArray[i].row; + b.smArray[currentB++].value = smArray[i].value; + } + } + } +} +``` +돌면서 b의 어레이에 몇 번째 원소, row, col 어디있는지 + 값 이렇게 저장.
+*this와 b가 필요로하는 공간 외에는.. c, i, currentB만을 위한 고정 공간 필요 + +#### 개선된 알고리즘 +메모리 Tradeoff 각 열에 대한 원소 수를 미리 알고 간다. +
실행시간 무려 O(cols + term)! + +```c++ +SparseMatrix sparseMatrix::FastTranspose() +{ + SparseMatrix b (cols, rows, terms); + if (terms > 0) + { + int *rowSize = new int[cols]; + int *rowStart = new int[cols]; + + fill (rowSize, rowSize + cols, 0); + + // 모든 원소 순회해서 col가져와서 ++ + // col 마다 원소ㅗ가 몇 개인지? + for (int i = 0; i < terms; i++) rowSize[smArray[i].col]++; + + rowStart = 0; + // 새로 만들 행렬에 넣어줄 원소가 원래 smArray에서 몇 번째 + // 원소였는지를 저장해뒀다가 또 쓴다. 이러면 중복이 없지! + for (int i = 1; i < cols; i++) rowStart[i] = rowStart[i-1] + rowSize[i-1]; + for (int i = 0; i < terms; i++) + { + int j = rowStart[smArray[i].col]; + b.smArray[j].row = smArray[i].col; + b.smArray[j].col = smArray[i].row; + b.smArray[j].value = smArray[i].value; + rowStart[smArray[i].col]++; + } + delete [] rowSize; + delete [] rowStart; + } +} +``` + +### 1.2 행렬 곱 +무려 N^3 +```c++ +for (int i = 0; i < a.rows; i++) { + for (int j = 0; j < b.cols; j++) { + sum = 0; + for (int k = 0; k < a.cols; k++) + sum += (a[i][k] * b[k][j]); + c[i][j] = sum; + } +} +``` + + +## 2. 희소 행렬 List +그냥 Matrix 모양의 Linked List를 만들자는 Idea. +1. 헤더 노드가 있는 원형 리스트 사용 +2. 0이 아닌 각 항은 **행 원형 리스트에** 속하는 동시에, **열 원형 리스트에 소속됨.** +3. 헤더 노드와 원소 노드를 나눈다. 열 리스트는 `down`, 행 리스트는 `right` 필드가 있다. 헤드 노드끼리는 `next` 필드가 연결. i쨰 헤더는 i쨰 열과 행의 헤더 역할을 모두 수행. +4. 원소 노드 - Matrix 전체 헤더 노드: 얘도 down, right 필드가 있다. 같은 열과 행의 0이 아닌 다음 항을 연결한다. 그리고 해당 원소의 정보를 저장하는 필드 row, col, value.. + +### 필요한 노드 수 +r개의 0 아닌 항을 가진 n*m 희소행렬이라면,
+n과 m중 더 큰 값 max{n, m} + r + 1개
+왜냐하면 행열노드 + 0 아닌 노드 + 전체 헤더 노드 + +## 각종 연산 구현 가능