๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
์•Œ๊ณ ๋ฆฌ์ฆ˜/์ž๋ฃŒ๊ตฌ์กฐ

4. STL ๋”ฐ๋ผ์žก๊ธฐ - ์ด์ค‘ ์—ฐ๊ฒฐ ๋ฆฌ์ŠคํŠธ (Doubly Linked List) ๊ตฌํ˜„

by ๐Ÿณ Laboon 2024. 2. 7.
์ด์ค‘ ์—ฐ๊ฒฐ ๋ฆฌ์ŠคํŠธ๋ž€ ?

 

์—ฌ๊ธฐ์„œ ์—ฐ๊ฒฐ ๋ฆฌ์ŠคํŠธ์— ๋Œ€ํ•œ ๊ฐœ๋…์„ ์•Œ๊ฒŒ ๋˜์—ˆ๊ณ  

์—ฌ๊ธฐ์„œ ๋‹จ์ˆœ ์—ฐ๊ฒฐ ๋ฆฌ์ŠคํŠธ๋ฅผ ๊ตฌํ˜„ํ•ด๋ณด์•˜๋‹ค.

 

๋˜, ์•ž์„  ํฌ์ŠคํŒ…์—์„œ ์—ฐ๊ฒฐ์— ๋Œ€ํ•œ ๋ฐฉ๋ฒ•์„ ๋งํ–ˆ๋Š”๋ฐ '์ด์ค‘ ์—ฐ๊ฒฐ ๋ฆฌ์ŠคํŠธ' ๋Š” ์–‘๋ฐฉํ–ฅ(์ด์ค‘)์œผ๋กœ ๊ตฌ์„ฑ๋œ ์ž๋ฃŒ๊ตฌ์กฐ์ด๋‹ค.

์ฆ‰, ์‹ฑ๊ธ€ ์—ฐ๊ฒฐ ๋ฆฌ์ŠคํŠธ๋Š” ์ฝ”์Šค ์—ฌํ–‰์ด๋ผ๋ฉด ์ด์ค‘ ์—ฐ๊ฒฐ ๋ฆฌ์ŠคํŠธ๋Š” ์ž์œ  ์—ฌํ–‰์ด๋‹ค.

์ด์— ๋Œ€ํ•ด์„  ๋‚ด๊ฐ€ ์ƒ๊ฐํ•œ ์˜ˆ์‹œ์ด๊ธฐ ๋•Œ๋ฌธ์— ํ•œ ๋ฒˆ ์ƒ๊ฐํ•ด๋ณด๊ณ  ๋น„์Šทํ•œ ์˜ˆ์‹œ๋ฅผ ์ฐพ์•„์„œ ๋ณธ์ธ๋งŒ์˜ ๊ฐœ๋…์œผ๋กœ ์ดํ•ดํ•˜๊ธธ..

 

์ด๋ฒˆ STL ๋”ฐ๋ผ์žก๊ธฐ ํฌ์ŠคํŠธ๋Š” standard library์ธ list๋ฅผ ๋งŒ๋“ค์–ด๋ณด๊ฒ ๋‹ค.

๋จผ์ €, list์— ์–ด๋–ค ๊ธฐ๋Šฅ์ด ์žˆ๋Š”์ง€ ํ•œ ๋ฒˆ ์•Œ์•„๋ณด์ž.

 

์šฐ๋ฆฌ๋Š” STL list์— ์–ด๋–ค ๊ธฐ๋Šฅ์ด ๊ตฌํ˜„๋˜์–ด์žˆ๋Š”์ง€ ํŒŒ์•…ํ•œ ๋’ค์— ์ด๋ฅผ ์ •๋ฆฌํ•  ๊ฒƒ์ด๋‹ค.

๊นƒํ—ˆ๋ธŒ ์ด์Šˆ์— ๊ตฌํ˜„ํ•  ๋‚ด์šฉ์„ ์ž‘์„ฑํ•˜๊ณ  ์ด๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ ๋ ˆํŒŒ์ง€ํ† ๋ฆฌ์— ์ €์žฅํ•  ๊ฒƒ์ด๋‹ค.

