728x90
728x90

원형 연결 리스트(Circular Linked List)

원형 연결 리스트의 개념

  • 단순 연결 리스트(Singly Linked List)
    • 끝까지 방문한 후에는 더 이상 방문할 곳이 없어 종료되므로 다시 방문하려면 헤드(head)부터 재시작해야 한다.
  • 원형 연결 리스트(Circular Linked List)는 단순 연결 리스트의 마지막 노드가 다시 첫 번째 노드를 가리키도록 설정되어 리스트 형태가 원(Circle) 형태로 구성된다.
    • 시작 위치와 다음 위치가 계속 이어진 후, 마지막에 다시 시작 위치로 돌아오는 형태
  • 원형 연결리스트는 단순 연결 리스트와 마찬가지로 데이터 삽입에서 오버헤드가 발생하지 않는다.

 

원형 연결 리스트의 원리

  • 원형 연결 리스트의 원리 및 구조도 단순 연결 리스트와 많은 부분이 비슷하다.

 

노드 구조

  • 단순 연결 리스트와 마찬가지로 원형 연결 리스트를 구현하기 위해서는 노드(Node)를 사용해야 한다.

노드의 구조

 

  • 원형 연결 리스트도 단순 연결 리스트와 마찬가지로 첫 번째 노드를 가리키는 헤드(head)를 사용한다.
    • 헤드는 원형 연결 리스트의 시작점으로 사용한다.

노드로 구성된 원형 연결 리스트

 

노드(데이터) 삽입

  • 1단계 : 삽입할 노드를 생성한다.
  • 2단계 : 순서에 맞게 링크를 수정한다.
    • 새 노드의 링크에 이전 노드의 링크를 복사한다.
    • 이전 노드의 링크에 새 노드를 지정한다.

원형 연결 리스트에서 중간 위치에 노드를 삽입하는 과정

 

  • 원형 연결 리스트에서 중간 노드를 삽입하는 과정은 단순 연결 리스트의 과정과 방식이 동일하다. 
    • 하지만, 첫 번째 노드 삽입이나 마지막 노드 삽입 등은 다르게 처리된다.

 

노드(데이터) 삭제

  • 1단계 : 삭제할 노드의 바로 앞 노드 링크를 수정한다.
    • 삭제할 노드의 링크를 바로 앞 노드의 링크로 복사하여 앞 노드가 삭제할 노드의 다음 노드를 가리키게 한다.
  • 2단계 : 삭제할 노드를 삭제한다.

원형 연결 리스트에서 중간 위치의 데이터를 삭제하는 과정

 

  • 원형 연결 리스트에서 중간 노드를 삭제하는 과정은 단순 연결 리스트의 과정과 방식이 동일하다. 
    • 하지만, 첫 번째 노드 삭제 마지막 노드 삭제 등은 다르게 처리된다.

 

원형 연결 리스트의 구현

  • 헤드(head) : 첫 번째 노드를 가리킨다.
  • 현재(current) : 지금 처리 중인 노드를 가리킨다.
  • 이전(pre) : 현재 처리 중인 노드의 바로 앞 노드를 가리킨다.

 

  • 처음에는 모두 비어 있으므면 되므로 다음과 같이 초기화한다.
memory = []
head, current, pre = None, None, None

 

① 원형 연결 리스트 생성

노드 생성

  • 노드는 클래스(Class)를 사용하여 구현한다.
class Node() :
def __init__(self): # 생성자 함수 : 데이터형을 생성할 때 자동으로 실행
self.data = None
self.Link = None
  • 노드 생성 및 확인
node1 = Node()
node1.data = "Apple"
print(node1.data, end = ' ')
node1.link = node1 # 첫 번째 노드와 마지막 노드가 연결되도록 설정한다.

 

노드 연결

  • 첫 번째 노드의 링크에 두 번째 노드 이름(node2)을 넣어 준다.
  • 그리고 두 번째 노드의 링크에 첫 번째 노드를 연결해서 원형 구조를 갖게 해준다.
