Computer Science/Data Structure

Single Linked List

sonzwon 2022. 7. 19. 12:47

# Single Linked List

 Linked List는 노드라는 객체로 구성되어 있습니다. 

노드는 데이터를 저장할 수 있는 필드와 다음 노드를 가리킬 수 있는 포인터 필드를 가지고 있습니다. 이 노드들이 다 연결된 리스트를 Linked List라고 하게 됩니다. 가장 앞 노드를 Head, 가장 뒤의 노드를 Tail이라고 하며, Tail은 다음 노드가 없기 때문에 포인터는 Null을 가리키게 됩니다.

array list와는 다르게 Linked List는 인덱스를 통한 random access가 불가능 합니다.

자신을 가리키고 있는 포인터만을 통해서 접근할 수 있기 때문에 N개의 노드를 가지고 있는 리스트는 O(N)의 시간이 소요됩니다. 

 

# 코드 구현 (python)

우선 노드를 만들어주는 클래스를 생성합니다

class Node:
    def __init__(self, data=None, next_node=None):
        self.data = data
        self.next_node = next_node   
    # 노드의 데이터값 리턴해주는 함수    
    def get_data(self):
        return self.data
    # 노드의 다음 노드를 리턴해주는 함수
    def get_next(self):
        return self.next_node
    # 노드의 다음 노드를 지정해주는 함수(포인터)
    def set_next(self, new_next):
        self.next_node = new_next

dummy node ( 데이터없이 존재하는 노드 )를 통해 구현하겠습니다.

class LinkedList:
    def __init__(self, head=None):
        self.head = head    
        self.size = 0

 

[ add ]

추가 기능은 tail 노드 앞에 노드를 추가합니다. tail노드까지 찾아서 가야 하기 때문에 O(N)의 시간이 소요됩니다.

def add(self, data):
    curr = self.head
    while curr.get_next() != None:
        curr = curr.get_next()
    new_node = Node(data)
    curr.set_next(new_node)
    self.size += 1

    curr = self.head                         
    while curr.get_next() != None:
        curr = curr.get_next()              head에서 부터 마지막노드까지 타고 들어감
    

    new_node = Node(data)
    curr.set_next(new_node)            원래 리스트의 마지막 노드(curr)의 다음 노드로 new node를 지정
    self.size += 1

 

[ insert ]

중간에 삽입할 때는 Array List와는 다르게 데이터들을 다 미뤄줄 필요없이 간단하게 포인터만 바꿔주면 쉽게 삽입이 가능합니다. 이 때도 마찬가지로 삽입할 자리를 찾아가기위한 과정에서 O(N)의 시간이 소요됩니다.

def insert(self, idx, data):
    if idx < 0 or idx > self.size:
        raise Exception("Invalid Index")
    i = 0
    prev = self.head
    curr = prev.get_next()   
    i += 1
    while i < idx:
        prev = prev.get_next()
        curr = curr.get_next()
    new_node = Node(data)
    prev.set_next(new_node)
    new_node.set_next(curr)
    self.size += 1

    if idx < 0 or idx > self.size:
        raise Exception("Invalid Index")      입력한 인덱스가 전체 길이보다 크면 예외 발생
    i = 0
    prev = self.head                     head를 이전노드
    curr = prev.get_next()            head다음 노드를 curr(인덱스 노드가 됨)
    i += 1
    while i < idx:                          
        prev = prev.get_next()
        curr = curr.get_next()         위치를 찾아감
    

    new_node = Node(data)         새로운 노드 생성
    prev.set_next(new_node)      prev와 new_node 연결
    new_node.set_next(curr)      new_node와 curr 연결
    self.size += 1

 

[delete] & [delete by index]

delete기능은 입력한 데이터 값으로 삭제하고, delete by index는 입력한 인덱스의 데이터를 삭제합니다. 삭제할 떄도 삽입과 마찬가지로 데이터들을 다 땡겨올 필요없이 간단하게 포인터만 바꿔주고 원래 연결을 끊어주면 됩니다.

def delete(self, data):
    prev = self.head
    curr = prev.get_next()
    while curr != None:
        if curr.get_data() == data:
            prev.set_next(curr.get_next())
            curr.set_next(None)
            self.size -= 1
        prev = prev.get_next()
        curr = curr.get_next()

    prev = self.head
    curr = prev.get_next()
    while curr != None:             마지막노드까지

        if curr.get_data() == data:                 입력한 데이터를 찾으면
            prev.set_next(curr.get_next())      이전 노드와 다음 노드 연결
            curr.set_next(None)                     원래 연결을 끊어줌
            self.size -= 1
        prev = prev.get_next()
        curr = curr.get_next()       위치 찾아 가기

def deletebyindex(self, idx):
    if idx < 0 or idx >= self.size:
        raise Exception("Invalid Index")
    i = 0
    prev = self.head
    curr = prev.get_next()
    i += 1
    while i < idx:
        prev = prev.get_next()
        curr = curr.get_next()
    prev.set_next(curr.get_next())
    curr.set_next(None)
    self.size -= 1
    return True

 

# 전체 코드

전체코드와 다른 기능들은 깃허브를 참고하시면 됩니다.

https://github.com/sonzwon/TIL/blob/master/data_structure_List.py

 

GitHub - sonzwon/TIL: Today I Learned

Today I Learned. Contribute to sonzwon/TIL development by creating an account on GitHub.

github.com