list์˜ ๋ชจ๋“  ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•˜์ง€๋Š” ์•Š๊ณ  '์ด์ค‘ ์—ฐ๊ฒฐ ๋ฆฌ์ŠคํŠธ'์˜ ํ•ต์‹ฌ ๊ธฐ๋Šฅ๊ณผ ์ถ”๊ฐ€ํ•˜๊ณ  ์‹ถ์€ ์ž‘์—…์— ๋Œ€ํ•ด ์ˆ˜ํ–‰ํ•  ๊ฒƒ์ด๋‹ค.

 

๊นƒํ—ˆ๋ธŒ Double Linked List ๊ตฌํ˜„ํ•  ๊ธฐ๋Šฅ ๋ชฉ๋ก ์ •๋ฆฌ


์ด์ค‘ ์—ฐ๊ฒฐ ๋ฆฌ์ŠคํŠธ์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์งˆ ๋…ธ๋“œ ๋งŒ๋“ค๊ธฐ DoubleLinkedList.h

 

template <typename T>
class Node {
public:
    Node(T data);
    
    T getData() const;
    Node* getNext() const;
    Node* getPrev() const;

    void setNext(Node* node);
    void setPrev(Node* node);

private:
    T data;
    Node* next;
    Node* prev;
};

 

์šฐ๋ฆฌ๊ฐ€ ๊ฐ€์งˆ ๋‚ด์šฉ์€ ์ฝ”๋“œ์— ์ž‘์„ฑ๋œ ๊ทธ๋Œ€๋กœ์ด๋‹ค.

๊ฐ ๋…ธ๋“œ๋Š” ๋ฐ์ดํ„ฐ์™€ ์—ฐ๊ฒฐ๋  ๋ฐ์ดํ„ฐ๋ฅผ ์—ฐ๊ฒฐํ•  ์„ ์„ ๋งŒ๋“ค์–ด์•ผ ํ•œ๋‹ค.

data - ๊ฐ’, next - ๋‹ค์Œ ๋…ธ๋“œ, prev - ์ด์ „ ๋…ธ๋“œ

 

ํ•ด๋‹น portotype์— ๋Œ€ํ•œ ์ž‘์„ฑ๋ฒ•์€ ์ƒ๋žตํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

ํ•œ ๋ฒˆ, ์ง์ ‘ ๊ตฌํ˜„ํ•ด๋ณด๊ณ  ๋ชจ๋ฅด๊ฒ ์œผ๋ฉด ์ œ ๊นƒํ—ˆ๋ธŒ์—์„œ ์ •๋‹ต์„ ๋ณด๋Š” ๊ฒƒ์„ ์ถ”์ฒœํ•ฉ๋‹ˆ๋‹ค.

โ€ป ์•Œ๋ฉด ์ข‹์€ ๊ฐœ๋…

1. const keyword

get ๋ฉ”์„œ๋“œ์— ๋Œ€ํ•ด ์ž์„ธํžˆ ๋ณด์ž. ๋งจ ๋์— const๊ฐ€ ๋‹ฌ๋ ค์žˆ๋‹ค.

๋ณ€์ˆ˜๋ฅผ ์„ ์–ธํ•˜๊ธฐ ์ „์— const ๋ณ€์ˆ˜๋ช… = ๊ฐ’; ์„ ์ทจํ•˜๋ฉด ํ•ด๋‹น ๋ณ€์ˆ˜๋Š” ์ˆ˜์ •ํ•  ์ˆ˜ ์—†๋Š” '์ƒ์ˆ˜'๊ฐ€ ๋œ๋‹ค.

์ฆ‰, const๋Š” ์ •๋ณด์˜ ๋ฌด๊ฒฐ์„ฑ(๋ณ€ํ•˜์ง€ ์•Š๋Š” ์„ฑ์งˆ)์„ ์ง€์ผœ์ฃผ๋Š” ํ‚ค์›Œ๋“œ์ž…๋‹ˆ๋‹ค.

ํ•ด๋‹น ๋ฉ”์„œ๋“œ๋Š” ์šฐ๋ฆฌ๊ฐ€ ์‚ฌ์šฉํ•˜๋Š” ๋ฉค๋ฒ„ ๋ณ€์ˆ˜์ธ data์™€ next, prev์— ๋Œ€ํ•ด ๋ฌด๊ฒฐ์„ฑ์„ ๋ณด์žฅํ•ด์ค๋‹ˆ๋‹ค.

๋‚ด๋ถ€์—์„œ ์ˆ˜์ •๋˜์–ด ์ด์ƒํ•œ ๊ฐ’์ด ์ „๋‹ฌ๋˜๋Š” ๊ฒƒ์„ ๋ง‰์•„์ฃผ์ฃ .

 