node2 = Node()
node2.data = "Banana"
node1.link = node2
node2.link = node1

 

노드 초기화

첫 번째 데이터
  • 첫 번째 노드이므로 헤드는 첫 번째 노드를 가리키도록 하고, 새 노드의 링크는 헤드가 가리키는 노드로 연결한다.
  • 첫 번째 노드이므로 결국 자신이 자신을 가리키는 형태가 된다.

 

node = Node()
node.data = dataArray[0] # 첫 번째 노드
head = node
node.link = head
memory.append(node)

 

두 번째 이후 데이터
  • 새 노드를 기준 노드의 링크에 저장하기 전에 기존 노드를 잠시 저장한 후 생성해야 한다.
  • 그리고 새 노드의 링크에 헤드가 가리키는 노드를 연결함으로써 원형 연결 리스트의 구조를 유지해야 한다.

 

pre = node
node = Node()
node.data = data # 두 번째 이후 노드
pre.link = node
node.link = head
memory.append(node)

 

② 노드 삽입

  • 노드를 원형 연결 리스트의 맨 앞, 중간, 마지막에 삽입하는 경우로 나누어 생각해 볼 수 있다.

 

첫 번째 노드 삽입

 

node = Node()
node.data = "item"
node.link = head
last = head # 마지막 노드를 첫 번째 노드로 우선 지정
while 마지막 노드까지 : # 마지막 노드를 찾으면 반복 종료
last = last.link # last를 다음 노드로 변경
last.link = node # 마지막 노드의 링크에 새 노드 지정
head = node

 

중간 노드 삽입

 

current = head
while 마지막 노드까지 :
pre = current
current = current.link
if current.data == origin_data :
node = Node()
node.data = new_data
node.link = current
pre.link = node

 

마지막 노드 삽입

 

# 마지막 노드까지 new_data 를 찾지 못한 후
node = Node()
node.data = new_data
current.link = node
node.link = head

 

함수 완성

def insertNode(findData, insertData) :
global memory, head, current, pre
if head.data == findData : # 첫 번째 노드 삽입
node = Node()
node.data = insertData
node.link = head
last = head # 마지막 노드를 첫 번째 노드로 우선 지정
while last.link != head: # 마지막 노드를 찾으면 반복 종료
last = last.link # last를 다음 노드로 지정
last.link = node # 마지막 노드의 링크에 새 노드 지정
head = node
return
current = head
while current.link != head: # 중간 노드 삽입
pre = current
current = current.link
if current.data == findData:
node = Node()
node.data = insertData
node.link = current
return
node = Node() # 마지막 노드 삽입
node.data = insertData
current.link = node
node.link = head

 

③ 노드 삭제

첫 번째 노드 삭제

 

current = head
head = head.link
last = head
while last.link != current : # 마지막 노드를 찾으면 반복 종료
last = last.link # last를 다음 노드로 변경
last.link = head # 마지막 노드의 링크에 head가 기리키는 노드 지정
del(current)

 

첫 번째 외 노드 삭제

 

current = head
while current.link != head :
pre = current
current = current.link
if current.data == finding_data :
pre.link = current.link
del(current)

 

함수 완성

def deleteNode(deleteData) :
global memory, head, current, pre
if head.data == deleteData : # 첫 번째 노드 삭제
current = head
head = head.link
last = head
while last.link != current : # 마지막 노드를 찾으면 반복 종료
last = last.link # last를 다음 노드로 변경
last.link = head # 마지막 노드의 링크에 head가 가리키는 노드 지정
del(current)
return
current = head # 첫 번째 외 노드 삭제
while current.link != head :
pre = current
current = current.link
if current.data == deleteData : # 중간 노드를 찾았을 때
pre.link = current.link
del(current)
return

 

④ 노드 검색

  • 검색할 데이터의 노드를 반환하는 방식으로 구현해본다.

 

함수 완성

def findNode(findData) :
global memory, head, current, pre
current = head
if current.data == findData :
return current
while current.link != head :
current = current.link
if current.data == findData :
return current
return Node() # 빈 노드 반환

 

