연결 리스트(Linked List)

각 노드(항목)들이 다음 노드를 가리키는 형식의 자료구조,
배열과 달리 중간에 데이터(노드)를 삽입, 삭제하는 과정이 쉽다.

1. 연결 리스트의 구조

연결 리스트의 구조를 그림으로 포현하면 아래와 같다.



위 그림에서 알 수 있듯이 새로운 원소 F를 C, D 사이에 넣고 싶을 떄,
단순히 C의 다음 항목을 F 노드에 연결하고 F의 다음 항목을 D노드에 연결시키기만 하면 된다.

// 배열의 경우 삽입하고자 하는 부분의 뒤 모든 원소를 한 칸씩 뒤로 이동시켜야 하기에 훨씬 복잡하다.



2. 연결 리스트 구현

연결리스트를 C++ 코드를 사용하여

  • 정적 메모리 할당 방식
  • 동적 메모리 할당 방식

으로 각각 구현하면 아래와 같다.

ex1. 정적 메모리 할당 방식
#include <iostream>
using namespace std;

class Node{
private:
    int m;
    Node* link;
public:
    Node(int a = 0){
        m = a;
        link = nullptr;
    }
    void insertNext(Node* nextNode){ link = nextNode; }
    int getM(){ return m; }
    Node* getLink(){ return link; }
};

int main(){
    Node* head;
    Node n1(10);
    Node n2(9);
    Node n3(8);
    head = &n1;
    n1.insertNext(&n2);
    n2.insertNext(&n3);

    while( head != nullptr){
        cout << head->getM();
        if (head->getLink() != nullptr){ cout << "->"; }
        head = head->getLink();
    }
    cout << endl;

    return 0;
}
ex2. 동적 메모리 할당 방식
#include <iostream>
using namespace std;

class Node{
private:
    int m;
    Node* link;
public:
    Node(int a = 0){
        m = a;
        link = nullptr;
    }
    void insertNext(Node* nextNode){ link = nextNode; }
    int getM(){ return m; }
    Node* getLink(){ return link; }
};

int main(){
    Node* head;
    head = new Node(10);
    head->insertNext(new Node(9));
    head->getLink()->insertNext(new Node(8));

    while (head != nullptr){
        cout << head->getM();
        if (head->getLink() != nullptr){ cout << "->"; }
        head = head->getLink();
    }
    cout << endl;

    return 0;
}


2. output

ex1, ex2
10->9->8




3. 연결 리스트로 타 자료구조 구현

연결리스트를 이용하여 스택(Stack)큐(Queue)를 구현하여 보겠다.

연결 리스트를 이용한 스택 구현
class Node{
private:
    int data;
    Node* link;
public:
    Node(int d = 0){ data = d; }
    ~Node(){}
    void setData(int d){ data = d; }
    int getData(){ return data; }
    void setLink(Node* nextNode){ link = nextNode; }
    Node* getLink(){ return link; }
};

class LinkedStack{
private:
    Node* top;
public:
    LinkedStack(){ top = nullptr; }
    void push(Node* n){
        n->setLink(top);
        top = n;
    }
    Node* pop(){
        Node* tmp = top;
        top = top->getLink();
        return tmp;
    }
    void display(){
        Node* tmp = top;
        while(tmp != nullptr){
            cout << tmp->getData() << " ";
            tmp = tmp->getLink();
        }
        cout << endl;
    }
};

int main(){
    LinkedStack ls;
    ls.push(new Node(10));
    ls.push(new Node(20));
    ls.push(new Node(30));
    ls.push(new Node(40));

    ls.display();

    cout << ls.pop()->getData() << endl;
    cout << ls.pop()->getData() << endl;

    ls.display();
}


연결 리스트를 이용한 큐 구현
class Node{
private:
    int data;
    Node* link;
public:
    Node(int d = 0){ data = d; }
    ~Node(){}
    void setData(int d){ data = d; }
    int getData(){ return data; }
    void setLink(Node* nextNode){ link = nextNode; }
    Node* getLink(){ return link; }
};

class LinkedQueue{
private:
    Node* front;
    Node* rear;
public:
    LinkedQueue(){ front = rear = nullptr; }
    void enqueue(Node* n){
        if (front == nullptr && rear == nullptr){
            front = n;
            rear = n;
        }else{
            rear->setLink(n);
            rear = n;
        }
    }
    Node* dequeue(){
        Node* tmp = front;
        front = front->getLink();
        return tmp;
    }
    void display(){
        Node* tmp = front;
        while(tmp != nullptr){
            cout << tmp->getData() << " ";
            tmp = tmp->getLink();
        }
        cout << endl;
    }
};

int main(){
    LinkedQueue lq;
    lq.enqueue(new Node(10));
    lq.enqueue(new Node(20));
    lq.enqueue(new Node(30));
    lq.enqueue(new Node(40));

    lq.display();

    cout << lq.dequeue()->getData() << endl;
    cout << lq.dequeue()->getData() << endl;

    lq.display();

    lq.enqueue(new Node(50));
    lq.display();
}


4. output

스택
40 30 20 10
40
30
20 10
10 20 30 40
10
20
30 40
30 40 50




정리,
연결 리스트(Linked List)는 배열에서의 단점을 보완할 수 있는 자료구조이다.
- (데이터 삽입, 삭제 / 동적으로 메모리 공간 활용 가능)
단점 역시 존재한다. (구현이 어렵고 오류나기 쉬움, 중간 데이터를 빠르게 가져올 수 없음)