๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

์ž๋ฃŒ๊ตฌ์กฐ ๋ฐ ์‹ค์Šต

์ž๋ฃŒ๊ตฌ์กฐ ๋ฐ ์‹ค์Šต - [8] ํŠธ๋ฆฌ Tree (ํŒŒ์ด์ฌ์œผ๋กœ ํŠธ๋ฆฌ ๊ตฌํ˜„) (1)

ํŠธ๋ฆฌ ADT

ํŠธ๋ฆฌ ADT๋Š” ๊ณ„์ธต์ ์œผ๋กœ ์ €์žฅ๋œ ๋ฐ์ดํ„ฐ ์›์†Œ๋“ค์„ ๋ชจ๋ธ๋ง ํ•œ ๊ฒƒ์ด๋‹ค. ์•ž์„  ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ๋“ค๊ณผ ์ฐจ์ด์ ์ด๋ผ๋ฉด ๊ณ„์ธต์ ์ด๋ผ๋Š” ์ ์ด๋‹ค.

๋งจ ์œ„์˜ ์›์†Œ๋ฅผ ์ œ์™ธํ•˜๊ณ , ๊ฐ ํŠธ๋ฆฌ ์›์†Œ๋Š” ๋ถ€๋ชจ(parent) ์›์†Œ์™€ 0๊ฐœ ์ด์ƒ์˜ ์ž์‹(children) ์›์†Œ๋“ค์„ ๊ฐ€์ง„๋‹ค.
์ „์ œ: ํŠธ๋ฆฌ๋Š” ๋น„์–ด์žˆ์ง€ ์•Š๋‹ค -> ์•Œ๊ณ ๋ฆฌ์ฆ˜ ๋‹จ์ˆœํ™”


ํŠธ๋ฆฌ ์šฉ์–ด

๋ฃจํŠธ(root): ๋ถ€๋ชจ๊ฐ€ ์—†๋Š” ๋…ธ๋“œ(A)
๋‚ด๋ถ€๋…ธ๋“œ(internal node): ์ ์–ด๋„ ํ•œ ๊ฐœ์˜ ์ž์‹์„ ๊ฐ€์ง„ ๋…ธ๋“œ(A, B, C, F)
์™ธ๋ถ€๋…ธ๋“œ(external node), ๋˜๋Š” ๋ฆฌํ”„ (leaf): ์ž์‹์ด ์—†๋Š” ๋…ธ๋“œ(E, I, J, K, G, H, D)
ํ˜•์ œ(siblings): ๊ฐ™์€ ๋ถ€๋ชจ๋ฅผ ๊ฐ€์ง„ ๋…ธ๋“œ๋“ค(G, H)
๋…ธ๋“œ์˜ ์กฐ์ƒ(ancestor): ๋ถ€๋ชจ(parent), ์กฐ๋ถ€๋ชจ(grandparent), ์ฆ์กฐ๋ถ€๋ชจ(grand-grandparent), ๋“ฑ
๋…ธ๋“œ์˜ ์ž์†(descendant): ์ž์‹(child), ์†์ฃผ(grandchild), ์ฆ์†์ฃผ(grandgrandchild), ๋“ฑ
๋ถ€ํŠธ๋ฆฌ(subtree): ๋…ธ๋“œ์™€ ๊ทธ ๋…ธ๋“œ์˜ ์ž์†๋“ค๋กœ ๊ตฌ์„ฑ๋œ ํŠธ๋ฆฌ

