Notice
Recent Posts
Recent Comments
Link
| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 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 |
Tags
- fstring
- 코딩테스트
- 얌얌코딩
- 재귀함수
- 미라클모닝
- unreal
- 구조체포인터
- dfs
- 개발
- 탐색기법
- 연산자오버로딩
- 개발자
- 내가해냄
- permutation
- 자료구조
- 코딩
- 게임프로그래밍
- 언리얼
- 구조체
- 커스텀로그
- 게임개발
- c++자료구조
- 백준
- UE5
- 프로그래밍
- TPS
- 링크드리스트
- C++
- 언리얼로그
- 오늘의에러
Archives
- Today
- Total
All is well
[YYBASIC0304/얌얌코딩] AddNode 구현, 링크드리스트 출력 본문
링크드 리스트 시작
// 노드 구조체 정의
struct Node
{
int data; // 데이터 저장
Node* next; // 다음 노드를 가리키는 포인터
};
// 연결 리스트의 헤드와 테일 포인터 선언
Node* head = nullptr; // 리스트의 첫 번째 노드를 가리킴
Node* tail = nullptr; // 리스트의 마지막 노드를 가리킴
- 링크드 리스트를 구현하려면 기본적으로 `head`(첫 번째 노드)와 `tail`(마지막 노드) 가 필요합니다.
- 처음에는 리스트가 비어 있기 때문에 `head` 와 `tail` 모두 `nullptr` 로 초기화하여 가독성을 높이고, 이후 노드가 추가되면서 값을 채워 나갑니다.
링크드 리스트에 노드 추가
#include <iostream>
using namespace std;
// 새로운 노드를 추가하는 함수
void AddNode(int data)
{
if (head == nullptr) // 리스트가 비어 있는 경우 (첫 번째 노드 추가)
{
// 새로운 노드 생성
head = new Node;
head->data = data;
head->next = nullptr; // 다음 노드가 없음을 명시
// tail도 head를 가리키도록 설정 (첫 번째 노드이므로)
tail = head;
}
else // 기존 노드가 존재하는 경우 (새로운 노드를 끝에 추가)
{
// 새로운 노드를 생성하여 현재 tail의 next에 연결
tail->next = new Node;
tail->next->data = data;
tail->next->next = nullptr; // 다음 노드가 없음을 명시
// tail을 새로 추가한 노드로 갱신
tail = tail->next;
}
}
// 리스트가 비어 있는 경우 `(head == nullptr)`
- `head` 가 `nullptr` 인 경우, 즉 리스트가 비어 있다면 새로운 `Node` 객체를 생성하여 `head` 에 추가합니다.
- 이후 `tail`도 `head`를 가리키도록 설정하여 첫 번째 노드가 추가되었음을 나타냅니다.
// 기존 노드가 있는 경우 (head != nullptr)
- 리스트에 이미 노드가 존재한다면, 새로운 노드는 항상 마지막 노드인 `tail` 뒤에 추가됩니다.
- 즉, `tail->next` 에 새로운 `Node` 객체를 생성하고 데이터를 할당합니다.
- 이후 새로 추가한 노드가 마지막 노드가 되므로 `tail` 을 갱신하여 `tail` 이 새로운 노드를 가리키도록 합니다.
- 마지막 노드의 `next` 는 `nullptr` 로 설정하여 다음 노드가 없음을 명확히 합니다.
링크드 리스트 출력 - 순차적으로 모든 노드 탐색
- 링크드 리스트는 배열과 다르게 각 노드가 연결된 형태이므로, 처음(`head`)부터 차례대로 따라가며 데이터를 출력해야 합니다.
- 이를 위해 `while` 문과 `for` 문을 이용한 탐색 방법을 살펴보겠습니다.
// `while` 문을 이용한 출력 (종료 조건: `break` 사용)
- 먼저 무한 루프(`while (true)`)를 사용한 방식입니다.
- 루프 안에서 `nullptr` 여부를 확인한 후 `break` 문으로 탈출하는 방식입니다.
Node* p = head;
while (true)
{
if (p == nullptr) // p가 nullptr이면 반복 종료
break;
cout << p->data << " "; // 현재 노드의 데이터 출력
p = p->next; // 다음 노드로 이동
}
- 실행 흐름은 다음과 같습니다.
- `p` 가 `head` 를 가리키도록 설정
- `nullptr` 을 만날 때까지 `data` 를 출력하고 `next` 로 이동
- `nullptr` 이 되면 `break` 로 루프 종료
- 장점: `break` 를 사용하여 명확하게 종료되는 지점을 표현했습니다.
- 단점: `while (true)` 를 사용하므로 일반적인 조건 기반 루프보다 직관성이 떨어질 수 있습니다.
// `while` 문을 이용한 출력 (보다 직관적인 종료 조건 사용)
- `while (true)` 대신, 루프 조건 자체를 `p != nullptr` 로 설정하는 방식입니다.
- 이 방식이 더 일반적인 연결 리스트 순회 방식이며 가독성이 좋습니다.
Node* p = head;
while (p != nullptr) // p가 nullptr이 아닐 때만 실행
{
cout << p->data << " ";
p = p->next;
}
- 실행 흐름은 다음과 같습니다.
- `p` 가 `head` 를 가리키도록 설정
- `nullptr` 이 아닌 동안 `data` 를 출력하고 `next` 로 이동
- `nullptr` 을 만나면 자동으로 루프 종료
- 장점: 조건 자체가 종료 조건을 포함하고 있어 코드가 직관적입니다.
- 단점: `nullptr` 검사를 매번 수행해야 하지만, 큰 성능 차이는 없습니다.
// `for` 문을 이용한 출력 (더 간결한 방식)
- 위의 `while` 문을 더 간결하게 표현한 방법입니다.
- 반복 변수 `p` 를 선언하고, `nullptr` 이 될 때까지 반복합니다.
for (Node* p = head; p != nullptr; p = p->next)
{
cout << p->data << " ";
}
- 장점: 반복문에 초기화, 조건 검사, 증감식이 한 줄로 정리되어 깔끔합니다.
- 단점: `while` 문에 비해 익숙하지 않은 사람에게는 조금 낯설 수 있습니다.
최종 코드
#include <iostream>
using namespace std;
// 노드 구조체 정의
struct Node
{
int data; // 데이터 저장
Node* next; // 다음 노드를 가리키는 포인터
};
// 연결 리스트의 헤드와 테일 포인터 선언
Node* head = nullptr; // 리스트의 첫 번째 노드를 가리킴
Node* tail = nullptr; // 리스트의 마지막 노드를 가리킴
// 새로운 노드를 추가하는 함수
void AddNode(int data)
{
if (head == nullptr) // 리스트가 비어 있는 경우 (첫 번째 노드 추가)
{
// 새로운 노드 생성
head = new Node;
head->data = data;
head->next = nullptr; // 다음 노드가 없음을 명시
// tail도 head를 가리키도록 설정 (첫 번째 노드이므로)
tail = head;
}
else // 기존 노드가 존재하는 경우 (새로운 노드를 끝에 추가)
{
// 새로운 노드를 생성하여 현재 tail의 next에 연결
tail->next = new Node;
tail->next->data = data;
tail->next->next = nullptr; // 다음 노드가 없음을 명시
// tail을 새로 추가한 노드로 갱신
tail = tail->next;
}
}
// 연결 리스트의 노드들을 출력하는 함수
void PrintNode()
{
// p 포인터를 사용하여 head를 이동시키며 출력 (원본 head 유지)
Node* p = head;
// while 문을 이용한 출력 (break 사용)
cout << "Linked List with 'while' : ";
while (true)
{
if(p == nullptr) // p가 nullptr이면 종료
break;
cout << p->data << " "; // 현재 노드의 데이터 출력
p = p->next; // 다음 노드로 이동
}
cout << "\\n";
// while 문을 이용한 출력 (더 직관적인 조건 사용)
p = head;
cout << "Linked List with 'while' : ";
while(p != nullptr) // p가 nullptr이 아닐 때 반복
{
cout << p->data << " "; // 현재 노드의 데이터 출력
p = p->next; // 다음 노드로 이동
}
cout << "\\n";
// for 문을 이용한 출력 (간결한 표현)
cout << "Linked List with 'for' : ";
for (Node* p = head; p != nullptr; p = p->next) // p를 head에서 시작해 nullptr이 아닐 때까지 이동
cout << p->data << " "; // 현재 노드의 데이터 출력
cout << "\\n";
}
int main()
{
// 노드 추가
AddNode(3);
AddNode(4);
AddNode(5);
// 연결 리스트 출력
PrintNode();
return 0;
}
// 디버깅

// 실행 결과

'C++ > YYBASIC' 카테고리의 다른 글
| [YYBASIC0306/얌얌코딩] 링크드 리스트 클래스 만들기 (0) | 2025.03.07 |
|---|---|
| [YYBASIC0305/얌얌코딩] C++ Template(템플릿) (0) | 2025.03.05 |
| [YYBASIC0303/얌얌코딩] 링크드 리스트 설명, 동적 할당 설명 (0) | 2025.02.16 |
| [YYBASIC0302/얌얌코딩] 구조체 포인터 연결하기 (0) | 2025.02.09 |
| [YYBASIC0301/얌얌코딩] 포인터 타입변수, 구조체 포인터 (1) | 2025.02.09 |