반응형
[ 구조체(C) 및 클래스(C++) 두가지 방식으로 구현하는 연결 리스트 ]
이 게시물에서 연결 리스트의 삭제, 출력 방식을 통해 기본적인 과정이 끝이 난다.
[ 구조체를 통한 표현 ]
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 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 | #include <stdio.h> #include <malloc.h> #define _CRT_SECURE_NO_WARNINGS #pragma warning(disable:4996) typedef struct Node { int data; Node *next; }node; int main() { node *head = NULL; // 이것은 구조체를 만든 것이 아닌 node 구조체를 가리킬 수 있는 포인터를 만든 것이다. node *tail = NULL; // node node1; 과는 다르다. node *cur = NULL; node *newnode = NULL; node *delnode; node *delnextnode; int value; printf("예외 : 0 입력시 연결 리스트 모든 값이 출력됩니다.\n"); printf("예외 : -1 입력시 연결 리스트 모든 값이 출력됩니다.\n\n"); while (1) { printf("자연수를 입력해 주세요 : "); scanf("%d", &value); // 연결 리스트 값 출력 ( value == 0 ) if (value == 0) { if (head == NULL) { printf("연결 리스트에 값이 존재하지 않습니다.\n"); continue; } else { cur = head; printf("%d ", cur->data); while (cur->next != NULL) // tail->next는 NULL이다. { cur = cur->next; printf("%d ", cur->data); } printf("\n"); } } // 연결 리스트 삭제 과정 ( value == -1 ) else if (value == -1) { if (head == NULL) { printf("삭제할 노드가 없습니다.\n"); continue; } else { delnode = head; delnextnode = head->next; printf("%d를 삭제합니다.\n", delnode->data); free(delnode); while (delnextnode != NULL) { delnode = delnextnode; // delnode는 그다음 노드를 가리키게된다. delnextnode = delnextnode->next; // delnextnode는 delnode 다음 노드를 가리킨다. printf("%d를 삭제합니다.\n", delnode->data); free(delnode); } // 모든 노드를 삭제하면서 free(delnode);를 시행했으니 결국 head가 가리키던 node 및 tail이 가리키던 node가 다 메모리 헤제가 되면서 // head와 tail이 쓰레기 값을 보고 있게된다. 그것을 방지해주기 위해 모두 NULL로 초기화 한다. head = NULL; tail = NULL; cur = NULL; } } else if (value < 1) // 예외처리는 모든 코딩에서 아주 중요하다. { printf("다시 입력해 주세요.\n"); continue; } else { // 노드의 추가 과정 newnode = (node*)malloc(sizeof(node)); newnode->data = value; // 새로 생긴 node에 data를 넣는다. newnode->next = NULL; // 새로 생긴 node의 next 포인터는 NULL을 가리키도록 한다. if (head == NULL) head = newnode; // 만약 head가 아무것도 가리키지 않고있다면 newnode를 가리키게 한다. else tail->next = newnode; // 그렇지 않다면 tail의 next 즉, tail은 node를 가리키니 node의 next가 newnode를 가리키게 한다. tail = newnode; } } return 0; } | Crocus |
[ 클래스를 통한 표현 ]
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 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 | #include <iostream> using namespace std; class node { private: int data; node *next; public: void inputData(int value) { data = value; } void init() { next = NULL; } // next라함은 a -> next(b)에서 a의 next를 의미한다. void doNext(node *newnode) { next = newnode; } // 연결 리스트에 연결된 노드들을 삭제하는 과정 void doDelete(node *delnode, node *delnextnode) { node *tmp = delnode; delnextnode = tmp->next; cout << tmp->data<< "를 삭제합니다." << endl; delete tmp; while (delnextnode != NULL) { tmp = delnextnode; // delnode는 그다음 노드를 가리키게된다. delnextnode = tmp->next; cout << tmp->data<< "를 삭제합니다." << endl; delete tmp; } } // 그 포인터가 가지는 데이터를 가져온다. int getData() { return data; } // 전체 노드를 보기 위한 함수 void see(node *head, node *cur) { cur = head; cout << cur->data << " "; while (cur->next != NULL) // tail->next는 NULL이다. { cur = cur->next; cout << cur->data << " "; } cout << endl; } }; int main() { node *head = NULL; // 이것은 구조체를 만든 것이 아닌 node 구조체를 가리킬 수 있는 포인터를 만든 것이다. node *tail = NULL; // node node1; 과는 다르다. node *cur = NULL; node *newnode = NULL; int value; cout << "예외 : 0 입력시 연결 리스트 모든 값이 출력됩니다." << endl; cout << "예외 : -1 입력시 연결 리스트 모든 값이 출력됩니다.\n" << endl; while (1) { cout << "자연수를 입력해 주세요 : " ; cin >> value; // 연결 리스트 값 출력 ( value == 0 ) if (value == 0) { if (head == NULL) { cout << "연결 리스트에 값이 존재하지 않습니다." << endl; continue; } else { cur->see(head,cur); } } // 연결 리스트 삭제 과정 ( value == -1 ) else if (value == -1) { if (head == NULL) { printf("삭제할 노드가 없습니다.\n"); continue; } else { node *delnode = head; node *delnextnode = NULL; delnode->doDelete(delnode, delnextnode); // 모든 노드를 삭제하면서 free(delnode);를 시행했으니 결국 head가 가리키던 node 및 tail이 가리키던 node가 다 메모리 헤제가 되면서 // head와 tail이 쓰레기 값을 보고 있게된다. 그것을 방지해주기 위해 모두 NULL로 초기화 한다. head = NULL; tail = NULL; cur = NULL; } } else if (value < 1) // 예외처리는 모든 코딩에서 아주 중요하다. { cout << "다시 입력해 주세요."<< endl; continue; } else { // 노드의 추가 과정 newnode = new node; // node의 크기만큼 newnode에 공간을 할당해 준다. newnode->inputData(value); // 새로 생긴 node에 data를 넣는다. newnode->init(); // 새로 생긴 node의 next 포인터는 NULL을 가리키도록 한다. if (head == NULL) head = newnode; // 만약 head가 아무것도 가리키지 않고있다면 newnode를 가리키게 한다. else tail->doNext(newnode); // 그렇지 않다면 tail의 next 즉, tail은 node를 가리키니 node의 next가 newnode를 가리키게 한다. tail = newnode; } } return 0; } | Crocus |
값 출력 과정에서 알고리즘
만약 head가 NULL을 가리킨다면?? 아무것도 없다는 뜻이니 값이 없다는 상태를 출력한다.
그게 아니라면 cur은 head가 가리키는 주소를 가리킨다.
즉, 연결 리스트의 가장 첫 부분을 가리키게 된다.
그다음 그 값을 cur->data(즉, cur이 가리키는 노드의 data 값)을 출력하고
while문의 조건을 확인한다. while문의 조건은 cur이 가리키는 노드의 next가 가리키는 것이 NULL이 아니라면
cur = cur->next;를 취한다.
이것의 의미는 cur이라는 포인터는 (cur = ) cur이 가리키는 노드의 next가 가리키는 주소를 가리켜라 (cur = cur->next;)라는 뜻이다.
그리고 그다음 값을 또 출력하며 조건이 맞지 않을 때 까지 반복한다.
값 삭제 과정에서의 알고리즘
출력과정과 동일한 알고리즘이고 그림을 보고 한번 어떠한 알고리즘으로 돌아가는지 생각해봤으면 한다.
그리고 [ 구조체를 통한 표현 ]부분에서 노드 삭제 과정의
head = NULL, tail = NULL, cur = NULL;의 의미를 한번 생각 해보는 시간을 가졌으면 좋겠다.
반응형
'Applied > 자료구조' 카테고리의 다른 글
이진 트리(Binary Tree) 개념 (1) (0) | 2016.05.09 |
---|---|
원형 연결 리스트(Cricular Linked List) (0) | 2016.05.04 |
자료구조 코딩 시 주의사항 (0) | 2016.05.03 |
연결 리스트(Linked List) 개념 (3) (0) | 2016.05.03 |
연결 리스트(Linked List) 개념 (2) (0) | 2016.05.03 |