수달이네 기술 블로그

9. 자료구조 본문

언어/Python

9. 자료구조

슬픈 수달이 2025. 8. 27. 17:04

타 언어와 마찬가지로 파이썬에서도 다양한 자료구조를 지원하며 구현할 수 있다. 

🔍스택(stack)

파이썬에서 스택을 리스트를 이용해 아주 간단하게 구현할 수 있다.

a = [1,2,3,4,5]
a.append(10)
print(a)
a.append(20)
print(a)
print(a.pop())
print(a)

#[1, 2, 3, 4, 5, 10]
# [1, 2, 3, 4, 5, 10, 20]
# 20
# [1, 2, 3, 4, 5, 10]

위의 코드를 보면

리스트. append() 메서드를 이용하여 간단하게 push를 구현하며,

리스트. pop() 메서드를 이용하여 간단하게 pop을 구현할 수 있다.

아래는 스택으로 만든 간단한 이진수 변환 코드이다.

num = int(input("Enter Number: "))
print("입력한 십진수: %s" %num)

binaryCode = []

while(num > 0):
    binaryCode.append(str(num % 2))
    num //= 2

print("".join(binaryCode[::-1]))

# Enter Number: 109
# 입력한 십진수: 109
# 1101101

🔍큐(queue)

큐 또한 마찬가지로 리스트로 간단하게 구현이 가능하다.

a = [1,2,3,4,5]
a.append(10)
print(a)
a.append(20)
print(a)
print(a.pop(0))
print(a)

#[1, 2, 3, 4, 5, 10]
# [1, 2, 3, 4, 5, 10, 20]
# 1
# [2, 3, 4, 5, 10, 20]

push는 똑같이 append() 메서드로,

pop은 pop(0)을 이용해 제일 앞의 요소를 뽑아주는 방식을 이용했다.


🔍튜플(tuple)

이전에 작성했던 글에서 나왔던 튜플 자료구조이다.

t = (10,)
t2 = (10)
t3 = tuple([10])

print(t,"\n",t2,"\n",t3)

# (10,) 
#  10 
#  (10,)

위처럼 소괄호를 이용해 선언한다. 

만약 하나의 튜플을 선언할 경우에는', (쉼표)'를 반드시 작성해 주어서 튜플임을 표기해주어야 한다.(안 할 경우 그냥 정수처리)

tuple() 메서드를 이용해 처리할 수도 있다.

 

튜플은 immutable object이므로 변경될 수 없기 때문에 변경되지 않아야 하는 객체에서 사용해야 한다.

t1 = (1,2,3,4,5)

t1[0] = 100
print(t1)

#TypeError: 'tuple' object does not support item assignment

그렇기 때문에 인덱스를 이용해 변경하려 들면 오류가 생긴다.

그러나 변경이 아닌 할당(연결)을 하는 것은 가능한데,

t1 = (1,2,3,4,5)
t2 = (6,7,8,9)

t = t1 + t2
print(t)

#(1, 2, 3, 4, 5, 6, 7, 8, 9)

위와 같은 기능은 가능하다. 

t1 = (1,2,3,4,5)
t2 = (6,7,8,9)

t = t1 + t2
print(t[3:6])

#(4, 5, 6)

위처럼 인덱스와 비슷하게 인덱싱과 슬라이싱 모두 이용 가능하다.

💡튜플 대입연산

튜플을 이용해 여러 개의 변수에 대입하는 기능이 존재한다.

student = ("철수", 19, "CS")
(name, age, major)  = student
print(name, age, major)
#철수 19 CS

왼쪽의 3개의 변수에 각각 앞에서부터 하나씩 대입되는 것을 볼 수 있다.

해당 기능을 사용하여 간단하게 변수의 값도 교환할 수 있다.

x = 10
y = 20
x,y = y,x
print(x,y)
#20 10

그러나! 튜플 대입연산의 경우 매개변수의 개수는 반드시 일치해야 함!

함수 기능 사용
tuple() 튜플로 만들어줌 a = tuple(리스트)
max,min() 최대값, 최소값을 만들어줌 min(tuple)
* + 리스트처럼 연결, 반복을 해줌 튜플 + 값 or 튜플
len() 튜플의 길이를 반환 len(튜플)
__eq__ 튜플의 비교 튜플1.__eq__(튜플2)

아래는 튜플에서 사용할 수 있는 함수들이다.

