본문 바로가기

자료구조

힙(우선순위 큐) 구현 #2

실행소스:github.com/KJT9109/Data_Structure/tree/master/Heap_ProrityQueue

 

앞서 설계한 구조를 가지고 설계를 해보자

 

우선 힙 구조체 선언은 다음과 같다.

 

Heap Data Structure

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
 
#define MAXIMUM_SIZE 255
 
typedef char HData;
typedef int HNode;
 
typedef HData (*HPriorityCompare)(HData, HData);
 
typedef struct
{
    int heapNode;
    HPriorityCompare HPriorityFunc;
    HData heapData[MAXIMUM_SIZE];
 
}HeapStruct;
 
cs

 

HeapStruct의 멤버변수

heapNode : 자료구조의 저장 갯수.

HPriorityFunc: 우선순위를 판단하는 함수.

heapData:Heap Data를 저장할 배열

 

 

HeapRawFunc

 

노드를 구하기 위한 함수

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
 
 
HNode HReadParentNode(HNode curNode)
{
    return curNode / 2;
}
 
HNode HReadChildLeftNode(HNode curNode)
{
    return curNode * 2;
}
 
HNode HReadChildRightNode(HNode curNode)
{
    return (curNode * 2+ 1;
}
 
HNode HFindNode(HeapStruct useHstr, HData wantData)
{
    HNode findNode = 0;
 
    while (strcmp(&(useHstr.heapData[++findNode]), &wantData))
    {
        return findNode;
    }
 
    return 0;
}
 
cs

 

노드의 데이터를 구하기 위한 함수

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
 
HData HReadData(HeapStruct useHstr, HNode curNode)
{
    return useHstr.heapData[curNode];
}
 
 
HData HReadParentData(HeapStruct useHstr, HNode curNode)
{
    return useHstr.heapData[curNode / 2];
}
 
HData HReadChildLeftData(HeapStruct useHstr, HNode curNode)
{
    return useHstr.heapData[curNode * 2];
}
 
HData HReadChildRightData(HeapStruct useHstr, HNode curNode)
{
    return useHstr.heapData[(curNode * 2+ 1];
}
 
cs

 

 

HeapApplicationFunc

API함수 경우엔 Raw Func 을 사용하여 힙 자료구조의 초기화, 삽입, 삭제를 구현 하였다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
void HeapInit(HeapStruct *useHstr)
{
    useHstr->HPriorityFunc = HPriorityCheck;
    useHstr->heapNode = 0;
    memset(useHstr->heapData, 0sizeof(useHstr->heapData) / sizeof(int));
}
 
HData HeapCount(HeapStruct useHstr)
{
    return useHstr.heapNode;
}
 
void HeapInsert(HeapStruct *useHstr, HData inData)
{
    HData tmpBuff;
    HNode tmpNode;
    useHstr->heapData[++useHstr->heapNode] = inData;
 
    tmpNode = useHstr->heapNode;
 
    /* 부모노드가 존재하고 부모노드와의 우선순위를 비교 했을 때 부모노드가 우선순위가 낮다면 */
    while (HReadParentNode(tmpNode) != 0
            && useHstr->HPriorityFunc(HReadParentData(*useHstr, tmpNode),
                    HReadData(*useHstr, tmpNode))
                    != HReadParentData(*useHstr, tmpNode))
    {
        /* 부모 노드의 데이터를 임시 버퍼에 저장한다. */
        tmpBuff = HReadParentData(*useHstr, tmpNode);
        /* 부모 노드에 현재 노드의 데이터를 저장한다. */
        useHstr->heapData[HReadParentNode(tmpNode)] =
                useHstr->heapData[tmpNode];
        /* 현재 노드에 부모 노드의 데이터를 저장한다. */
        useHstr->heapData[tmpNode] = tmpBuff;
        /* 현재 노드를 부모노드로 변경한다. */
        tmpNode = HReadParentNode(tmpNode);
    }
 
}
 
int HeapDelete(HeapStruct *useHstr, HData inData)
{
    HNode curNode;
    HNode childNode;
 
    HData tmpBuff;
 
    /* 해당 데이터가 Heap Node에  존재 하는지 찾는다.*/
    if (HFindNode(*useHstr, inData) != 0)
    {
        /* Heap의 마지막 노드(우선순위가 낮은)를 삭제된 노드로 옮긴다 */
        curNode = HFindNode(*useHstr, inData);
        useHstr->heapData[curNode] = useHstr->heapData[useHstr->heapNode];
        /* Heap의 마지막 노드를 삭제한다.*/
        useHstr->heapData[useHstr->heapNode--= 0;
 
        /* 자식 노드있는지 확인한다.*/
        while (HReadChildLeftNode(curNode) < useHstr->heapNode)
        {
            /* 자식 노드들과 우선순위를 비교 후 낮은 우선순위의 자식 노드를 구한다. */
            if (useHstr->HPriorityFunc(HReadChildLeftData(*useHstr, curNode),
                    HReadChildRightData(*useHstr, curNode))
                    == HReadChildLeftData(*useHstr, curNode))
            {
                childNode = HReadChildLeftNode(curNode);
            }
            else
            {
                childNode = HReadChildRightNode(curNode);
            }
 
            /* 현재노드가 자식노드보다 우선순위가 작다면 */
            if (useHstr->HPriorityFunc(HReadData(*useHstr, curNode),
                    HReadData(*useHstr, childNode))
                    == HReadData(*useHstr, childNode))
            {
                /* 현재 노드와 자식노드를 바꿔준다. */
 
                /* 자식 노드를 저장한다. */
                tmpBuff = HReadData(*useHstr, childNode);
                /* 자식 노드에 현재 노드의 데이터를 저장한다. */
                useHstr->heapData[childNode] = useHstr->heapData[curNode];
                /* 현재 노드에 자식 노드의 데이터를 저장한다. */
                useHstr->heapData[curNode] = tmpBuff;
                /* 현재 노드를 자식노드로 변경한다. */
                curNode = childNode;
 
            }
        }
        /* 정상적으로 종료 */
        return 0;
    }
    else
    {
        /* 데이터가 존재하지 않음 */
        return -1;
    }
 
}
 
cs

동작 방식은 앞선 글에 설명하였으므로 따로 설명하지는 않는다.

 

우선순위를 판단할때 사용한 함수는 다음과 같다.

 

HData HPriorityCheck(HData data_A, HData data_B)
{
	if (data_A <= data_B)
		return data_A;

	else
		return data_B;

}

데이터가 작을수록 우선순위가 높다

 

main에서 실행 시킬 때 문자를 집어넣었으므로(HData는 char로 선언됨) A가 가장 맨 앞 index의 와야한다.

 

Test한 Main화면

 

HeapStruct HeapStructure;

int main(void)
{
	printf("Start Heap Structure\r");
	HeapInit(&HeapStructure);

	HeapInsert(&HeapStructure, 'B');
	HeapInsert(&HeapStructure, 'D');
	HeapInsert(&HeapStructure, 'G');
	HeapInsert(&HeapStructure, 'E');
	HeapInsert(&HeapStructure, 'C');
	HeapInsert(&HeapStructure, 'A');
	HeapInsert(&HeapStructure, 'F');

	HeapDelete(&HeapStructure, 'A');
	HeapDelete(&HeapStructure, 'B');


}

Insert 까지만 실행 했을 때 디버깅화면

 

Delete 실행 후 디버깅 화면

 

'자료구조' 카테고리의 다른 글

병합 정렬 구현 (분열) #1  (0) 2021.11.14
힙(Heap)정렬 구현  (0) 2021.01.11
힙(우선순위 큐) 구현 #1  (0) 2021.01.08
수식트리의 구현 #2  (0) 2020.12.30
수식트리의 구현 #1  (0) 2020.12.30