강의노트 18. 자료구조 - LinkedList (링크드 리스트)

|

패스트캠퍼스 컴퓨터공학 입문 수업을 듣고 중요한 내용을 정리했습니다. 개인공부 후 자료를 남기기 위한 목적임으로 내용 상에 오류가 있을 수 있습니다.

linked list

  • 강의자료
  • 참고 생활코딩 - linked list
  • 자료구조에서 가장 중요한 개념 중 하나 (doubly-linked-list와 함께 면접에 자주 나온다. node를 사용하여 구현)
  • Array List와는 다르게 엘리먼트와 엘리먼트 간의 연결(link)을 이용해서 리스트를 구현한 것
  • linked list에서 가장 중요한 것은 연결이 무엇인가를 파악하는 것
  • python 의 경우 list 기본 자료형에 linked list 기능이 함께 포함되어 있다.
  • array list에서는 엘리먼트라는 이름을 사용했지만 linked list와 같이 연결된 엘리먼트들은 노드(node, 마디, 교점의 의미) 혹은 버텍스(vertex, 정점, 꼭지점의 의미)라고 부른다.
views
linked list (출처 : wikipedia)


views
linked list (출처 : wikipedia)


views
doubly-linked-list (출처 : wikipedia)


dummy linked list

  • 맨 앞에 dummy를 두어서 if문의 양을 줄인다.
  • (실제 데이터를 지닌 노드가 아닌, 구현의 편의를 위해서 맨 앞에 두는 무의미한 노드)
  • 노드를 단위로 한다. 노드는 자료와 다음 노드를 가리키는 참조값으로 구성되어 있다. 노드가 다음 노드로 아무것도 가리키지 않으면 리스트의 끝이다.

Node

  • 노드는 자료와 다음 노드를 가리키는 참조값으로 구성되어 있다
  • 자료구조를 이해하기 위해서는 노드에 충분히 익숙해져야 한다.
class Node:
  def __init__(self, data):
    self.data = data
    self.next = None

dummy linked list ADT (인터페이스)

views
출처 : https://github.com/ythwork/
  • 링크드 리스트 클래스 내에는 노드를 가르키는 1) 4개의 참조와 2) 데이터의 개수 만 존재한다.
  • head : 맨 앞을 가르킨다.
  • before : 현재 위치 전
  • current : 현재 탐색위치
  • tail : 맨 뒤를 가르킨다.
  • num_of_data : 데이터의 총 개수
  • 메소드 구현
    • 생성자 : head, before, current, tail, num_of_data 초기화
    • .append() : 맨 뒤에 노드 추가 (insert)
    • .first() : 맨 앞의 노드 검색 (search)
    • .next() : 다음 노트 검색 (search)
    • .delete() : 현재 노드의 삭제 (delete)

dummy linked list 구현예시

LinkedList Class 정의

# Node 클래스 정의
class Node:
    def __init__(self, data):
        self.data = data
        self.next = None


# LinkedList 클래스 (자료구조) 정의
class LinkedList:

    # 초기화 메소드
    def __init__(self):
        dummy = Node("dummy")
        self.head = dummy
        self.tail = dummy

        self.current = None
        self.before = None

        self.num_of_data = 0

    # append 메소드 (insert - 맨 뒤에 노드 추가, tail과 node의 next, 데이터 개수 변경)
    def append(self, data):
        new_node = Node(data)
        self.tail.next = new_node
        self.tail = new_node

        self.num_of_data += 1

    # delete 메소드 (delete - current 노드 삭제, 인접 노드의 current, next 변경, 데이터 개수 변경)
    def delete(self):
        pop_data = self.current.data

        if self.current is self.tail:
            self.tail = self.before

        self.before.next = self.current.next
        self.current = self.before # 중요 : current가 next가 아닌 before로 변경된다.
        #

        self.num_of_data -= 1

        return pop_data

    # first 메소드 (search1 - 맨 앞의 노드 검색, before, current 변경)
    def first(self):
        if self.num_of_data == 0: # 데이터가 없는 경우 첫번째 노드도 없기 때문에 None 리턴
            return None

        self.before = self.head
        self.current = self.head.next

        return self.current.data

    # next 메소드 (search2 - current 노드의 다음 노드 검색, 이전에 first 메소드가 한번은 실행되어야 함)
    def next(self):
        if self.current.next == None:
            return None

        self.before = self.current
        self.current = self.current.next

        return self.current.data

    def size(self):
        return self.num_of_data

테스트 코드

if __name__ = '__main__':
  l_list = LinkedList()
  l_list.append(5)
  l_list.append(2)
  l_list.append(1)
  l_list.append(2)
  l_list.append(7)
  l_list.append(2)
  l_list.append(11)

  print('first :', l_list.first())      # first : 5
  print('next :', l_list.next())        # next : 2
  print('size :', l_list.size())        # size : 7
  print('delete :', l_list.delete())    # delete : 2
  print('size :', l_list.size())        # size : 6
  print('current:', l_list.current.data)# current: 5
  print('tail:', l_list.tail.data)      # tail: 11
  print('first :', l_list.first())      # first : 5
  print('next :', l_list.next())        # next : 1
  print('next :', l_list.next())        # next : 2
  print('next :', l_list.next())        # next : 7


  # 전체 노드 data 표시하기
  data = l_list.first()

  if data:
      print(data, end=' ')
      while True:
          data = l_list.next()
          if data:
              print(data, end= ' ')
          else:
              break
  # 5 1 2 7 2 11



  # 2만 삭제하기
   data = l_list.first()

   if data and data == 2:
       l_list.delete()
       print('deleted', end=' ')
   else:
       print(data, end= ' ')

   while True:
       data = l_list.next()
       if data == 2:
           l_list.delete()
           print('deleted', end=' ')
       elif data:
           print(data, end=' ')
       else:
           break

   # 5 1 deleted 7 deleted 11