๊ฒฝ๋กœ(path): ์กฐ์ƒ ๋˜๋Š” ์ž์†์„๋”ฐ๋ผ ์ด์–ด์ง„ ๋…ธ๋“œ ์‹œํ€€์Šค(์˜ˆ:ABF)
๊ฒฝ๋กœ๊ธธ์ด(path length): ๊ฒฝ๋กœ๋‚ด ๊ฐ„์„ (edge)์˜ ์ˆ˜
๋…ธ๋“œ์˜ ๊นŠ์ด(depth): ๋ฃจํŠธ๋กœ๋ถ€ํ„ฐ ๋…ธ๋“œ์— ์ด๋ฅด๋Š”์œ ์ผํ•œ ๊ฒฝ๋กœ์˜ ๊ธธ์ด
๋…ธ๋“œ์˜ ๋†’์ด(height): ๋…ธ๋“œ๋กœ๋ถ€ํ„ฐ ์™ธ๋ถ€๋…ธ๋“œ์—์ด๋ฅด๋Š” ๊ฐ€์žฅ ๊ธด ๊ฒฝ๋กœ์˜ ๊ธธ์ด
ํŠธ๋ฆฌ์˜ ๋†’์ด(height of a tree): ๋ฃจํŠธ์˜ ๋†’์ด


ํŠธ๋ฆฌ ADT ๋ฉ”์„œ๋“œ

ํŠธ๋ฆฌ ADT์˜ ๋ฉ”์„œ๋“œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

- ์ผ๋ฐ˜ ๋ฉ”์„œ๋“œ
  boolean isEmpty()*
  integer size()

- ์ ‘๊ทผ ๋ฉ”์„œ๋“œ
  node root()
  node parent(v)
  node children(v)
  element element(v)

- ์งˆ์˜ ๋ฉ”์„œ๋“œ
  boolean isInternal(v)
  boolean isExternal(v)
  boolean isRoot(v)

- ๊ฐฑ์‹  ๋ฉ”์„œ๋“œ
  swapElements(v, w) #๋…ธ๋“œ์™€ ๋…ธ๋“œ์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์„œ๋กœ swap
  element setElement(v, e) #๋…ธ๋“œ์˜ ๋ฐ์ดํ„ฐ๋ฅผ e๋กœ set

- ์˜ˆ์™ธ
invalidNodeException(): ๋ถˆ๋ฒ• ๋…ธ๋“œ ์ ‘๊ทผ ์‹œ ๋ฐœ๋ น

ํŠธ๋ฆฌADT๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ์— ๋”ฐ๋ผ ์ถ”๊ฐ€์ ์ธ ๊ฐฑ์‹  ๋ฉ”์„œ๋“œ (์‚ฝ์ž…, ์‚ญ์ œ ๋“ฑ) ์ •์˜๊ฐ€ ๊ฐ€๋Šฅํ•˜๋‹ค!!

๊นŠ์ด

๊นŠ์˜ ์˜์‚ฌ์ฝ”๋“œ

๋…ธ๋“œ v์˜ ๊นŠ์ด(depth)์˜ ์žฌ๊ท€์  ์ •์˜

  - ๋งŒ์•ฝ v๊ฐ€ ๋ฃจํŠธ๋ฉด, v์˜ ๊นŠ์ด๋Š” 0

  - ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด, v์˜ ๊นŠ์ด๋Š” v์˜ ๋ถ€๋ชจ์˜ ๊นŠ์ด ๋”ํ•˜๊ธฐ 1

 

์‹คํ–‰์‹œ๊ฐ„์€ O(n) ์ด๋ฉฐ ๋‹จ, n์€ ํŠธ๋ฆฌ ๋‚ด ์ด ๋…ธ๋“œ ์ˆ˜์ด๋‹ค.

 

 

๋†’์ด

๋†’์ด์˜ ์˜์‚ฌ์ฝ”๋“œ

๋…ธ๋“œ v์˜ ๋†’์ด(heigth)์˜ ์žฌ๊ท€์  ์ •์˜

  - ๋งŒ์•ฝ v๊ฐ€ ์™ธ๋ถ€๋…ธ๋“œ๋ฉด, v์˜ ๋†’์ด๋Š” 0

  - ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด, v์˜ ๋†’์ด๋Š” v์˜ ์ž์‹๋“ค ์ค‘ ์ตœ๋Œ€ ๋†’์ด ๋”ํ•˜๊ธฐ 1

 

