2 * i + 12 * i + 2(i - 1) / 2typedef struct
{
int last;
int capacity;
void **heapArr;
int (*compare) (const void *, const void *);
} HEAP;
🤔힙 배열을 생성하는데 왜 이중포인터를 사용할까?
typedef struct
{
int last;
int capacity;
void **heapArr;
int (*compare) (const void *, const void *);
} HEAP;
🔸 1. 배열을 만들기 위한 포인터
✅ 목적: 동적 배열을 구현하기 위해
이중 포인터 void **heapArr는"포인터 배열"을 만들기 위해 쓰임
📌 예시:
void **heapArr = malloc(sizeof(void*) * capacity);
이렇게 하면 heapArr는 포인터들을 담는 배열
즉, 각 원소는 다시 데이터를 가리키는 포인터
heapArr
↓
+------+------+------+------+
| * | * | * | ... | → 각각 void* 타입 (데이터 주소)
+------+------+------+------+
그래서:
heapArr[0] → 데이터 0의 주소 (예: int*, tWord*)heapArr[1] → 데이터 1의 주소🔸 2. 어떤 형태이든 올 수 있도록 하는 포인터
✅ 목적: 자료형에 관계없이 다양한 데이터를 저장하기 위해
void *는 "형태가 정해지지 않은 주소"를 저장할 수 있는 포인터
즉, 어떤 자료형이든 담을 수 있음:
int*, char*, float*, 구조체 포인터 등 다 가능
HEAP *heap_Create(int (*compare)(const void *, const void *)) {
HEAP *heap = (HEAP *)malloc(sizeof(HEAP));
if (!heap) return NULL;
heap->heapArr = (void **)malloc(sizeof(void *) * INIT_CAPACITY);
//메모리 할당 중간 실패 시 메모리 누수 방지
if (!heap->heapArr) {
free(heap);
return NULL;
}
//현재 요소 없음 : last는 -1
heap->last = -1;
heap->capacity = INIT_CAPACITY;
heap->compare = compare;
return heap;
}
힙 구조를 그림으로 나타내면 아래와 같음
void heap_Destroy(HEAP *heap, void (*remove_data)(void *)) {
for (int i = 0; i <= heap->last; i++) {
remove_data(heap->heapArr[i]);
}
free(heap->heapArr);
free(heap);
}
//dataPtr : 삽입할 데이터의 주소
int heap_Insert(HEAP *heap, void *dataPtr) {
if (heap->last + 1 >= heap->capacity) {
//메모리 재할당 (현재 메모리의 2배)
void **temp = realloc(heap->heapArr, sizeof(void *) * heap->capacity * 2);
if (!temp) return 0;
heap->heapArr = temp;
heap->capacity *= 2;
}
//last 인덱스를 하나 증가시키고 새 데이터를 해당 위치에 삽입
heap->last++;
heap->heapArr[heap->last] = dataPtr;
//새로 삽입된 요소가 heap 조건을 만족시키도록 위로 올리기
_reheapUp(heap, heap->last);
//성공적으로 삽입되었으면 1 반환
return 1;
}
힙은 루트 노트를 삭제하고 마지막 노드를 루트로 이동한다. 이후 reheapDown을 통해 힙 정렬을 한다.
int heap_Delete(HEAP *heap, void **dataOutPtr) {
//힙이 비었는지 확인
if (heap->last < 0) return 0;
*dataOutPtr = heap->heapArr[0];
//마지막 노드를 루트로 이동
//이후에 last--로 힙 크기 감소
heap->heapArr[0] = heap->heapArr[heap->last--];
_reheapDown(heap, 0);
return 1;
}
heap->heapArr[0] = heap->heapArr[heap->last--];
이 코드가 진행되는 게 왜
마지막 노드를 루트로 이동 -> 이후에 last --로 힙 크기 감소가 되는지 궁금했다.
last--로 힙 크기 감소하고 루트로 이동할 수도 있지 않은가?
그러나 --last가 아니라 last--라고 연산을 수행하고 마이너스를 실행하는 것이었다.