차밍이

[알고리즘] 패스트캠퍼스 알고리즘 학습 정리 - 링크드 리스트(Linked List) 본문

파이썬/알고리즘

[알고리즘] 패스트캠퍼스 알고리즘 학습 정리 - 링크드 리스트(Linked List)

2021. 2. 8. 18:29
반응형

목차

    대표적인 데이터 구조: 링크드 리스트 (Linked List)

    1. 링크드 리스트 (Linked List) 구조

    • 연결 리스트라고도 함

    • 배열은 순차적으로 연결된 공간에 데이터를 나열하는 데이터 구조

    • 링크드 리스트는 떨어진 곳에 존재하는 데이터를 화살표로 연결해서 관리하는 데이터 구조

    • 본래 C언어에서는 주요한 데이터 구조이지만, 파이썬은 리스트 타입이 링크드 리스트의 기능을 모두 지원

    • 링크드 리스트 기본 구조와 용어

      • 노드(Node): 데이터 저장 단위 (데이터 값, 포인터)로 구성
      • 포인터(pointer): 각 노드 안에서, 다음이나 이전의 노드와의 연결 정보를 가지고 있는 공간
    • 배열의 단점

      • 배열의 경우 미리 데이터의 길이를 선언해야한다.
      • 선언한 길이만큼 공간을 미리 차지하고 있다.
      • 데이터가 인덱스에 따라 연속된 공간에 배치된다.
    • 링크드 리스트의 장점

      • 각 데이터가 이곳저곳 어디에든 위치해도 된다.
      • 미리 데이터 공간을 차지하지 않아도 된다.
    • 일반적인 링크드 리스트 형태

    (출처: wikipedia, https://en.wikipedia.org/wiki/Linked_list))

    출처 FastCampus 강의 내용 발췌 : 강의 굳


    2. 간단한 링크드 리스트 예

    Node 구현

    • 보통 파이썬에서 링크드 리스트 구현 시, 파이썬 클래스를 활용함

    • 링크드 리스트를 구성하기 위해서 기본 노드 구성을 만듦

    • 각 노드는 데이터를 부분과 다음 노드의 주소를 가진 부분 두 가지를 가진다.

    • Node는 datanext_address 부분을 구성하면 된다.

    링크드 리스트 구현하기

    class Node:
        def __init__(self, data, next_address=None):
            self.data = data
            self.next_address = next_address
    
    # Node와 Node 연결하기 (포인터 활용)
    node1 = Node(1) # node1에 데이터 1이 들어감
    node2 = Node(2) # node2에 데이터 2가 들어감
    node1.next_address = node2 # node1의 다음 주소로 node2가 설정됨
    head = node1 # 링크드리스트 시작 `head`를 node1으로 설정

    링크드 리스트로 데이터 추가하기

    class Node:
        def __init__(self, data, next_address=None):
            self.data = data
            self.next_address = next_address
    
    def add(data):
        node = head # 링크드리스트의 시작점 head에서 시작
        while node.next_address: # 데이터를 추가하기 위해 가장 끝 노드를 찾아가는 과정
            print(node.data, end=" ") # 끝 노드로 가는 과정을 보기 위한 출력
            node = node.next_address
        # 다음 next node가 없으면 반복문 종료
        print()
        node.next_address = Node(data) # 가장 끝 노드에 새로운 데이터가 담긴 노드를 연결

    확인하기

    node1 = Node(1)
    head = node1
    for index in range(2, 10):
        add(index)
    
    >>>
    
    1 
    1 2 
    1 2 3 
    1 2 3 4 
    1 2 3 4 5 
    1 2 3 4 5 6 
    1 2 3 4 5 6 7 

    링크드 리스트 데이터 출력하기(검색하기)

    node = head
    # address를 따라가며 데이터를 출력
    while node.next_address: 
        print(node.data)
        node = node.next_address
    print (node.data)
    
    >>>
    1
    2
    3
    4
    5
    6
    7
    8
    9

    3. 링크드 리스트의 장단점 (전통적인 C언어에서의 배열과 링크드 리스트)

    • 장점

      • 미리 데이터 공간을 미리 할당하지 않아도 됨
        • 배열은 미리 데이터 공간을 할당해야
    • 단점

      • 연결을 위한 별도 데이터 공간이 필요하므로, 저장공간 효율이 높지 않음
      • 연결 정보를 찾는 시간이 필요하므로 접근 속도가 느림
      • 중간 데이터 삭제 시, 앞뒤 데이터의 연결을 재구성해야 하는 부가적인 작업 필요

    4. 링크드 리스트의 복잡한 기능 1 (링크드 리스트 데이터 사이에 데이터를 추가)

    • 링크드 리스트는 유지 관리에 부가적인 구현이 필요함

    (출처: wikipedia, https://en.wikipedia.org/wiki/Linked\_list)

    • 중간 노드에 데이터를 추가하기 위한 과정이 조금 복잡하다.
    • 앞쪽 노드의 연결을 추가할 newNode로 바꿔주고, newNode의 next주소를 뒷 노드를 향하도록 한다.

    현재 링크드 리스트에 저장된 데이터는 1, 2,... , 9까지의 데이터가 저장된 상태에서 1.5라는 데이터를 12 사이에 넣어보자.

    먼저 1.5라는 데이터를 가진 노드를 생성한다.

    node3 = Node(1.5)
    
    node = head
    search = True
    while search:
        if node.data == 1: # 데이터를 넣을 앞쪽 부분 노드를 찾는다.
            search = False
        else:              # 찾는 부분이 아니면 계속 다음 노드로 넘어간다.
            node = node.next_address
    
    # 노드의 주소 설정을 새롭게 해준다.
    node_next_address = node.next_address
    node.next_address = node3
    node3.next_address = node_next_address
    
    # 결과 확인하기
    node = head
    while node.next_address:
        print(node.data)
        node = node.next_address
    print (node.data)
    
    >>>
    1
    1.5
    2
    3
    4
    5
    6
    7
    8
    9

    5. 파이썬 객체지향 프로그래밍으로 링크드 리스트 구현하기

    class Node:
        def __init__(self, data, next_address=None):
            self.data = data
            self.next_address = next_address
    
    class NodeMgmt:
        def __init__(self, data):
            self.head = Node(data)
    
        def add(self, data):
            if self.head == '':
                self.head = Node(data)
            else:
                node = self.head
                while node.next_address:
                    node = node.next_address
                node.next_address = Node(data)
    
        def desc(self): # 링크드 리스트 순회함수
            node = self.head
            while node:
                print (node.data)
                node = node.next_address
    
    
    # 확인하기
    for data in range(1, 10):
        linkedlist1.add(data)
    linkedlist1.desc()
    
    >>>
    0
    1
    2
    3
    4
    5
    6
    7
    8
    9

    6. 링크드 리스트의 복잡한 기능 2 (특정 노드를 삭제)

    • 다음 코드는 위의 코드에서 delete 메서드만 추가한 것이므로 해당 메서드만 확인하면 됨
    • 삭제할 노드를 찾아간다.
    • 삭제할 노드의 앞쪽 노드의 주소를 삭제할 노드가 가리키는 뒤쪽 노드를 향하도록 설정해준다.
    class Node:
        def __init__(self, data, next_address=None):
            self.data = data
            self.next_address = next_address
    
    class NodeMgmt:
        def __init__(self, data):
            self.head = Node(data)
    
        def add(self, data):
            if self.head == '':
                self.head = Node(data)
            else:
                node = self.head
                while node.next_address:
                    node = node.next_address
                node.next_address = Node(data)
    
        def desc(self):
            node = self.head
            while node:
                print (node.data)
                node = node.next_address
    
        def delete(self, data):
            if self.head == '':
                print ("해당 값을 가진 노드가 없습니다.")
                return
    
            if self.head.data == data:
                temp = self.head
                self.head = self.head.next_address
                del temp
            else:
                node = self.head
                while node.next_address:
                    if node.next_address.data == data:
                        temp = node.next_address
                        node.next_address = node.next_address.next_address
                        del temp
                        return
                    else:
                        node = node.next_address

    확인하기

    # 링크드 리스트를 만들고 데이터를 써줌
    linkedlist1 = NodeMgmt(0)
    for data in range(1, 10):
        linkedlist1.add(data)
    
    # 데이터 4를 삭제
    linkedlist1.delete(4)
    linkedlist1.delete(9)
    linkedlist1.desc()
    
    >>>
    0
    1
    2
    3
    5
    6
    7
    8

     

    [알고리즘] 패스트캠퍼스 알고리즘 학습 정리 - 자료구조란?

    [알고리즘] 패스트캠퍼스 알고리즘 학습 정리 - 스택이란?

    반응형

    관련된 글 보기

    Comments