์‹คํ–‰์‹œ๊ฐ„์€ O(n) ์ด๋ฉฐ ๋‹จ, n์€ ํŠธ๋ฆฌ ๋‚ด ์ด ๋…ธ๋“œ ์ˆ˜์ด๋‹ค.

 


์ˆœํšŒ

์ˆœํšŒ(traversal)๋ž€ ํŠธ๋ฆฌ์˜ ๋…ธ๋“œ๋“ค์„ ์ฒด๊ณ„์ ์ธ ๋ฐฉ์‹์œผ๋กœ ๋ฐฉ๋ฌธํ•˜๋Š” ๊ฒƒ์„ ๋งํ•œ๋‹ค.

 

์„ ์œ„์ˆœํšŒ (preorder traversal) : ๋…ธ๋“œ๋ฅผ ๊ทธ์˜ ์ž์†๋“ค๋ณด๋‹ค ์•ž์„œ ๋ฐฉ๋ฌธ

์„ ์œ„์ˆœํšŒ ์˜์‚ฌ์ฝ”๋“œ
์„ ์œ„์ˆœํšŒ์‹œ ๋ฐฉ๋ฌธํ•˜๋Š” ์ˆœ์„œ

 

 

๋ ˆ๋ฒจ์ˆœํšŒ (levelorder traversal): ํ๋ฅผ ์ด์šฉํ•˜์—ฌ ๊นŠ์ด d์˜ ๋ชจ๋“  ๋…ธ๋“œ๋“ค์„ ๊นŠ์ด d + 1์˜ ๋…ธ๋“œ๋“ค์— ์•ž์„œ ๋ฐฉ๋ฌธ

๋ ˆ๋ฒจ์ด๋ž€ ํŠธ๋ฆฌ์˜ ๊ฐ™์€ ๊นŠ์ด d์— ์กด์žฌํ•˜๋Š” ๋ชจ๋“  ๋…ธ๋“œ๋“ค์˜ ์ง‘ํ•ฉ์„ ๋‚˜ํƒ€๋‚ธ๋‹ค.

๋ ˆ๋ฒจ์ˆœํšŒ์˜ ์˜์‚ฌ์ฝ”๋“œ
๋ ˆ๋ฒจ์ˆœํšŒ์‹œ ๋ฐฉ๋ฌธ ์ˆœ์„œ

 

 

ํ›„์œ„์ˆœํšŒ( postorder traversal) : ๋…ธ๋“œ๋ฅผ ๊ทธ์˜ ์ž์†๋“ค๋ณด๋‹ค ๋‚˜์ค‘์— ๋ฐฉ๋ฌธ

ํ›„์œ„์ˆœํšŒ ์˜์‚ฌ์ฝ”๋“œ
ํ›„์œ„์ˆœํšŒ์‹œ ๋ฐฉ๋ฌธํ•˜๋Š” ์ˆœ์„œ


์ด์ง„ํŠธ๋ฆฌ ADT

์ด์ง„ํŠธ๋ฆฌ๋ž€ ํŠธ๋ฆฌ์˜ ๊ฐ ๋‚ด๋ถ€๋…ธ๋“œ๊ฐ€ ๋‘ ๊ฐœ์˜ ์ž์‹์„ ๊ฐ€์ง – ์™ผ์ชฝ(left) ๋ฐ ์˜ค๋ฅธ์ชฝ(right) ์ž์‹

์ขŒ์šฐ ์ž์‹๋…ธ๋“œ ๊ฐ€์šด๋ฐ ํ•˜๋‚˜๊ฐ€ ๋น„์–ด ์žˆ๋Š” ๊ฒฝ์šฐ๋ผ๋„ ์ ์ •์ด์ง„ํŠธ๋ฆฌ๋กœ ๊ตฌํ˜„ ๊ฐ€๋Šฅํ•˜๋‹ค.

 

์ด์ง„ํŠธ๋ฆฌ ADT ๋ฉ”์„œ๋“œ

