22.자료구조와 알고리즘-5

SOWA·2023년 3월 26일
0

🖇️ 최소값

자료구조에서 가장 작은 값

class MinAlgorithm:

    def __init__(self, ns):
        self.nums = ns
        self.minNum = 0

    def getMinNum(self):
        self.minNum  = self.nums[0]

        for n in self.nums:
            if self.minNum > n:
                self.minNum = n

        return self.minNum


nums = [-2, -4, 5, 7, 10, 0, 8, 20, -11]
ma = MinAlgorithm(nums)
minNum = ma.getMinNum()
print(f'minNum: {minNum}')

-11


🖇️최빈값

데이터에서 빈도수가 가장 많은 데이터

  • 학생 100명의 점수 분포
##모듈
class MaxAlgorithm:

    def __init__(self, ns):
        self.nums = ns
        self.maxNum = 0
        self.maxNumIdx = 0

    def setMaxIdxandNum(self):
        self.maxNum = self.nums[0]
        self.maxNumIdx - 0

        for i, n in enumerate(self.nums):

            if self.maxNum < n:
                self.maxNum = n
                self.maxNumIdx = i


    def getMaxNum(self):
        return self.maxNum

    def getMaxNumIdx(self):
        return  self.maxNumIdx
##실행
import random
import qq

scores = []

for i in range(100):
    rn = random.randint(71, 100)
    if rn != 100: rn = rn- (rn % 5) #5단위 재설정
    scores.append(rn)

print(f'scores: {scores}')
print(f'scores length: {len(scores)}')


#최대값 알고리즘

maxAlo = qq.MaxAlgorithm(scores)
maxAlo.setMaxIdxandNum()
maxNum = maxAlo.getMaxNum()
print(f'maxNum: {maxNum}')

#인덱스 리스트 생성

indexes = [0 for i in range(maxNum + 1)]
print(f' indexes: {indexes}')
print(f' indexes length: {len(indexes)}')


#인덱스 리스트 빈도 저장

for n in scores:
    indexes[n] = indexes[n] + 1
print(f'indexes: {indexes}')

n = 1
while True:

    maxAlo = qq.MaxAlgorithm(indexes)
    maxAlo.setMaxIdxandNum()
    maxNum = maxAlo.getMaxNum()
    maxNumIdx = maxAlo.getMaxNumIdx()
    # print(f'maxNum: {maxNum}')
    # print(f'maxNumIdx: {maxNumIdx}')

    if maxNum == 0:
        break

    print(f'{n}. {maxNumIdx}빈도수: {maxNum} \t', end='')
    print('+' * maxNum)

    indexes[maxNumIdx] = 0

    n += 1

scores: [80, 80, 80, 90, 70, 70, 95, 90, 95, 90, 90, 90, 75, 75, 95, 90, 95, 85, 85, 75, 70, 95, 95, 100, 80, 80, 80, 75, 95, 90, 90, 75, 75, 95, 85, 90, 90, 95, 75, 80, 90, 90, 80, 90, 90, 75, 75, 80, 95, 95, 70, 90, 80, 80, 70, 90, 90, 90, 80, 75, 70, 90, 85, 70, 75, 95, 70, 75, 95, 95, 70, 70, 75, 95, 95, 90, 70, 80, 70, 90, 95, 90, 80, 95, 85, 70, 90, 70, 95, 70, 70, 90, 75, 95, 75, 75, 70, 90, 80, 70]
scores length: 100
maxNum: 100
 indexes: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
 indexes length: 101
indexes: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 16, 0, 0, 0, 0, 15, 0, 0, 0, 0, 5, 0, 0, 0, 0, 25, 0, 0, 0, 0, 20, 0, 0, 0, 0, 1]
1. 90빈도수: 25 	+++++++++++++++++++++++++
2. 95빈도수: 20 	++++++++++++++++++++
3. 70빈도수: 18 	++++++++++++++++++
4. 75빈도수: 16 	++++++++++++++++
5. 80빈도수: 15 	+++++++++++++++
6. 85빈도수: 5 	+++++
7. 100빈도수: 1 	+


🖇️ 근삿값

특정 값(참값)에 가장 가까운값

import random

nums = random.sample(range(0, 50), 20)
print(f'nums: {nums}')

inputNum = int(input('input number: '))
print(f'inputNum: {inputNum}')