2. private access modifier

์šฐ๋ฆฌ๋Š” ๋ฉค๋ฒ„ ๋ณ€์ˆ˜์— ๋Œ€ํ•ด ์™ธ๋ถ€์—์„œ ์ ‘๊ทผํ•  ์ˆ˜ ์—†๋„๋ก ์บก์Аํ™”(encapsulate)๋ฅผ ํ–ˆ์Šต๋‹ˆ๋‹ค.

์ •๋ณด์€๋‹‰์„ ํ†ตํ•ด ๋ฐ์ดํ„ฐ์˜ ๋ฌด๊ฒฐ์„ฑ, ์‹ ๋ขฐ์„ฑ์„ ๋ณด์žฅํ•ฉ๋‹ˆ๋‹ค.

 

๋…ธ๋“œ๋ฅผ ๋งŒ๋“ค์—ˆ์œผ๋ฉด ํ•ด๋‹น ๋…ธ๋“œ๋กœ ์ด์ค‘ ์—ฐ๊ฒฐ ๋ฆฌ์ŠคํŠธ๋ฅผ ์ƒ์„ฑํ•˜๊ธฐ DoublyLinkedList.h
#pragma once
#include "DoublyLinkedListNode.h"

// Prototype
template <typename T>
class DoublyLinkedList {
public:
    DoublyLinkedList();

	// ๋ฐ˜๋ณต์ž 
    class iterator {
    public:
        iterator(Node<T>* node, bool& isReverse);

        T operator*() const;
        iterator& operator++(int);
        iterator& operator--(int);
        bool operator!=(const iterator& other) const;

    private:
        Node<T>* it;
        bool isReverse;
        
        Node<T>* getNode();
        friend class DoublyLinkedList<T>;
    };
    
    // Function
	iterator begin();
    iterator end();
	iterator rbegin();
	iterator rend();
	iterator erase(iterator it);

    void push_front(const T& value);
    void push_back(const T& value);
    void pop_front();
    void pop_back();
    void insert(iterator it, const T& value);
    void reverse();
    
    T front() const;
    T back() const;

    int getSize() const;

private:
    Node<T>* head;
    Node<T>* tail;
    int size;
    bool isReverse;
    //void insert_reverse(iterator it, const T& value);
};

 

๊นƒ ์ด์Šˆ์— ์ž‘์„ฑํ•œ๋Œ€๋กœ ๋จผ์ €, ๊ตฌํ˜„ํ•  ๋ชฉ๋ก์„ ์ƒ์„ฑํ–ˆ์Šต๋‹ˆ๋‹ค.

๊ฐ ๊ธฐ๋Šฅ์— ๋Œ€ํ•ด์„œ๋Š” ๋ช‡ ๋ช‡ ๋ถ€๋ถ„๋งŒ ์ž‘์„ฑํ•˜๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

๋‚จ์€ ๋ถ€๋ถ„์€ ๊ฐ์ž ์ž‘์„ฑํ•ด๋ณด๊ณ  ๋ชจ๋ฅด๊ฒ ์œผ๋ฉด ์ œ ๊นƒํ—ˆ๋ธŒ์—์„œ ํ™•์ธํ•˜์‹œ๋ฉด ๋˜๊ฒ ์Šต๋‹ˆ๋‹ค.

๊นƒ ํ—ˆ๋ธŒ ๋งํฌ๋Š” ์ œ์ผ ํ•˜๋‹จ์— ๊ณต๊ฐœํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

 

โ€ป ์•Œ๋ฉด ์ข‹์€ ๊ฐœ๋…

1. head์™€ tail

์ด์ค‘ ์—ฐ๊ฒฐ ๋ฆฌ์ŠคํŠธ๋Š” ์‹œ์ž‘ ๋…ธ๋“œ์™€ ๋ ๋…ธ๋“œ๋กœ ๊ตฌ์„ฑ๋˜์–ด ์žˆ์œผ๋ฉฐ ์‹œ์ž‘๋…ธ๋“œ ๋ถ€ํ„ฐ ๋ ๋…ธ๋“œ๊นŒ์ง€ ์—ฐ๊ฒฐ๋˜์–ด์žˆ๋‹ค..