์ด์ง„ํŠธ๋ฆฌ ADT๋Š” ํŠธ๋ฆฌ ADT์˜ ํ™•์žฅ์ด๋‹ค – ์ฆ‰, ํŠธ๋ฆฌ ADT์˜ ๋ชจ๋“  ๋ฉ”์„œ๋“œ๋ฅผ ์ƒ์†ํ•œ๋‹ค.

 

-์ถ”๊ฐ€์ ์ธ ๋ฉ”์„œ๋“œ
  node leftChild(v)
  node rightChild(v)
  node sibling(v)

์ด์ง„ํŠธ๋ฆฌADT๋ฅผ ์—ญ์‹œ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ์— ๋”ฐ๋ผ ์ถ”๊ฐ€์ ์ธ ๊ฐฑ์‹  ๋ฉ”์„œ๋“œ (์‚ฝ์ž…, ์‚ญ์ œ ๋“ฑ) ์ •์˜๊ฐ€ ๊ฐ€๋Šฅํ•˜๋‹ค!!

 

์ด์ง„ํŠธ๋ฆฌ์˜ ๊นŠ์ด์™€ ๋†’์ด

์ด์ง„ํŠธ๋ฆฌ์˜ ๊นŠ์ด์™€ ๋†’์ด ์˜์‚ฌ์ฝ”๋“œ

๋…ธ๋“œ v์˜ ๊นŠ์ด(depth)์˜ ์žฌ๊ท€์  ์ •์˜

  - ๋งŒ์•ฝ v๊ฐ€ ๋ฃจํŠธ๋ฉด, v์˜ ๊นŠ์ด๋Š” 0

  - ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด, v์˜ ๊นŠ์ด๋Š” v์˜ ๋ถ€๋ชจ์˜ ๊นŠ์ด ๋”ํ•˜๊ธฐ 1

 

๋…ธ๋“œv์˜ ๋†’์ด(height)์˜ ์žฌ๊ท€์  ์ •์˜

  - ๋งŒ์•ฝ v๊ฐ€ ์™ธ๋ถ€๋…ธ๋“œ๋ฉด, v์˜ ๋†’์ด๋Š” 0

  - ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด, v์˜ ๋†’์ด๋Š” v์˜ ์™ผ์ชฝ๊ณผ ์˜ค๋ฅธ์ชฝ ์ž์‹ ์ค‘ ์ตœ๋Œ€ ๋†’์ด ๋”ํ•˜๊ธฐ 1


์ด์ง„ํŠธ๋ฆฌ ์ˆœํšŒ

์ด์ง„ํŠธ๋ฆฌ์˜ ์ˆœํšŒ๋Š” ํŠธ๋ฆฌ์ˆœํšŒ์˜ ํŠนํ™”๋‹ค.

์„ ์œ„์ˆœํšŒ์™€ ํ›„์œ„์ˆœํšŒ์˜ ์˜์‚ฌ์ฝ”๋“œ

์„ ์œ„์ˆœํšŒ(preorder traversal): ๋…ธ๋“œ๋ฅผ ๊ทธ์˜ ์™ผ์ชฝ ๋ฐ ์˜ค๋ฅธ์ชฝ ๋ถ€ํŠธ๋ฆฌ๋ณด๋‹ค ์•ž์„œ ๋ฐฉ๋ฌธ
ํ›„์œ„์ˆœํšŒ(postorder traversal): ๋…ธ๋“œ๋ฅผ ๊ทธ์˜ ์™ผ์ชฝ ๋ฐ ์˜ค๋ฅธ์ชฝ ๋ถ€ํŠธ๋ฆฌ๋ณด๋‹ค ๋‚˜์ค‘์— ๋ฐฉ๋ฌธ

 

๋‘ ๊ฐ€์ง€ ๋ฐฉ๋ฒ•์€ '๋ฐฉ๋ฌธ์„ ์–ธ์ œํ•˜๋А๋ƒ?' ์— ๋‹ฌ๋ ค์žˆ๋‹ค.

 