nearNum = 0
minNum = 50

for n in nums:
    absNum = abs(n - inputNum)
    # print(f'absNum: {absNum}')

    if absNum < minNum:
        minNum = absNum
        nearNum = n

print((f'nearNum: {nearNum}'))

nums: [2, 35, 13, 3, 44, 16, 36, 41, 48, 12, 22, 39, 8, 47, 10, 11, 27, 18, 34, 42]
input number: 15
inputNum: 15
nearNum: 16


🖇️ 평균

여러 수나 양의 중간값을 갖는 수

  • 체조선수의 점수 평균 구하고 순위 정하기
##모듈
class Top5Players:

    def __init__(self, cs, ns):
        self.currentScores = cs
        self.newScore = ns

    def setAlignScore(self):

        nearIdx = 0
        nearScore = 0
        minNum = 10.0

        for i, s in enumerate(self.currentScores):
            absNum = abs(self.newScore - s) ## 절대값

            if absNum < minNum:
                minNum = absNum
                nearIdx = i
                nearScore = s

        if self.newScore >= self.currentScores[nearIdx]: #어느 위치에 넣을건지
            for i in range(len(self.currentScores)-1, nearIdx, -1):
                self.currentScores[i] = self.currentScores[i-1]

            self.currentScores[nearIdx] = self.newScore
        else:
            for i in range(len(self.currentScores) - 1, nearIdx+1, -1):
                self.currentScores[i] = self.currentScores[i - 1]

            self.currentScores[nearIdx] = self.newScore

    def getFinalTop5Scores(self):
        return self.currentScores
##실행
import  rankscom as rs

scores = [8.9, 7.6, 8.2, 9.1, 8.8, 8.1, 7.9,  9.4, 7.2, 8.7]

top5PlayerScores = [9.12, 8.95, 8.12, 7.9, 7.88]

print(f'top5PlayerScores: {top5PlayerScores}')

total = 0; average = 0
for n in scores:
    total += n

average = round(total / len(scores), 2)

print(f' total: {total}')
print(f' average: {average}')

tp = rs.Top5Players(top5PlayerScores, average)
tp.setAlignScore()
top5PlayerScores = tp.getFinalTop5Scores()

print(f'top5PlayerScores: {top5PlayerScores}')

top5PlayerScores: [9.12, 8.95, 8.12, 7.9, 7.88]
 total: 83.9
 average: 8.39
top5PlayerScores: [9.12, 8.95, 8.39, 8.12, 7.9]


🖇️ 재귀 알고리즘

나 자신을 다시 호출하는 것

def recursion(num):

    if num > 0:
        print('*' * num)
        return recursion(num-1)

    else:
        return 1

recursion(10)

**********
*********
********
*******
******
*****
****
***
**
*

  • 유클리드 호제법

    두 자연수 n1,n2에 대하여 (n1>n2) n1을 n2로 나눈 나머지를r이라고 할때 n1과 n2의 최대공약수는 n2와 r의 최대공약수와 같음
def gcd(n1, n2):

    if n1 % n2 == 0:
        return n2
    else:
        return gcd(n2, n1 % n2)

print(f'gdc(82, 32): {gcd(82, 32)}')
print(f'gdc(96, 40): {gcd(96, 40)}')

gdc(82, 32): 2
gdc(96, 40): 8

  • 하노이탑

    세개의 기둥을 이용해서 원판을 다른 기둥으로 옮기면 되고, 제약조건은 다음과 같다
    -한 번에 한개의 원판만 옮기기 가능
    -큰 원판이 작은 원판 위에 있어서는 안됨
           ##원판 개수, 출발기둥, 도착 기둥, 경유 기둥
def moveDisc(discCnt, fromBar, toBar, viaBar):

    if discCnt == 1:
        print(f'{discCnt}disc를 {fromBar}에서 {toBar}로 이동 ')

    else:
        #discNo-1개들을 경유 기둥으로 이동
        moveDisc(discCnt-1, fromBar, viaBar, toBar)

        #discNo를 목적 기둥으로 이동
        print(f'{discCnt}disc를 {fromBar}에서 {toBar}로 이동')

        #discNo-1개들을 도착기둥으로 이동
        moveDisc(discCnt - 1, viaBar, toBar, fromBar)

moveDisc(3, 1, 2, 3)

