[수업출처] 숙명여자대학교 소프트웨어학부 유석종 교수님 자료구조 수업
1. Python
- Interpreter
- 객체 지향 Object-oriented
- 자료형 미리 선언하지 않음 Dynamic typing
- Sequence, collection data type
- 값 저장X, 참조 방식 Literal reference
- 동적 할당 Dynamic allocation
- 파이썬의 모든 변수 → 포인터
- 값에 대한 참조 변수 (값이 저장되어 있는 곳의 주소 참조)
- a, b = b, a : swap
2. Data type
1) Immutable data type 불변자료형
- int, float, string
- 값 변경 불가능 → 값 변경이 아니고 새로운 literal 참조하는 것
- 매개변수 전달시 값 변경 불가능
2) Mutable data type 가변자료형
- list, dictionary
- 원소 값 변경, 추가 가능
- 리스트는 각 원소 값에 대한 참조들의 모음
- 매개변수 전달시 인수 값 변경될 수 있음
- 가변자료형: '참조변수'를 바꿀 수 있다는 것
3. Parameter Passing
- call by value
- call by reference
- python → call by object reference 객체 참조 전달
def f(a):
a = 3
print(a)
return(a)
b = 2
f(b) # 3
print(b) # 2
b = f(b) # 3
print(b) # 3
return을 받으려면 변수에 입력해야함
4. Alias 별명
- 두 변수가 하나의 객체를 동시에 참조하여 공유하는 것
A = [[2, 3, 4], 5]
B = A
B[0][1] = 'f'
print(A, id(A)) # [[2, 'f', 4], 5] 1860139826944
print(B, id(B)) # [[2, 'f', 4], 5] 1860139826944
5. Shallow copy 얕은 복사
- 변수는 복사하여 새로 생성하지만 참조하는 리터럴은 공유하는 복사 방법
- copy 모듈의 copy() 함수로 실행
- 첫번째 level 객체만 복사
import copy
A = [[2, 3, 4], 5]
B = copy.copy(A) # B = list(A)
B[0][1] = 'f'
B[1] = 7
print(A, id(A), id(A[0]), id(A[0][1])) # [[2, 'f', 4], 5] 1860140611008 1860140611584 1860137884464
print(B, id(B), id(B[0]), id(B[0][1])) # [[2, 'f', 4], 7] 1860140611904 1860140611584 1860137884464
- list A를 변수 B에 얕은 복사
- list B의 원소들은 새롭게 생성되지만, 원소들이 참조하는 객체는 원본과 동일하며 새로 생성되지 않음
- list A 와 B의 주소는 다르지만 리스트 원소가 참조하는 객체는 동일
6. Deep copy 깊은 복사
- 변수와 대상 객체(리터럴)를 모두 복제하여 생성
- 완전히 독립됨
import copy
A = [[2, 3, 4], 5]
B = copy.deepcopy(A)
B[0][1] = 'f'
B[1] = 7
print(A, id(A), id(A[0]), id(A[0][1]), id(A[1])
# [[2, 3, 4], 5] 1482518103488 1482518184832 1482509412720 1482509412784
print(B, id(B), id(B[0]), id(B[0][1]), id(B[1])
# [[2, 3, 4], 5] 14825181072000 1482518204544 1482509753136 1482509412848
- 변수 A와 B, 리스트 원소, 원소가 참조하는 객체의 주소가 모두 다름
- 리스트 원소가 참조하는 객체도 복제되기 때문에 B의 원소 값을 수정해도 리스트 A가 참조하는 객체에는 변화가 없음
7. List
- 원소의 자료형 같을 필요 없음
- 파이썬은 정적 배열 지원하지 않음
- 사이즈는 고정되어 있지 않음 dynamic
- referential array 리스트 원소는 값에 대한 참조 변수
A = [2, 3, 4]
A.append(7)
A[1] = 9
1) 리스트 생성
- 리스트 복합 표현
- range(), list() 함수 사용
- 빈 리스트 선언 후 원소 추가
# [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
num1 = [i for i in range(10)]
num2 = list(range(10))
num3 = []
for i in range(10):
num3 = num3 + [i] # num3.append(i)
2) 주사위 던지기 예제
import random
def throw_dice(count, n):
for i in range(n):
eye = random.randint(1, 6)
count[eye-1] += 1
def calc_ratio(count):
ratio = []
total = sum(count)
for i in range(6):
ratio.append(count[i]/total)
return ratio
def print_percent(num):
print('[', end = '')
for i in num:
print('%4.2f %i, end = ' ')
print(']')
dice = [0]*6
for n in [10, 100, 1000]:
print('Times = ', n)
throw_dice(dice, n)
print(dice)
ratio = calc_ratio(dice)
print_percent(ratio)
print()
Times = 10
[2, 1, 2, 1, 2, 2]
[0.20, 0.10, 0.20, 0.10, 0.20, 0.20]
Times = 100
[17, 14, 24, 28, 16, 21]
[0.15, 0.13, 0.22, 0.16, 0.15, 0.19]
Times = 1000
[197, 185, 176, 162, 188, 202]
[0.18, 0.17, 0.16, 0.15, 0.17, 0.18]
3) 2차원 배열 생성
scores = [[75, 90, 85], [60, 100, 75], [90, 70, 80]]
print('scores', scores)
for score in scores:
for num in score:
print(num, end = ' ')
print()
print()
print('scores[0][1]', scores[0][1])
print('scores[2]', scores[2])
print('scores[2][2]', scores[2][2])
scores [[75, 90, 85], [60, 100, 75], [90, 70, 80]]
75 80 85
60 100 75
90 70 80
scores[0][1] 90
scores[2] [90, 70, 80]
scores[2][2] 80
4) 볼링 점수 계산 예제
score1 = [(8,0), ((4,3), (8,2), (4,6), (2,6), \
(10,0), (9,0), (10,0), (8,2), (10,0), (10,10)]
score2 = [(10,0), (10,0), (10,0), (10,0), (10,0), \
(10,0), (10,0), (10,0), (10,0), (10,0), (10, 10)]
score_list = [score1, score2] # 첫번째, 두번째 게임
for score in score_list:
i = total = 0
frame = [] # (프레임 점수, 결과)
for first, second in score: # 1회, 2회 쓰러뜨린 핀의 수
f_total = first + second
next_first, next_second = score[i+1]
if first == 10:
result = 'STRIKE'
f_total += next_first + next_second
# 1~9 프레임에서 더블을 친 경우
if i != 9 and next_first == 10:
next_next_first, next_next_second = score[i+2]
f_total += next_next_first
elif (first + second) == 10:
result == 'SPARE'
f_total += next_first
else: result = 'NONE'
total += f_total
frame.append((f_total, result))
i += 1
if i == 10: break
print(frame)
print('Total = ', total)
print()
[(8, 'NONE'), (7, 'NONE), (14, 'SPARE'), (12, 'SPARE'), (8, 'NONE'), (19, 'SPARE'), (9, 'NONE'), (20, 'STRIKE'), (20, 'SPARE'), (30, 'STRIKE')]
Total = 147
[(30, 'STRIKE'), (30, 'STRIKE'), (30, 'STRIKE'), (30, 'STRIKE'), (30, 'STRIKE'), (30, 'STRIKE'), (30, 'STRIKE'), (30, 'STRIKE'), (30, 'STRIKE'), (30, 'STRIKE')]
Total = 300
8. Set and Dictionary
1) Set
- 수학의 집합과 유사한 자료구조로 집합 연산자 지원
- 원소의 나열 순서가 없으며 중복 허용하지 않음
- s1 = set([1, 2, 3])
- s2 = {2, 3, 4}
- 연산자
- membership( in ), 합집합 union( | ), 차집합 difference( - )
- add()
- update( { } )
- remove()
2) Dictionary
- key & value의 쌍으로 구성된 자료형
- 키를 통해 원소에 접근
- items() : 각 항목 튜플로 반환
- keys() : 키만을 추출하여 리스트로 반환
- values() : 값만을 추출하여 리스트로 반환
- 단어 출현 빈도 예제
sentence = sentence.lower() # 소문자로 변환
words = sentence.split() # 단어 단위로 분리
dic = {}
for word in words:
if word not in dic:
dic[word] = 0
dic [word] += 1
print('# of different words =', len(dic))
n = 0
for word, count in dic.items():
print(word, '(%d)' %count, end = ' ')
n += 1
if n % 3 == 0: print()
# sentence = 'Van Rossum was born and raised in the Netherlands, where he received a master's degree in mathematics and computer science from the University of Amsterdam in 1982. In December 1989, Van Rossum had been looking for a hobby programming project that would keep him occupied during the week around Christmas as his office was closed when he decided to write an interpreter for a new scripting language he had been thinking about lately, a descendant of ABC that would appeal to Unix / C hackers. '
# of different words = 66
van (2) rossum (2) was (2) born (1) and (2) raised (1) ...
9. Polynomial ADT 다항식 객체 (추상자료형)
- polynomial A(x) = 3x^20 + 2x^5 + 4
- x: variable, a: 계수 coefficient, e: 지수 exponent
- 튜플로 저장해야할 것: coefficient, exponent
# 다항식 덧셈
def padd(a, b, d):
while a and b:
coef1, exp1 = a[0]
coef2, exp2 = b[0]
if exp1 > exp2:
d.append(a.pop(0))
elif exp1 < exp2:
d.append(b.pop(0))
else:
if coef1 + coef2 == 0:
a.pop(0)
b.pop(0)
else:
d.append((coef1 + coef2, exp1))
a.pop(0)
b.pop(0)
for coef, exp in a:
d.append((coef, exp))
for coef, exp in b:
d.append((coef, exp))
a = [(5, 12), (-6, 8), (13, 3)]
b = [(10, 15), (4, 8), (9, 0)]
d = []
padd(a, b, d)
print(d)
# [(10, 15), (5, 12), (-2, 8), (13, 3), (9, 0)]
10. Sparse Matrix 희소 행렬
- 2D array: matrix[m][n] → 공간복잡도 S(m, n) = m*n
- Sparse matrix A[m, n] : 유효한 값은 거의 없고 나머지는 0인 행렬
- 2D array에 저장하기에 메모리 공간이 아까운 경우 → 0이 아닌 값 저장 (행, 열, 값)
- a[0].row: 행렬의 행 수
- a[0].col: 행렬의 열 수
- a[0].value: 0이 아닌 값의 개수
- a[1]부터 0이 아닌 값의 행, 열, 값 저장 (left-right, top-bottom)
class SparseMatrix:
def __init__(self):
self.matrix = [[15, 0, 0, 22, 0, 15], \
[0, 11, 3, 0, 0, 0], \
[0, 0, 0, -6, 0, 0], \
[0, 0, 0, 0, 0, 0], \
[91, 0, 0, 0, 0, 0], \
[0, 0, 28, 0, 0, 0]]
self.sparse_list = []
def toTuple(self):
row = count = 0
for rows in self.matrix:
col = 0
for value in rows:
if value != 0:
count += 1
self.sparse_list.append((row, col, value))
count += 1
row += 1
height = len(self.matrix)
width = len(self.matrix[0])
self.sparse_list.insert(0, (height, width, count))
s = SparseMatrix()
s.toTuple()
print(s.sparse_list)
# [(6, 6, 8), (0, 0, 15), (0, 3, 22), (0, 5, 15),
# (1, 1, 11), (1, 2, 3), (2, 3, -6), (4, 0, 91), (5, 2, 28)]
'Software > Data Structures' 카테고리의 다른 글
[Python] 2장 연습문제 (0) | 2022.04.16 |
---|---|
[Python] 1. Introduction (0) | 2022.03.08 |
[자료구조] 탐색 (0) | 2021.04.20 |
[자료구조] 연결 리스트 (0) | 2021.04.20 |
[자료구조] 선형 자료구조 (0) | 2021.04.18 |