자습
HEAP TREE with HEAP SORT ALGORITHM
CASTLELONG
2020. 12. 10. 15:35
linear linked list를 이용한 stack에 이어 두번째 algorithm 시간이다.
오늘은 heap tree와 heap sort를 구현했다.
재학시절 트리를 구현한 적이 있긴 있는데
2년이 넘도록 그에 관련한 알고리즘을 사용하지도 않고 보지도 않았으니 다 까먹었다.
그래서 heap tree를 이해하는데 한참이 걸렸다.
아무것도 모르는 사람이 heap tree 의 이미지를 보면 난해할것이다.
이미지만 보고서 구현을 할라면 무엇으로 구현을 해야하는지 착잡해지는데.
간단하다.
heap tree는 1차원 배열로 구현되며,
0이 아닌 1로 시작한다는 가정 하에 부모 자식간의 상관은
자식/2가 부모를 가리킨다.
#include <iostream>
#include <stdlib.h>
#include <math.h>
void newKey();
void delKey();
void sortKeys();
void showKeys(int *arr);
void swap(int *arr, int k1, int k2);
int *heap;
int main() {
int a;
heap = NULL;
while (true) {
std::cout << " 1.New key\n 2.Delete a Key\n 3.Sort Keys\n 4.Show keys\n 5.EXIT\n>>";
std::cin >> a;
switch (a) {
case 1:
newKey();
break;
case 2:
delKey();
break;
case 3:
sortKeys();
break;
case 4:
showKeys(heap);
break;
case 5:
delete(heap);
return 0;
}
}
return 0;
}
void newKey() {
int value,key;
std::cout << "input a new value for key\n>>";
std::cin >> value;
if (heap == NULL)
heap = new int[1]{ value };
else {
heap = (int*)realloc(heap, _msize(heap) + sizeof(int));
key = _msize(heap) / sizeof(int)-1;
heap[key] = value;
while (key > 1) {
if (heap[key] < heap[(key + 1)/ 2 - 1]) {
swap(heap, key, (key + 1)/ 2 - 1);
key = (key+1)/2-1;
}
else
break;
}
}
}
void delKey() {
int key = 0, tmpkey;
swap(heap, key, _msize(heap) / sizeof(int) - 1);
showKeys(heap);
std::cout << _msize(heap) / sizeof(int) - 1 << std::endl;
heap = (int*)realloc(heap, _msize(heap) - sizeof(int));
std::cout << _msize(heap) / sizeof(int) - 1 << std::endl;
while ((key+1)*2-1 <= _msize(heap) / sizeof(int) - 1) {
if ((key + 1) * 2 > _msize(heap) / sizeof(int) - 1 && heap[key] > heap[(key+1)*2-1]) {
swap(heap, key, (key + 1) * 2 - 1);
break;
}
else if ((key + 1) * 2 > _msize(heap) / sizeof(int) - 1) break;
else {
if (heap[(key + 1) * 2 - 1] < heap[(key + 1) * 2]) {
tmpkey = (key + 1) * 2 - 1;
}
else
tmpkey = (key + 1) * 2;
if (heap[key] > heap[tmpkey]) {
swap(heap, key, tmpkey);
key = tmpkey;
}
else break;
}
}
}
void sortKeys() {
int len = _msize(heap) / sizeof(int);
int *tmp = new int[len];
for (int i = 0; i < len; i++) {
tmp[i] = heap[i];
int key = i;
while (key > 0) {
if (tmp[key] > tmp[(key + 1) / 2 - 1]) {
swap(tmp, key, (key + 1) / 2 - 1);
key = (key + 1) / 2 - 1;
}
else
break;
}
}
for (int i = len - 1; i > 0;) {
swap(tmp, 0, i--);
int key=0, tmpKey;
while ((key + 1) * 2 - 1 <= i) {
if ((key + 1) * 2 > i && tmp[(key + 1) * 2 - 1] > tmp[key]) {
swap(tmp, key, (key + 1) * 2 - 1);
break;
}
else if ((key + 1) * 2 > i) break;
else {
if ((tmp[(key + 1) * 2 - 1]) > tmp[(key + 1) * 2]) tmpKey = (key + 1) * 2 - 1;
else tmpKey = (key + 1) * 2;
swap(tmp, key, tmpKey);
key = tmpKey;
}
}
showKeys(tmp);
}
for (int i = 0; i < len; i++)
heap[i] = tmp[i];
delete(tmp);
}
void showKeys(int *arr) {
int row;
for (row = 1; ; row++) {
if (_msize(arr) / sizeof(int) < pow(2, row))
break;
}
for (int i = 0; i < _msize(arr) / sizeof(int); i++) {
if ((float)log2(i+1) - (int)log2(i+1) == 0) {
for (int j = 0; j < pow(2, row-1)-1; j++)
std::cout << " ";
}
if (arr[i] < 10)
std::cout << " ";
std::cout << arr[i];
for (int j = 0; j < pow(2, row)-1; j++)
std::cout << " ";
if ((float)log2(i + 2) - (int)log2(i + 2) == 0) {
std::cout << std::endl;
row--;
}
}
std::cout << std::endl;
}
void swap(int *arr, int k1, int k2) {
int value = arr[k1];
arr[k1] = arr[k2];
arr[k2] = value;
머리가 좋지 않아서 구현하는데 시간이 걸렸다.
특히 delete함수를 구현했지만 멍청하게 해서 자괴감이 들었다.
혼자 배우며 어떠한 서적도 참고하지 않는 공부라서
위 코드로 실행하면 버그가 생기는 부분이 여러군데 있을지도 모르겠다.
배우며 느낀것은
나는 멍청하다.
태클 환영.