๋‹จ์ผ ์—ฐ๊ฒฐ ๋ฆฌ์ŠคํŠธ์—์„œ๋Š” ๋‹จ๋ฐฉํ–ฅ์œผ๋กœ๋งŒ ํƒ์ƒ‰์„ ์ง„ํ–‰ํ•  ์ˆ˜ ์žˆ์—ˆ์ง€๋งŒ,

์ด์ค‘ ์—ฐ๊ฒฐ ๋ฆฌ์ŠคํŠธ์—์„œ๋Š” ์–‘๋ฐฉํ–ฅ์œผ๋กœ ํƒ์ƒ‰์„ ์ง„ํ–‰ํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ tail๋ถ€ํ„ฐ head๊นŒ์ง€๋„ ํƒ์ƒ‰์„ ์ง„ํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค.

 

2. iterator ๋‚ด๋ถ€ ํด๋ž˜์Šค

์šฐ๋ฆฌ๊ฐ€ STL์„ ์‚ฌ์šฉํ•˜๋‹ค๋ณด๋ฉด ์•„๋ž˜์™€ ๊ฐ™์€ ์ฝ”๋“œ๋ฅผ ์ ‘ํ•ด๋ณธ ์ ์ด ์žˆ์„ ๊ฒƒ์ด๋‹ค.

list<int> lis;

lis.push_back(1);
lis.push_back(2);
lis.push_back(3);

// ์š”๊ธฐ ์š”๊ธฐ ์ž˜๋ณด์„ธ์—ฐ
for(auto it = lis.begin(); it != lis.end(); it++) {  
	cout << *it << ' ';
}

it์ด๋ผ๊ณ  ํ•˜๋ฉด ๋ฌด์–ธ๊ฐ€๋ฅผ ์ง€์นญํ•˜๋Š” it์ด ์•„๋‹ˆ๋‹ค.

iterator์˜ ์•ฝ์ž์ด๋ฉฐ auto๋กœ ์ž๋™ ์บ์ŠคํŒ…๋˜๋Š” ์ € ๋ถ€๋ถ„์€ ์‚ฌ์‹ค 'list<int>::iterator' ๊ฐ€ ๋“ค์–ด๊ฐ€๋Š” ๊ฒƒ์ด ์˜ณ๋‹ค.

์—ฌ๊ธฐ์„œ '::' ๋Š” namespace์— ์ ‘๊ทผํ•˜๋Š” ๊ฐœ๋…์œผ๋กœ list ๋‚ด๋ถ€์— iterator๋ผ๋Š” ๋‚ด๋ถ€ ํด๋ž˜์Šค๊ฐ€ ์กด์žฌํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

๊ทธ๋Ÿผ ์šฐ๋ฆฌ๋Š” ์ด iterator๋ฅผ ๊ตฌํ˜„ํ•˜๊ธฐ ์œ„ํ•ด์„œ ๋‚ด๋ถ€ ํด๋ž˜์Šค๋ฅผ ์ƒ์„ฑํ•ด์•ผ ํ•œ๋‹ค.

 

์ตœ์ข…์ ์œผ๋กœ DoublyLinkedList<int>::iterator ๋กœ ๋ฐ์ดํ„ฐ์— ๋Œ€ํ•œ '๋ฐ˜๋ณต์ž'๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ๋‹ค.

 

3. operator keyword

operator ํ‚ค์›Œ๋“œ๋Š” ์šฐ๋ฆฌ๊ฐ€ ์‚ฌ์šฉํ•˜๋Š” +=, ++, * ์™€ ๊ฐ™์€ ์—ฐ์‚ฐ๊ธฐํ˜ธ๋ฅผ ์˜๋ฏธํ•œ๋‹ค.

์šฐ๋ฆฌ๋Š” ํด๋ž˜์Šค์—์„œ ์—ฐ์‚ฐ๊ธฐํ˜ธ์— ๋Œ€ํ•ด์„œ๋„ ์ง์ ‘ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.

๊ทธ ์ค‘ operator++(int) ์— ๋Œ€ํ•ด ์•Œ์•„์•ผํ•œ๋‹ค. ๋”ฑ ๋ณด๋ฉด ํ›„์œ„ ์—ฐ์‚ฐ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ ๊ฐ™์€๋ฐ int๊ฐ€ ์ž‘์„ฑ๋˜์–ด์žˆ๋‹ค.

 

