#pragma once
#include <stdio.h>
#include <stdlib.h>
struct ListNode {
int data;
struct ListNode* link;
};
struct ListManager
{
struct ListNode* head;
struct ListNode* ci; // current index;
struct ListNode* pi; // previous index;
int (*comp)(int d1, int d2);
int node_count; // data 값이 유효한 node의 수
int malloc_count; // 할당된 수
};
void ListInit(struct ListManager* lm);
void LInsertNoSort(struct ListManager* lm, int data);
void FInsert(struct ListManager* lm, int data);
void SInsert(struct ListManager* lm, int data);
void LInsert(struct ListManager* lm, int data);
int LFirst(struct ListManager* lm, int* data);
int LNext(struct ListManager* lm, int* data);
int LCount(struct ListManager* lm);
int LRemove(struct ListManager* lm);
int WhoIsPrecede(int d1, int d2);
void SetSortRule(struct ListManager* lm, int (*comp)(int d1, int d2));
void* CreateNodeMemory(struct ListManager* lm, int len);
void ShowList(struct ListManager* lm);
void DeleteNode(struct ListManager* lm, struct ListNode* target);
void DeleteList(struct ListManager* lm);
void ListInit(struct ListManager* lm)
{
// count 초기화
lm->node_count = 0;
lm->malloc_count = 0;
// head 다음으로 항상 유지하는 빈 노드 생성
struct ListNode* new_node = (struct ListNode*)CreateNodeMemory(lm, sizeof(struct ListNode));
new_node->data = -1;
new_node->link = NULL; // 제일 끝이므로 무조건 NULL을 갖는다.
// 연결리스트 헤드 초기화
lm->head = (struct ListNode*)CreateNodeMemory(lm, sizeof(struct ListNode));
lm->head->data = -1;
lm->head->link = new_node;
// 인덱스 초기화
lm->ci = NULL;
lm->pi = NULL;
SetSortRule(lm, WhoIsPrecede);
//lm->comp = NULL;
return;
}
void LInsertNoSort(struct ListManager* lm, int data)
{
struct ListNode* new_node = (struct ListNode*)CreateNodeMemory(lm, sizeof(struct ListNode));
// head 다음의 빈 노드에 값을 반영, 링크는 건들지 않는다.
lm->head->link->data = data;
// empty_node 설정
new_node->data = -1;
new_node->link = lm->head->link;
lm->head->link = new_node;
lm->node_count++;
return;
}
void FInsert(struct ListManager* lm, int data)
{
struct ListNode* new_node = (struct ListNode*)CreateNodeMemory(lm, sizeof(struct ListNode));
// head 다음의 빈 노드에 값을 반영, 링크는 건들지 않는다.
lm->head->link->data = data;
// empty_node 설정
new_node->data = -1;
new_node->link = lm->head->link;
lm->head->link = new_node;
lm->node_count++;
return;
}
void SInsert(struct ListManager* lm, int data)
{
struct ListNode* new_node = (struct ListNode*)CreateNodeMemory(lm, sizeof(struct ListNode));
struct ListNode* pred = lm->head->link;
new_node->data = data;
while (pred->link != NULL && lm->comp(data, pred->link->data) != 0)
pred = pred->link;
// predecessor이 마지막 노드이면 그냥 거기다가 추가하면 되기 때문에 마지막 노드까지 가지 아니한다.
new_node->link = pred->link;
pred->link = new_node;
(lm->node_count)++;
return;
}
void LInsert(struct ListManager* lm, int data)
{
if (lm->comp == NULL)
{
printf("FInsert();\n");
FInsert(lm, data);
}
else
{
printf("SInsert();\n");
SInsert(lm, data);
}
return;
}
int LFirst(struct ListManager* lm, int* data)
{
if (lm->node_count == 0)
{
printf("순회할 노드가 없습니다.\n");
return false;
}
lm->ci = lm->head->link->link;
lm->pi = lm->head->link;
*data = lm->ci->data;
return true;
}
int LNext(struct ListManager* lm, int* data)
{
if (lm->ci->link == NULL)
return false;
lm->pi = lm->ci;
lm->ci = lm->ci->link;
*data = lm->ci->data;
return true;
}
int LCount(struct ListManager* lm)
{
return lm->node_count;
}
int LRemove(struct ListManager* lm)
{
int remove_value = lm->ci->data;
struct ListNode* rtarget = lm->ci;
lm->pi->link = rtarget->link;
lm->ci = lm->pi;
DeleteNode(lm, rtarget);
return remove_value;
}
int WhoIsPrecede(int d1, int d2)
{
if (d1 < d2)
return 0; // d1이 정렬 순서상 앞선다.
else
return 1; // d2가 정렬 순서상 앞서거나 같다.
}
void SetSortRule(struct ListManager* lm, int (*comp)(int d1, int d2))
{
lm->comp = comp;
return;
}
void* CreateNodeMemory(struct ListManager* lm, int len)
{
lm->malloc_count++;
return (void*)malloc(len);
}
void ShowList(struct ListManager* lm)
{
struct ListNode* index_node = NULL;
if (lm->malloc_count == 0)
{
printf("head와 new node 및 일반 node들까지 모두 존재하지 않습니다.");
return;
}
else if (lm->node_count == 0)
printf("추가된 노드는 모두 제거된 상태이지만, head와 new node가 존재하고 추가 가능한 상태입니다.\n");
for (index_node = lm->head; index_node != NULL; index_node = index_node->link)
{
printf("[%d|%p]", index_node->data, index_node);
if (index_node->link != NULL)
printf("->");
}
fputc('\n', stdout);
return;
}
void DeleteNode(struct ListManager* lm, struct ListNode* target)
{
if (target->data != -1)
lm->node_count--;
free(target);
lm->malloc_count--;
return;
}
void DeleteList(struct ListManager* lm)
{
struct ListNode* index_node = NULL;
struct ListNode* next_node = NULL;
for (index_node = lm->head; index_node != NULL; index_node = next_node)
{
next_node = index_node->link;
DeleteNode(lm, index_node);
}
if (lm->malloc_count != 0)
printf("메모리 해체에 문제가 있습니다\n");
return;
}