cur→next를 이용하기 위해서 사라지기 전 백업하기 위해 포인터 변수 2개(dN, dNN) 필요
2. 단순 연결 리스트의 ADT와 구현
새 노드를 머리에 추가하는 경우
장점 : 포인터 변수 tail이 불필요하다.
단점 : 저장된 순서를 유지하지 않는다.
새 노드를 꼬리에 추가하는 경우
장점 : 저장된 순서가 유지된다.
단점 : 포인터 변수 tail이 필요하다.
- SetSortRule 함수 선언에 대한 이해
1
2
3
4
voidSetSortRule(List * plist, int (*comp)(LData d1, LData d2) );
->int (*comp)(LData d1, LData d2) // 반환형이 int이고, LData형 인자를
// 두 개 전달받는 함수의 주소값을 전달
이렇듯 결정된 약속을 근거로 함수가 정의되어야 하며, 연결 리스트 또한 이를 근거로 구현되어야 한다.
- 더미 노드 기반 연결 리스트
dummy node : 유효한 데이터가 없는 노드
→ 더미 노드를 처음에 미리 초기화를 시키고 이후의 모든 연산이 처음 노드를 건너뛰고 연산을 진행 할 수 있도록 한다. ⇒ 노드 추가 및 삭제 방식이 항상 일정해짐! 분기 줄어듦
- 정렬 기능 추가된 연결 리스트의 구조체
1
2
3
4
5
6
7
8
9
10
typedefstruct_linkedList
{
Node * head; // 더미 노드를 가리킴
Node * cur; // 참조 및 삭제 용
Node * before; // 삭제를 도움
int numOfData; // 저장된 데이터의 수
int (*comp)(LData d1, LData d2); // 정렬의 기준을 등록하기 위한 멤버
}
typedef LinkedList List; // 별도 이름을 주어 헤더파일에서 임의로 간편히 자료형 변환
// 삭제
LData LRemove(List * plist)
{
// 데이터 백업
Node * rpos = plist->cur;
LData rdata = rpos->data;
// 데이터 이동
plist->before->next = plist->cur->next;
plist->cur = plist->before;
// 데이터 삭제
free(rpos);
(plist->numOfData)--;
return rdata;
}
cur 이전 데이터로 값을 얻을 수 없으므로 before 변수를 통해서 미리 값 저장
3. 연결 리스트의 정렬 삽입의 구현
단순 연결 리스트의 정렬 관련 3 요소
정렬기준이 되는 함수를 등록하는 SetSortRule 함수
SetSortRule 함수로 전달된 함수정보 저장을 위한 LinkedList의 멤버 comp [정의기준]
comp에 등록된 정렬기준을 근거로 데이터를 저장하는 SInsert 함수
⇒“SetSortRule 함수가 호출되면서 정렬의 기준이 리스트의 멤버 comp에 등록되면, SInsert 함수 내에서는 comp에 등록된 정렬의 기준을 근거로 데이터를 정렬하여 저장한다.”
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
voidSInsert(List * plist, LData data)
{
Node * newNode = (Node*)malloc(sizeof(Node)); // 노드 생성
Node * pred = plist->head; // 더미 노드 가리킴 (A-B 중 A로 B 알수있음
newNode->data = data;
// 새 노드가 들어갈 위치를 찾기 위한 반복문!
while(pred->next != NULL && plist->comp(data, pred->next->data) !=0)
// 리스트의 끝 && 들어온 데이터의 정렬 순서가 뒤로 가야하는 상황
{
pred = pred->next; // 다음 노드로 이동
}
// 데이터 추가
newNode->next = pred->next;
pred->next = newNode;
(plist->numOfData)++;
}