์‹ค์ œ๋กœ operator++(int)๋Š” ํ›„์œ„์—ฐ์‚ฐ์„ ์ž‘์„ฑํ•˜๋Š”๊ฒŒ ๋งž๊ณ , ์ „์œ„ ์—ฐ์‚ฐ์€ ++operator๊ฐ€ ์•„๋‹ˆ๋ผ

operator++() ์ด๊ธฐ ๋•Œ๋ฌธ์— ์ด๋ฅผ ๊ตฌ๋ถ„ํ•˜๊ธฐ ์œ„ํ•ด int๋ฅผ ์ž‘์„ฑํ–ˆ์Šต๋‹ˆ๋‹ค.

 

operator ํ‚ค์›Œ๋“œ๋กœ ์—ฐ์‚ฐ๊ธฐํ˜ธ๋ฅผ ์žฌ์กฐ์ •ํ•˜๊ฒ ๋‹ค๋Š” ๋œป์ด ๋˜์–ด์•ผํ•˜๋Š”๋ฐ ++์ด๋ผ๋Š” ํ‚ค์›Œ๋“œ๊ฐ€ ๋จผ์ € ๋‚˜์˜ค๋ฉด ์—ฐ์‚ฐ์„ ํ•˜๋ ค๊ณ  ํ•˜๊ฒ ์ฃ ? ์—ฐ์‚ฐ์„ ์ˆ˜ํ–‰ํ•œ ๋’ค operator ํ‚ค์›Œ๋“œ์— ์ ‘๊ทผํ•ด๋ดค์ž ์‹ฌ๋ณผ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•  ๊ฒƒ ์ž…๋‹ˆ๋‹ค.

 

4. isReverse ๋ณ€์ˆ˜

SLT list๋ฅผ ์‚ฌ์šฉํ•ด๋ณด์‹  ๋ถ„๋“ค ๊ณต๊ฐํ•˜์‹ค ๊ฒƒ ๊ฐ™์€๋ฐ iterator๋ฅผ ๊ฐ€์ ธ์˜ค๊ณ  reverse๋ฅผ ํ•˜๋ฉด ์–ด๋–ป๊ฒŒ ๋˜์ง€?

	list<int> l;
	l.push_back(1); // null <- 1 -> null
	l.push_back(2); // null <- 1 <-> 2 -> null
	l.push_back(3); // null <- 1 <-> 2 <-> 3 -> null
	
	auto it = l.begin(); // null <- 1(it) <-> 2 <-> 3 -> null
    l.reverse(); // null <- 3 <-> 2 <-> 1(it) -> null

1. ๋งจ ์•ž์—์„œ ๊ฐ€์ ธ์˜จ ์ •๋ณด๋ฅผ reverse ํ•˜๊ฒŒ ๋œ๋‹ค๋ฉด ํ•ด๋‹น iterator๋Š” ๋งจ ๋งˆ์ง€๋ง‰์„ ๊ฐ€๋ฅดํ‚ค๋Š”์ง€?

2. ์—ฌ์ „ํžˆ ๋งจ ์•ž์— ๋…€์„์„ ๊ฐ€๋ฅดํ‚ค๋Š”์ง€?

3. ๋งจ ๋งˆ์ง€๋ง‰์„ ๊ฐ€๋ฅดํ‚จ๋‹ค๊ณ  ํ•˜๋”๋ผ๋„ ++ ์—ฐ์‚ฐ์„ ํ•˜๋ฉด null๋กœ ์ด๋™ํ•˜๋Š”์ง€? 2๋กœ ์ด๋™ํ•˜๋Š”์ง€?

๊ถ๊ธˆํ•œ ๋‚ด์šฉ ์•„๋‹Œ๊ฐ€์š”??

 

์ €๋Š” reverse()๋ฅผ ํ•˜๊ธฐ์ „์˜ iterator๋Š” ๋‚ด๋ถ€ ํด๋ž˜์Šค ์ด๋ฆ„์„ iterator๋กœ ์‚ฌ์šฉํ•˜๊ณ 

reverse์— ๊ด€ํ•œ๊ฑด iterator2๋‚˜ reverseIterator ์ฒ˜๋Ÿผ reverse ์ „, ํ›„์˜ iterator๋“ค์„ ๊ด€๋ฆฌํ•˜๋Š” ํด๋ž˜์Šค๊ฐ€ ๋”ฐ๋กœ ์žˆ์„ ๊ฒƒ์ด๋ผ๊ณ  ์ƒ๊ฐํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ list์—์„œ ์ง์ ‘ ํ…Œ์ŠคํŠธ ํ•ด๋ดค์Šต๋‹ˆ๋‹ค.

