From 8705adb07b8619df3fba064a214aac3ff498be22 Mon Sep 17 00:00:00 2001 From: binary_ho Date: Thu, 28 Mar 2024 13:12:02 +0900 Subject: [PATCH] =?UTF-8?q?docs=20:=20=EB=8B=A4=EB=A5=B8=20=EB=A0=88?= =?UTF-8?q?=ED=8F=AC=EC=97=90=20=EC=A0=80=EC=9E=A5=ED=95=B4=20=EB=86=93?= =?UTF-8?q?=EC=9D=80=20=EC=9E=90=EB=A3=8C=20=EA=B0=80=EC=A0=B8=EC=98=A4?= =?UTF-8?q?=EA=B8=B0=20(#2)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...4\354\240\204 \354\230\210\354\240\234.md" | 47 +++ "AVL Tree/\354\275\224\353\223\234/AVL.cpp" | 139 +++++++ "AVL Tree/\354\275\224\353\223\234/AVL.h" | 29 ++ "AVL Tree/\354\275\224\353\223\234/hw12.cpp" | 60 +++ Heap/Max Heap Code/hw9.cpp | 31 ++ Heap/Max Heap Code/maxheap.h | 108 +++++ Linked List/list.cpp | 65 +++ Linked List/list.h | 21 + Linked List/main.cpp | 34 ++ ...4\354\240\204 \354\230\210\354\240\234.md" | 64 +++ Polynomial/polya.cpp | 92 +++++ Polynomial/polya.h | 30 ++ Postfix Traversal/hw5.cpp | 18 + Postfix Traversal/post.cpp | 186 +++++++++ Postfix Traversal/post.h | 68 +++ ...5\225\234 sorting algorithms cpp code.cpp" | 237 +++++++++++ Subway Problem/hw10.cpp | 38 ++ Subway Problem/subway.cpp | 151 +++++++ Subway Problem/subway.h | 53 +++ Tree Traversal/README.md | 84 ++++ Tree Traversal/bt.h | 121 ++++++ binary tree, heap sort database.cpp | 268 ++++++++++++ .../DataStructureHomeWork11.m | 69 ++++ compare sorting performance/hw11.cpp | 51 +++ compare sorting performance/sort.h | 193 +++++++++ infixToPostfix, postfixCalculator, dfs.cpp | 388 ++++++++++++++++++ linked list, stack, queue, bst, graph.cpp | 276 +++++++++++++ mini database - hashTable ver.cpp | 189 +++++++++ mini database.cpp | 353 ++++++++++++++++ stack preorder, postorder.cpp | 89 ++++ ...mented by linked list, and maze escape.cpp | 216 ++++++++++ total spanning tree, dfs, bfs.cpp | 121 ++++++ ...4\354\204\261 \354\230\210\354\240\234.md" | 59 +++ ...4 \355\226\211\353\240\254 array, list.md" | 104 +++++ 34 files changed, 4052 insertions(+) create mode 100644 "AVL Tree/AVL \355\212\270\353\246\254 \354\213\244\354\240\204 \354\230\210\354\240\234.md" create mode 100644 "AVL Tree/\354\275\224\353\223\234/AVL.cpp" create mode 100644 "AVL Tree/\354\275\224\353\223\234/AVL.h" create mode 100644 "AVL Tree/\354\275\224\353\223\234/hw12.cpp" create mode 100644 Heap/Max Heap Code/hw9.cpp create mode 100644 Heap/Max Heap Code/maxheap.h create mode 100644 Linked List/list.cpp create mode 100644 Linked List/list.h create mode 100644 Linked List/main.cpp create mode 100644 "Permutations \354\213\244\354\240\204 \354\230\210\354\240\234.md" create mode 100644 Polynomial/polya.cpp create mode 100644 Polynomial/polya.h create mode 100644 Postfix Traversal/hw5.cpp create mode 100644 Postfix Traversal/post.cpp create mode 100644 Postfix Traversal/post.h create mode 100644 "Sorting Algorithm/\353\213\244\354\226\221\355\225\234 sorting algorithms cpp code.cpp" create mode 100644 Subway Problem/hw10.cpp create mode 100644 Subway Problem/subway.cpp create mode 100644 Subway Problem/subway.h create mode 100644 Tree Traversal/README.md create mode 100644 Tree Traversal/bt.h create mode 100644 binary tree, heap sort database.cpp create mode 100644 compare sorting performance/DataStructureHomeWork11.m create mode 100644 compare sorting performance/hw11.cpp create mode 100644 compare sorting performance/sort.h create mode 100644 infixToPostfix, postfixCalculator, dfs.cpp create mode 100644 linked list, stack, queue, bst, graph.cpp create mode 100644 mini database - hashTable ver.cpp create mode 100644 mini database.cpp create mode 100644 stack preorder, postorder.cpp create mode 100644 stack, queue implemented by linked list, and maze escape.cpp create mode 100644 total spanning tree, dfs, bfs.cpp create mode 100644 "\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" create mode 100644 "\355\235\254\354\206\214 \355\226\211\353\240\254 array, list.md" 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 아닌 노드 + 전체 헤더 노드 + +## 각종 연산 구현 가능