์ค‘์œ„์ˆœํšŒ์˜ ์˜์‚ฌ์ฝ”๋“œ

์ค‘์œ„์ˆœํšŒ(inorder traversal): ๋…ธ๋“œ๋ฅผ ๊ทธ์˜ ์™ผ์ชฝ ๋ถ€ํŠธ๋ฆฌ๋ณด๋‹ค๋Š” ๋‚˜์ค‘์—, ์˜ค๋ฅธ์ชฝ ๋ถ€ํŠธ๋ฆฌ๋ณด๋‹ค๋Š” ์•ž์„œ ๋ฐฉ๋ฌธํ•œ๋‹ค.

์ค‘์œ„์ˆœํšŒ๋„ ์œ„ ๋‘๊ฐ€์ง€ ๋ฐฉ๋ฒ•๊ณผ ๋น„์Šทํ•˜๊ฒŒ ๋ฐฉ๋ฌธ ์ˆœ์„œ๋งŒ ์ฐจ์ด๊ฐ€ ์žˆ๋‹ค.


ํŒŒ์ด์ฌ์œผ๋กœ ํŠธ๋ฆฌ ๊ตฌํ˜„

class Node:
  def __init__(self,data,L=None,R=None,parent=None):
    self.data = data
    self.L = L
    self.R = R
    self.parent = parent

class tree:
  def __init__(self):
    self.root = None
    self.n=0

  def isEmpty(self):
    return self.root==None
  
  def treesize(self):
    print(self.n)
    return self.n
  
  def rootnode(self):
    #print(self.root)
    return self.root.data
  
  def parent(self,v):
    if v == self.root:
      print("Root Node")
    else:
      #print(v.parent.data)
      return v.parent.data
  
  def children(self,v):
    return v.L.data,v.R.data
  
  def element(self,v):
    return v.data
  
  def isInternal(self,v):
    if v.L != None or v.R != None:
      return True
    else: 
      return False
  
  def isExternal(self,v):
    if v.L == None and v.R == None:
      return True
    else:
      return False
  
  def isRoot(self,v):
    if self.root == v:
      return True
    else:
      return False
  
  def swapElements(self,v,w):
    tmp = v.data
    v.data = w.data
    w.data = tmp
    print(f"v.data : {tmp} => {v.data} / w.data : {v.data} => {w.data} ")
  
  def setElements(self,v,e):
    tmp = v.data
    v.data = e
    print(f"Succesly set element v.data : {tmp}=> {e}")
  
  def addNode(self,v,data,location):
    if location =='L':
      v.L = Node(data,None,None,v)
      self.n+=1
    elif location == 'root':
      self.root = Node('Root')
      self.n+=1
    else:
      v.R = Node(data,None,None,v)
      self.n+=1
>>> a = tree()
>>> a.addNode(None,None,'root')
>>> a.addNode(a.root,"root_left",'L')
>>> a.addNode(a.root,"root_right",'R')
>>> a.swapElements(a.root.L,a.root.R)
v.data : root_left => root_right / w.data : root_right => root_left 

>>> print(a.isEmpty())
False

>>> a.treesize()
3

>>> print(a.rootnode())
Root

>>> print(a.children(a.root))
('root_right', 'root_left')

>>> a.swapElements(a.root.L,a.root.R)
v.data : root_right => root_left / w.data : root_left => root_right

>>> print(a.isInternal(a.root))
True

>>> print(a.isExternal(a.root))
False

>>> print(a.isInternal(a.root.L))
False

>>> print(a.isExternal(a.root.L))
True

>>> print(a.isRoot(a.root))
True

>>> print(a.isRoot(a.root.L))
False

>>> a.setElements(a.root.L,"LEFT")
Succesly set element v.data : root_left=> LEFT

>>> print(a.element(a.root.L))
LEFT

๋ฉ”์„œ๋“œ๊ฐ€ ์ž˜ ์‹คํ–‰๋˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

728x90