list<int> l = {1, 2, 3};

list<int>::iterator it = l.begin(); // 1์„ ๊ฐ€๋ฅดํ‚ด
it++; // ๋ฌธ์ œ ์—†์Œ 2๋ฅผ ๊ฐ€๋ฅดํ‚ด

l.reverse();
cout << *it; // ์—ฌ์ „ํžˆ 2๋ฅผ ๊ฐ€๋ฅดํ‚ด
// ์—ฌ๊ธฐ์„œ it์€ ๋ฐ์ดํ„ฐ ๊ทธ ์ž์ฒด์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ๊ณ„์† ๊ฐ€์ง€๊ณ  ์žˆ์Œ์„ ์•Ž

cout << *(++it); // 1์„ ๊ฐ€๋ฅดํ‚ด !!!
// reverse ์ „์— ๋ฝ‘์€ iter์ž„.
// ํ•˜์ง€๋งŒ ++ ์—ฐ์‚ฐ์„ ํ•˜๋‹ˆ reverse ๊ฒฐ๊ณผ๊ฐ€ ์ ์šฉ ๋จ
// reverse๋ฅผ ํ•˜์ง€ ์•Š์•˜๋‹ค๋ฉด ์›๋ž˜ 3์„ ๊ฐ€๋ฅด์ผœ์•ผ ํ•จ!!!

// ์—ฌ๊ธฐ์„œ it๋„ reverse๊ฐ€ ๋˜๋Š”๊ตฌ๋‚˜๋ฅผ ์•Œ๊ฒŒ ๋จ.
// ์˜๋ฌธ, ๊ทธ๋Ÿผ reverse ์ „, ํ›„์˜ ๋‚ด๋ถ€ ํด๋ž˜์Šค iterator๊ฐ€ ๊ฐ™์€๊ฐ€?

list<int>::iterator reverseIt = it.begin(); // 3์„ ๊ฐ€๋ฅดํ‚ด
// reverse ๋˜์—ˆ์Œ์—๋„ ๊ฐ™์€ iterator๋ฅผ ๋ฐ˜ํ™˜ํ•จ.

๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ •๋ณด๋กœ ๊ฐ™์€ iterator๋ฅผ ํ†ตํ•ด์„œ reverse ๋˜์—ˆ๋Š”์ง€ ๋‚ด๋ถ€์ ์œผ๋กœ ํ†ต์‹ ํ•˜๊ณ  ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ–ˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋ž˜์„œ ์ƒ์„ฑ์ž์— ๋Œ€ํ•œ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ์ฃผ์†Œ๊ฐ’์„ ์ „๋‹ฌํ•ด์ฃผ๊ณ  isReverse ๊ฐ’์— ๋”ฐ๋ผ reverse๋œ ๊ฒฐ๊ณผ๋ฅผ ์ค˜์•ผ๊ฒ ๋‹ค! ๋ผ๋Š” ์ ‘๊ทผ~

 

6. friend access modifier

private์œผ๋กœ ์„ค์ •ํ•œ ๋ฉค๋ฒ„ ๋ณ€์ˆ˜ ๋ฐ ๋ฉ”์„œ๋“œ๋Š” ์™ธ๋ถ€์—์„œ ์ ‘๊ทผํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

freind ์ ‘๊ทผ์ œํ•œ์ž๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์นœ๊ตฌ๋กœ ์ธ์ •ํ•˜๊ณ  ๋‚ด๋ถ€ ์ •๋ณด์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ด์ค๋‹ˆ๋‹ค.

์ƒ์† ๊ฐœ๋…์—์„œ ์‚ฌ์šฉ๋˜๋Š” protected์™€๋Š” ๋‹ค๋ฆ…๋‹ˆ๋‹ค.

 

ํ•ด๋‹น API์—๋Š” erase ๋ฉ”์„œ๋“œ๋ฅผ ๊ตฌํ˜„ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋ผ๋ฉด friend ์ ‘๊ทผ์ œํ•œ์ž๊ฐ€ ํ•„์š”ํ•˜๋‹ค๊ณ  ์ƒ๊ฐํ•ด์„œ ์ถ”๊ฐ€ํ–ˆ์Šต๋‹ˆ๋‹ค.

