#include <stdlib.h>
typedef struct Listnode {
int data;
struct Listnode *link;
} Listnode;
Listnode *new_node()
{
Listnode *pnode;
pnode = (Listnode *) malloc(sizeof(Listnode));
if (!pnode)
return NULL;
pnode->data = 0;
pnode->link = NULL;
return pnode;
}
Listnode *new_node(int data)
{
Listnode *pnode = new_node();
if (! pnode)
return NULL;
pnode->data = data;
return pnode;
}
// phead :헤드 포인터에 대한 포인터
// pnode : 삽입될 노드의 선행 노드
// inode : 삽입될 노드
//
void insert_node(Listnode **phead, Listnode *pnode,Listnode *inode)
{
if (pnode == NULL) {
pnode = *phead;
if (pnode == NULL)
*phead = inode;
else {
while (pnode->link)
pnode = pnode->link;
pnode->link = inode;
}
} else {
pnode->link = inode;
}
}
// phead:헤드 포인터에 대한 포인터
// p:삭제될 노드의 선행 노드
// removed:삭제될 노드
//
int removed_node(Listnode **phead, Listnode *p,Listnode *removed)
{
if (p == NULL) {
if (*phead == removed) // 첫번째 노드와 removed노드가 같은 경우
*phead = (*phead)->link; // 삭제 노드가 첫번째와 같으면
//*phead = removed->link;
else { // 아니면 찾을 노드가 어디 있는지 모를 경우 전체 탐색
p = *phead;
while (p) {
if (p->link == removed) // 삭제할 노드의 선행 노드 탐색
break;
p = p->link;
}
if (!p) // 지울 노드 탐색 실패
return -1;
p->link = removed->link;
}
} else {
p->link = removed->link;
}
free(removed);
return 0;
}
Listnode *gplnHead = NULL;
int main(int argc, char* argv[])
{
Listnode *pnode;
pnode = new_node(1);
insert_node(&gplnHead, NULL, pnode);
Listnode *pnode2;
pnode2 = new_node(2);
insert_node(&gplnHead, pnode, pnode2);
insert_node(&gplnHead, pnode2, new_node(3));
Listnode *pnode3 = pnode2->link;
removed_node(&gplnHead, NULL, pnode); // 님의 프로그램은 이렇게 첫번째를 지정한 것임.
removed_node(&gplnHead, NULL, pnode3); // 그러나 이런 경우 오류발생함.
//removed_node(&gplnHead, pnode, pnode2); //
// ...
return 0;
}
프로그램에서
removed_node(&gplnHead, NULL, pnode); // 님의 프로그램은 이렇게 첫번째를 지정한 것임.
if (*phead == removed) // 첫번째와 헤더가 같으면
*phead=(*phead)->link; // 첫번째를 이렇게 삭제해도 됨.
이런경우
*phead=removed->link; === *phead=(*phead)->link;
와 같은 코드가 됩니다.
그러나 main 예에서
removed_node(&gplnHead, NULL, pnode3); // 3번재 로드를 지정하면
*phead != removed
이렇게 되죠. 이런 경우 다음과 같이 하면 문제가 되죠.
*phead=(*phead)->link;
이런 경우 코드 내에서 탐색과정을 추가 했습니다.
정리하면
질문하신 내용은
removed_node(&gplnHead, NULL, pnode);
처럼 p가 NULL이면 반드시 첫번째 pnode가 노드가 되어야 합니다.
이런식의 규칙을 설정하고 짜여진 코드 입니다.
1. 기본적으로 포인터이므로 ->를 사용하는것이 정석인데요.
*phead=(*phead)->link;
static 변수로 사용한다면
*phead = (**phead).link;
*phead = (*(*phead)).link;
이런 방식도 존재 하내요.
3. phead는 헤더가 있어야 처음 노드를 쉽게 알수 있죠. 위의 메인 처럼 간단하다면 변수가 쉽게 보입니다만, 복잡해 지면 헤더를 찾는 것이 쉽지 않죠.
pnode가 처음 만들어 진것이므로 이것을 초기 노드로 알수는 있느나 함수가 복잡해 지면 그게 그리 쉽지 않습니다. 따라서 Listnode *gplnHead = NULL;를 만들고 이 변수를 사용하면 됩니다.
Listnode *gplnHead = NULL;
Listnode *getHeader()
{
return *gplnHead;
}
int main(int argc, char* argv[])
{
Listnode *pnode;
pnode = new_node(1);
insert_node(&gplnHead, NULL, pnode);
Listnode *pnode2;
pnode2 = new_node(2);
insert_node(&gplnHead, pnode, pnode2);
insert_node(&gplnHead, NULL, new_node(3));
void printList(Listnode *pnode);
printList(getHeader());
// ...
}
void printList(Listnode *pnode)
{
for (;pnode;pnode = pnode->link) {
printf("[0x%08x] %d", pnode, pnode->data);
if (pnode->link)
printf(" -> ");
}
}
실행결과 :
[0x008a9df0] 1 -> [0x008a9e38] 2 -> [0x008a9e80] 3