원형 연결 리스트의 완성

# 원형 연결 리스트의 구현
## 클래스와 함수 선언 부분 ##
class Node() :
def __init__(self) :
self.data = None
self.link = None
def printNodes(start) :
current = start
if current.link == None:
return
print(current.data, end = ' ')
while current.link != start :
current = current.link
print(current.data, end = ' ')
print()
def insertNode(findData, insertData) :
global memory, head, current, pre
if head.data == findData : # 첫 번째 노드 삽입
node = Node()
node.data = insertData
node.link = head
last = head # 마지막 노드를 첫 번째 노드로 우선 지정
while last.link != head: # 마지막 노드를 찾으면 반복 종료
last = last.link # last를 다음 노드로 지정
last.link = node # 마지막 노드의 링크에 새 노드 지정
head = node
return
current = head
while current.link != head: # 중간 노드 삽입
pre = current
current = current.link
if current.data == findData:
node = Node()
node.data = insertData
node.link = current
return
node = Node() # 마지막 노드 삽입
node.data = insertData
current.link = node
node.link = head
def deleteNode(deleteData) :
global memory, head, current, pre
if head.data == deleteData : # 첫 번째 노드 삭제
current = head
head = head.link
last = head
while last.link != current : # 마지막 노드를 찾으면 반복 종료
last = last.link # last를 다음 노드로 변경
last.link = head # 마지막 노드의 링크에 head가 가리키는 노드 지정
del(current)
return
current = head # 첫 번째 외 노드 삭제
while current.link != head :
pre = current
current = current.link
if current.data == deleteData : # 중간 노드를 찾았을 때
pre.link = current.link
del(current)
return
def findNode(findData) :
global memory, head, current, pre
current = head
if current.data == findData :
return current
while current.link != head :
current = current.link
if current.data == findData :
return current
return Node() # 빈 노드 반환
## 전역 변수 선언 부분 ##
memory = []
head, current, pre = None, None, None
dataArray = ["다현", "정연", "쯔위", "사나", "지효"]
## 메인 코드 부분 ##
if __name__ == "__main__":
node = Node()
node.data = dataArray[0] # 첫 번째 노드
head = node
node.link = head
memory.append(node)
for data in dataArray[1:] : # 두 번째 이후 노드
pre = node
node = Node()
node.data = data
pre.link = node
node.link = head
memory.append(node)
printNodes(head)
# 삽입 예
insertNode("다현", "화사")
printNodes(head)
insertNode("사나", "솔라")
printNodes(head)
insertNode("지민", "문별")
printNodes(head)
# 삭제 예
deleteNode("다현")
printNodes(head)
deleteNode("쯔위")
printNodes(head)
deleteNode("지효")
printNodes(head)
deleteNode("지민")
printNodes(head)
# 검색 예
fNode = findNode("다현")
print(fNode.data)
fNode = findNode("쯔위")
print(fNode.data)
fNode = findNode("지민")
print(fNode.data)

 

결과 보기
다현 정연 쯔위 사나 지효
화사 다현 정연 쯔위 사나 지효
화사 다현 정연 쯔위 사나 지효
화사 다현 정연 쯔위 사나 지효 문별
화사 정연 쯔위 사나 지효 문별
화사 정연 사나 지효 문별
화사 정연 사나 문별
화사 정연 사나 문별
None
None
None

 

 

 

728x90
728x90

원형 연결 리스트(Circular Linked List)원형 연결 리스트의 개념원형 연결 리스트의 원리노드 구조노드(데이터) 삽입노드(데이터) 삭제원형 연결 리스트의 구현① 원형 연결 리스트 생성노드 생성노드 연결노드 초기화② 노드 삽입첫 번째 노드 삽입중간 노드 삽입마지막 노드 삽입함수 완성③ 노드 삭제첫 번째 노드 삭제첫 번째 외 노드 삭제함수 완성④ 노드 검색함수 완성원형 연결 리스트의 완성