(์‚ฌ์‹ค ๋งŒ๋“ค๋‹ค๋ณด๋‹ˆ friend ์—†์ด๋Š” ์•ˆ๋  ๊ฒƒ ๊ฐ™์•„์„œ ์ถ”๊ฐ€ํ•จ..)


 

iterator ๊ตฌํ˜„
template <typename T>
DoublyLinkedList<T>::iterator::iterator(Node<T>* node, bool& isReverse) : it(node), isReverse(isReverse) {}

template <typename T>
T DoublyLinkedList<T>::iterator::operator*() const {
    return it->getData();
}

template <typename T>
typename DoublyLinkedList<T>::iterator& DoublyLinkedList<T>::iterator::operator++(int) {
    if(isReverse) {
		it = it -> getPrev();
	} else {
		it = it->getNext();	
	}
    return *this;
}

template <typename T>
bool DoublyLinkedList<T>::iterator::operator!=(const iterator& other) const {
    return it != other.it;
}

 

 

์ƒ์„ฑ์ž, ํฌ์ธํ„ฐ, ํ›„์œ„์—ฐ์‚ฐ, ๋น„๊ต์—ฐ์‚ฐ์— ๋Œ€ํ•œ ์ฝ”๋“œ์ด๋‹ค.

๊ธฐ๋Šฅ ๋‹จ์œ„๋กœ ๋„ˆ๋ฌด ์˜ˆ์˜๊ฒŒ ์ž˜ ์ž‘์„ฑํ•œ ๊ฒƒ ๊ฐ™์•„์„œ ใ…Žใ…Ž.. ์„ค๋ช…์€ ์ƒ๋žต

 

DoublyLinkedList Method
template <typename T>
DoublyLinkedList<T>::DoublyLinkedList() : head(nullptr), tail(nullptr), size(0), isReverse(false) {}

template <typename T>
typename DoublyLinkedList<T>::iterator DoublyLinkedList<T>::begin() {
	return iterator(head, this -> isReverse);
}

template <typename T>
typename DoublyLinkedList<T>::iterator DoublyLinkedList<T>::end() {
	return iterator(nullptr, this -> isReverse);
}

template <typename T>
void DoublyLinkedList<T>::push_back(const T& value) {
	Node<T>* node = new Node<T>(value);
	if (head == nullptr) {
		head = node;
		tail = node;
	} else {
		tail -> setNext(node);
		node -> setPrev(tail);
		tail = node;
	}
	size++;
}

๊ฐ€์žฅ ๊ธฐ๋ณธ์ ์ธ ๊ธฐ๋Šฅ์ธ push_back๊ณผ ํƒ์ƒ‰์„ ์œ„ํ•œ, begin(), end()๋ฅผ ์ถ”๊ฐ€ํ•ด๋ณด์•˜๋‹ค.

 

ํ™œ์šฉํ•˜๊ธฐ
/*
	authored by dot
    https://dev-dot.tistory.com
*/
#include <list>
#include <iostream> 
#include "DoublyLinkedList.h"

using namespace std;

int main() {
	DoublyLinkedList<int> customList;
	
	printf("push_back : 40, 50, 60\n");
	customList.push_back(40);
	customList.push_back(50);
	customList.push_back(60);
	
	printf("push_front : 30, 20, 10\n");
	customList.push_front(30);
	customList.push_front(20);
	customList.push_front(10);
	
	printf("pop_front\n");
	customList.pop_front();

	printf("pop_back\n\n");
	customList.pop_back();
	
	printf("begin() and rbegin() before reverse\n");
	printf("begin val : %d, rbegin val : %d\n", *(customList.begin()), *(customList.rbegin()));
	printf("front() and back() before reverse\n");
	printf("front : %d, back : %d\n", customList.front(), customList.back());
	
	printf("Forward Travel\n");
	for(auto it = customList.begin(); it != customList.end(); it++) {
		cout << *it << ' ';
	}
	cout << "\n\n";
	
	customList.reverse();
	
	printf("begin() and rbegin() after reverse\n");
	printf("begin val : %d, rbegin val : %d\n", *(customList.begin()), *(customList.rbegin()));
	printf("front() and back() before reverse\n");
	printf("front : %d, back : %d\n", customList.front(), customList.back());
	
	printf("Reversed Travel\n");
	for(auto it = customList.begin(); it != customList.end(); it++) {
		cout << *it << ' ';
	}
	cout << "\n\n";

	DoublyLinkedList<int>::iterator it = customList.begin();
	it++;
	printf("value of it : %d\n", *it);
	
	it = customList.erase(it);
	printf("value of it after erase : %d\n", *it);
	
	it = customList.erase(customList.begin());
	printf("value of it after erase front : %d\n", *it);
	
	it++;
	it = customList.erase(it);
	printf("value of it after erase back : %d\n", *it);
	
	printf("Travel after erase\n");
	for(auto it = customList.begin(); it != customList.end(); it++) {
		cout << *it << ' ';
	}
	cout << "\n\n";
	
	customList.insert(it, 20);
	printf("Travel after insert\n");
	for(auto it = customList.begin(); it != customList.end(); it++) {
		cout << *it << ' ';
	}
	cout << "\n\n";
	
	return 0;
}
์‹คํ–‰ ๊ฒฐ๊ณผ