1disc를 1에서 2로 이동 
2disc를 1에서 3로 이동
1disc를 2에서 3로 이동 
3disc를 1에서 2로 이동
1disc를 3에서 1로 이동 
2disc를 3에서 2로 이동
1disc를 1에서 2로 이동 


🖇️ 병합 정렬

-자료구조를 분할하고 각각의 분할된 자료구조를 정렬한 후 다시 병합하여 정렬
-속도면에서 향상된 정렬
-재귀 알고리즘 적용가능

  • 1부터 100까지이 난수 10개 생성 후 요구사항을 만족하는 모듈 제작
    -병합정렬 알고리즘을 이용한 난수 정렬 모듈 구현
    -위의 모듈에 오름차순과 내림차순을 선택할 수 있는 옵션 추가
##모듈
def mSort(ns, asc=True):

    if len(ns) < 2:
        return ns

    midIdx = len(ns) // 2
    leftNums = mSort(ns[0:midIdx], asc=asc) #왼쪽으로 분할 ##재귀함수를 쓸때는 옵션도 같이 붙여서
    rightNums = mSort(ns[midIdx:len(ns)], asc=asc) #오른쪽으로 분할 ##재귀함수를 쓸때는 옵션도 같이 붙여서

    mergeNums = []
    leftIdx = 0; rightIdx = 0
    while leftIdx < len(leftNums) and rightIdx < len(rightNums):

        if asc:  ##오름차순

            if leftNums[leftIdx] < rightNums[rightIdx]:
                mergeNums.append(leftNums[leftIdx])
                leftIdx += 1

            else:
                mergeNums.append(rightNums[rightIdx])
                rightIdx += 1

        else:  ##내림차순
            if leftNums[leftIdx] > rightNums[rightIdx]:
                mergeNums.append(leftNums[leftIdx])
                leftIdx += 1

            else:
                mergeNums.append(rightNums[rightIdx])
                rightIdx += 1

    mergeNums = mergeNums + leftNums[leftIdx:]
    mergeNums = mergeNums + rightNums[rightIdx:]
    return  mergeNums
###실행
import random as rd
import mergeAl as ma

rNums = rd.sample(range(1, 101), 10)
print(f'not sorted rNums: {rNums}')
print(f'sorted rNums by asc: {ma.mSort(rNums)}')
print(f'sorted rNums by dsc: {ma.mSort(rNums, asc=False)}')

not sorted rNums: [24, 16, 64, 68, 27, 72, 43, 3, 15, 73]
sorted rNums by asc: [3, 15, 16, 24, 27, 43, 64, 68, 72, 73]
sorted rNums by dsc: [73, 72, 68, 64, 43, 27, 24, 16, 15, 3]


🖇️ 퀵정렬

기준값보다 작은 값과 큰 값으로 분리한 후 다시 합침

  • 1부터 100까지이 난수 10개 생성 후 요구사항을 만족하는 모듈 제작
    -퀵정렬 알고리즘을 이용한 난수 정렬 모듈 구현
    -위의 모듈에 오름차순과 내림차순을 선택할 수 있는 옵션 추가
##모듈
def qSort(ns, asc=True):

    if len(ns) < 2:
        return ns

    midIdx = len(ns) // 2
    midVal = ns[midIdx]

    smallNums = []; sameNums = []; bigNums = []

    for n in ns:

        if n < midVal:
            sameNums.append(n)

        elif n == midVal:
            sameNums.append(n)

        else:
            bigNums.append(n)

    if asc:
        return qSort(smallNums, asc=asc) + sameNums + qSort(bigNums, asc=asc)
    else:
        return qSort(bigNums, asc=asc) + sameNums + qSort(smallNums, asc=asc)
##실행
import random as rd
import quickAL as qa

rNums = rd.sample(range(1, 100), 10)
print(f'not sorted rNums: {rNums}')
print(f'sorted rNums ASC: {qa.qSort(rNums)}')
print(f'sorted rNums DSC: {qa.qSort(rNums, asc=False)}')

not sorted rNums: [35, 89, 20, 61, 26, 52, 68, 25, 15, 57]
sorted rNums ASC: [35, 20, 26, 52, 25, 15, 61, 68, 57, 89]
sorted rNums DSC: [89, 61, 68, 57, 35, 20, 26, 52, 25, 15]

from.제로베이스 데이터 취업스쿨 강의

0개의 댓글