해당 함수들 외에도 함수들은 많으며 dir(변수)를 이용하여 사용가능한 함수들을 모두 출력할 수 있다.


🔍세트(set)

순서가 없는 리스트인 집합 자료구조 또한 지원한다.

numbers = {2,1,3}
print(numbers)

#{1, 2, 3}

{중괄호}를 이용해 선언 가능하다. 
위의 결과를 보면 순서가 다르게 출력되었음을 확인할 수 있다.

즉, 세트 자료구조는 순서가 존재하지 않는다. 그렇기에 인덱싱, 슬라이싱 연산을 지원하지 않는다!

add(), update()

해당 두 메서드는 모두 세트 자료구조에 내용을 추가하는 기능이다. 

numbers = {2,1,3,1}
numbers.add(2)
numbers.add(5)
print(numbers)

#{1, 2, 3, 5}

add() 메서드는 값 하나를 추가하는 연산이라면

numbers = {2,1,3,1}

numbers.update([6,6,7,6,65,54,43])

print(numbers)

#{1, 2, 3, 65, 6, 7, 43, 54}

update() 메서드는 시퀀스 자료형 자체를 세트에 추가해 줄 수 있다.

sorted()

리스트에서 사용했던 sorted함수를 이용하여 세트 자료형의 원소들을 정렬하여 사용할 수 있다.

numbers = {2,1,3,1}
print(sorted(numbers, reverse=True))
#[3, 2, 1]

remove(), clear()

위의 두 메서드는 set내의 요소들을 삭제할 수 있다.

partyA = {"김연아", "손흥민", "손연재"}
partyB = {"김민재", "손흥민", "이정후"}

partyA.remove("손흥민")
partyB.clear()
print(partyA)
print(partyB)

# {'김연아', '손연재'}
# set()

remove()는 특정 요소 하나를,

clear()는 세트 내 모든 요소를 삭제한다.

💡set의 특징

set의 모든 요소는 해싱을 이용하여 저장하고 관리한다.

(해시: 요소에 특정 값을 부여하여 배열처럼 바로 찾고, 같은 값인 경우 리스트로 연결된 자료구조)

즉, 세트를 쓰기 위해서 해시값이 필요하며 해시값은 변경될 수 없다. 따라서 세트는 변경 불가하며, 변경가능한 항목도 가질 수 없다.

numbers = {2,1,3,1,[1,2,3]}

print(sorted(numbers, reverse=True))

#TypeError: unhashable type: 'list'

그러나 리스트로부터 세트를 생성하는 것은 가능하다. 

💡집합연산

세트의 가장 큰 기능은 집합연산이다.

부분집합, 상위집합은 아래와 같이 표현가능하다.

a = {1,2,3,4,5}
b = {2,3,4}

print(a > b) #True(b 는 a의 부분집합)
print(a < b) #False(반대는 아님)

print(b.issubset(a)) #True(b 는 a의 부분집합)
print(a.issuperset(b)) #True(a 는 b의 상위집합)

a > b의 경우 b는 a의 부분집합임을 표현하며, issubset() 메서드로도 구현가능하다.

반대는 상위집합이며, issuperset() 메서드로 구현가능하다.

 

합집합, 교집합, 차집합의 연산도 가능하다.

a = {1,2,3,4,5}
b = {4,5,6,7,8}

print(a|b) #or a.union(b)
print(a&b) #or a.intersection(b)
print(a-b) #or a.difference(b)

# {1, 2, 3, 4, 5, 6, 7, 8}
# {4, 5}
# {1, 2, 3}

|: 합집합 연산이며, union()으로 구현 가능하다

&: 교집합 연산이며, intersection()으로 구현 가능하다.

-: 차집합 연산이며, difference()로 구현가능하다.

연산
all() 세트의 모든 요소가 True일때 세트가 True
any() 세트 요소중 하나라도 True 면 True
enumerate() 인덱스
isdisjoint() 서로소인가?

위와 같은 연산들이 더 존재한다.

set1 = {10,20,30,40,50}
set2 = {0,0,0,0,0,7}
print("all()결과: ", all(set1))
print("any()결과: ", any(set2))

print("같은 요소가 없는가: ", set1.isdisjoint(set2))

#True, True, False
partyA = {"김연아", "손흥민", "손연재"}
partyB = {"김민재", "손흥민", "이정후"}

for i in enumerate(partyA, start=1):
    print(i)
for i in enumerate(partyB, start=1):
    print(i)