๋ชจ๋“  ๊ธฐ๋Šฅ์ด ์ž‘์„ฑ๋œ ์ฝ”๋“œ๋Š” Github ๋ ˆํŒŒ์ง€ํ† ๋ฆฌ์— push ํ•  ์˜ˆ์ •์ž…๋‹ˆ๋‹ค.

๋‹ค๋ฅธ ๊ธฐ๋Šฅ๋“ค์€ ํ•œ ๋ฒˆ ์ง์ ‘ ๊ตฌํ˜„ํ•ด๋ณด์‹œ๋Š”๊ฑธ ์ถ”์ฒœ๋“œ๋ฆฝ๋‹ˆ๋‹ค.

 

์•„! ๊ทธ๋ฆฌ๊ณ  ํ˜น์‹œ ์ด๊ธ€์„ ๋ณด์‹œ๋Š” ๋ถ„๋“ค ์ค‘ Readme.md๋ฅผ ๊พธ๋ฉฐ์ฃผ์‹œ๊ฑฐ๋‚˜...

๋ถ€์กฑํ•œ ๋ฉ”์„œ๋“œ๋ฅผ ์ฑ„์›Œ์„œ PR ํ•ด์ฃผ์‹œ๋ฉด ์ •๋ง ๊ฐ์‚ฌํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค!!!

 

์ž‘์„ฑํ•ด๋ณด๋ฉด ๋„์›€์ด ๋˜๋Š” Method

 

reverse, erase, push_front ๋Š” ํ•„์ˆ˜๋กœ ํ•ด๋ณด์‹œ๋ฉด ์ข‹๊ฒ ์Šต๋‹ˆ๋‹ค.

erase์˜ ๊ฒฝ์šฐ ์ฃผ์˜ํ•ด์•ผ ํ•  ์ ์ด ๋งŽ์Šต๋‹ˆ๋‹ค!

 

๊นƒํ—ˆ๋ธŒ ์ด์Šˆ ๋ฐ ๋ ˆํŒŒ์ง€ํ† ๋ฆฌ, ๋ ˆํผ๋Ÿฐ์Šค

 

๊นƒํ—ˆ๋ธŒ ์ด์Šˆ : https://github.com/jihwankim128/datastructure/issues/4

 

์ด์ค‘ ์—ฐ๊ฒฐ ๋ฆฌ์ŠคํŠธ (Doubly Linked List) · Issue #4 · jihwankim128/datastructure

https://cplusplus.com/reference/list/list/ STL list ๋”ฐ๋ผ์žก๊ธฐ iterators: begin end rbegin rend Capacity: empty size elemental : front back modifiers: push_back push_front pop_back pop_front insert erase...

github.com

 

๊นƒํ—ˆ๋ธŒ ๋ ˆํŒŒ์ง€ํ† ๋ฆฌ : https://github.com/jihwankim128/datastructure

 

GitHub - jihwankim128/datastructure

Contribute to jihwankim128/datastructure development by creating an account on GitHub.

github.com

 

๋ ˆํผ๋Ÿฐ์Šค : https://cplusplus.com/reference/list/list/insert/

 

https://cplusplus.com/reference/list/list/insert/

range (3)template iterator insert (const_iterator position, InputIterator first, InputIterator last);

cplusplus.com