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

๊ณณ๊ฐ„์—์„œ ์ธ์‹ฌ๋‚œ๋‹ค/์Šคํ„ฐ๋””

[์ž๋ฃŒ๊ตฌ์กฐ] ์—ฐ๊ฒฐ ๋ฆฌ์ŠคํŠธ

๋‹จ์ผ ์—ฐ๊ฒฐ ๋ฆฌ์ŠคํŠธ

 

๋…ธ๋“œ ๊ตฌ์„ฑ : ๋ฐ์ดํ„ฐ + link(๋‹ค์Œ ๋…ธ๋“œ์— ๋Œ€ํ•œ ์—ฐ๊ฒฐ ๊ณ ๋ฆฌ. ํฌ์ธํ„ฐ ํ˜น์€ ๋ ˆํผ๋Ÿฐ์Šค)

์ฒซ ๋ฒˆ ์งธ ๋…ธ๋“œ : ํ—ค๋” header

๋งˆ์ง€๋ง‰ ๋…ธ๋“œ : ๊ผฌ๋ฆฌ tail. link๋Š” ๋น„์›Œ๋‘๊ฑฐ๋‚˜ null๋กœ ์ง€์ •ํ•จ

๋…ธ๋“œ์˜ link๋Š” ๋‹ค์Œ ๋…ธ๋“œ๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” ํฌ์ธํŠธ๋‚˜ ๋ ˆํผ๋Ÿฐ์Šค๋กœ๋งŒ ๊ตฌ์„ฑ๋จ. ๊ทธ๋ž˜์„œ ์•ž์œผ๋กœ๋งŒ ์ข…์ฃผ ๊ฐ€๋Šฅ

๋ฆฌ์ŠคํŠธ๋ฅผ ์™„์ • ์ข…์ฃผํ•˜๋ ค๋ฉด ํ•ญ์ƒ ์ฒซ ๋ฒˆ์งธ ์›์†Œ๋ถ€ํ„ฐ ์‹œ์ž‘ํ•ด์•ผ ํ•œ๋‹ค.

๋ฆฌ์ŠคํŠธ์— ์žˆ๋Š” ๋ชจ๋“  ์›์†Œ์˜ ์œ„์น˜๋ฅผ ํŒŒ์•…ํ•˜๋ ค๋ฉด ๋ฆฌ์ŠคํŠธ์˜ ์ฒซ ๋ฒˆ์งธ ์›์†Œ์— ๋Œ€ํ•œ ํฌ์ธํ„ฐ๋‚˜ ๋ ˆํผ๋Ÿฐ์Šค๊ฐ€ ์žˆ์–ด์•ผ ํ•œ๋‹ค.

์ฒซ ๋ฒˆ์žฌ ์›์†Œ์˜ ํฌ์ธํ„ฐ๋‚˜ ๋ ˆํผ๋Ÿฐ์Šค๋Š” ๋ณดํ†ต ๋ณ„๋„์˜ ์ž๋ฃŒ๊ตฌ์กฐ์— ์ €์žฅํ•จ.

 

 ๋…ธ๋“œ. ์ฝ”ํ‹€๋ฆฐ์œผ๋กœ ์ž‘์„ฑ

class SinglyLinkedListElement<T>(val value: T, var next: SinglyLinkedListElement<T>? = null)

typealias ListElement<T> = SinglyLinkedListElement<T>

 

ํ—ค๋”์— ์‚ฝ์ž…

//ํ—ค๋”์—์„œ ์‹คํ–‰
fun <T> ListElement<T>?.insertInFront(data: T) : ListElement<T>
        = ListElement(value = data, next = this)

 

์‚ฝ์ž…

//ํ—ค๋”์—์„œ ์‹คํ–‰
fun <T> ListElement<T>?.insert(data: T) : ListElement<T> {
    if (this == null) return this.insertInFront(data)

    var thisNode : ListElement<T> = this
    var nextNode : ListElement<T>? = this.next
    while(nextNode != null) {
        thisNode = nextNode
        nextNode = thisNode.next
    }
    thisNode.next = ListElement(value = data, next = null)
    return this
}

 

์ „์ฒด ๋ฆฌ์ŠคํŠธ ์ฝ๊ธฐ

//ํ—ค๋”์—์„œ ์‹คํ–‰
fun <T> ListElement<T>?.readAll() {
    var node : ListElement<T>? = this
    println("----- singly linked list read -----")
    while(node != null) {
        println("node data : ${node.value}")
        node = node.next
    }
    println("----- node read done -----")
}

 

๊ฒ€์ƒ‰

//ํ—ค๋”์—์„œ ์‹คํ–‰
fun <T> ListElement<T>?.search(data: T) : ListElement<T>? {
    var node : ListElement<T>? = this
    while (node != null && node.value != data) {
        node = node.next
    }
    return node
}

 

์‚ญ์ œ

ํ—ค๋” ๋…ธ๋“œ๋ฅผ ์‚ญ์ œํ•  ๊ฒฝ์šฐ, ๋ฆฌ์ŠคํŠธ ์ „์ฒด๋ฅผ ์žƒ์–ด๋ฒ„๋ฆด ์ˆ˜ ์žˆ๋‹ค๋Š” ๋ฌธ์ œ์— ๋ด‰์ฐฉ. ๊ณ ๋ฏผํ•˜๋‹ค๊ฐ€ ์‚ญ์ œ ์ž‘์—… ๊ฒฐ๊ณผ ๊ฐ’์œผ๋กœ Pair๋ฅผ ์“ฐ๊ธฐ๋กœ ํ•จ. ์‚ญ์ œ ๊ฒฐ๊ณผ ์—ฐ๊ฒฐ ๋ฆฌ์ŠคํŠธ์˜ ํ—ค๋” ๋ ˆํผ๋Ÿฐ์Šค์™€ ์‚ญ์ œ ์‹คํ–‰ ๊ฒฐ๊ณผ Boolean ๊ฐ’์„ ๋„ฃ๊ณ  ๋ฐ˜ํ™˜ํ•˜๊ธฐ๋กœ ํ•จ.

fun <T> ListElement<T>?.deleteListElement(data : T?) : Pair<ListElement<T>?, Boolean> {
    if(this == null || data == null) return this to false

    var preNode : ListElement<T>? = null
    var node = this
    while(node != null && node.value != data) {
        preNode = node
        node = node.next
    }
    if (node == null) return this to false

    if (preNode == null) return node.next to true
    preNode.next = node.next
    return this to true
}

 

ํ…Œ์ŠคํŠธ

un testSinglyLinkedList() {
    var head : ListElement<Int>? = ListElement(5, null).insertInFront(3).insert(4).readAll()

    println()
    (1..4).forEach {
        println("๋‹จ์ผ ์—ฐ๊ฒฐ ๋ฆฌ์ŠคํŠธ์— $it ๊ฐ’์ด ์žˆ๋Š”์ง€ ํ™•์ธ")
        println("๊ฒฐ๊ณผ : ${head.search(it) != null}")
    }

    println()
    head.deleteListElement(2).let {
        println("2 ์‚ญ์ œ ์‹œ๋„: ${it.second}")
        it.first.readAll()
        head = it.first
    }

    println()
    head.deleteListElement(3).let {
        println("3 ์‚ญ์ œ ์‹œ๋„: ${it.second}")
        it.first.readAll()
        head = it.first
    }

    println()
    head.deleteListElement(4).let {
        println("4 ์‚ญ์ œ ์‹œ๋„: ${it.second}")
        it.first.readAll()
        head = it.first
    }

    println()
    head.deleteListElement(5).let {
        println("5 ์‚ญ์ œ ์‹œ๋„: ${it.second}")
        it.first.readAll()
        head = it.first
    }

    println()
    head = head.insert(8)
    head.readAll()
}

 

Q. ๋‹จ์ผ ์—ฐ๊ฒฐ ๋ฆฌ์ŠคํŠธ์˜ ๋งˆ์ง€๋ง‰์—์„œ m๋ฒˆ์งธ ์›์†Œ

๋‹จ์ผ ์—ฐ๊ฒฐ ๋ฆฌ์ŠคํŠธ๊ฐ€ ์ฃผ์–ด์กŒ์„ ๋•Œ ๋ฆฌ์ŠคํŠธ์˜ ๋งจ ๋’ค์—์„œ m๋ฒˆ ์งธ ์›์†Œ๋ฅผ ์ฐพ์•„๋‚ด๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜. "๋งจ ๋’ค์—์„œ m๋ฒˆ ์งธ ์›์†Œ"๋Š” m = 0์ผ ๋•Œ ๋ฆฌ์ŠคํŠธ์˜ ๋งˆ์ง€๋ง‰ ์›์†Œ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฒƒ

์‹œ๊ฐ„, ๊ณต๊ฐ„ ํšจ์œจ์„ ๋ชจ๋‘ ๊ณ ๋ คํ•ด์„œ, O(n) ์•Œ๊ณ ๋ฆฌ์ฆ˜์œผ๋กœ ๊ตฌํ˜„ํ•˜๊ธฐ ์œ„ํ•ด์„œ, ๋ฆฌ์ŠคํŠธ๋ฅผ ํ•œ ๋ฒˆ ์ข…์ฃผํ•  ๋•Œ ํ˜„์žฌ์˜ ์œ„์น˜์™€, ํ˜„์žฌ๋กœ๋ถ€ํ„ฐ m๋งŒํผ ๋–จ์–ด์ง„ ์œ„์น˜๋ฅผ ๊ฐ™์ด ์ด๋™์‹œํ‚ค๋ฉด์„œ ๋ฆฌ์ŠคํŠธ์˜ ๋งˆ์ง€๋ง‰์— ๋„๋‹ฌํ•ด์„œ ๊ฐ’์„ ๊ตฌํ•˜๋Š” ๊ฒƒ

fun <T> ListElement<T>?.findMeToLastElement(numOfGap : Int) : ListElement<T>? {

    var current : ListElement<T>? = this ?: return null

    for(index in 0 until numOfGap) {
        if (current?.next != null)
            current = current.next
        else return null
    }

    var behind : ListElement<T>? = this

    while (current?.next != null) {
        current = current.next
        behind = behind?.next
    }

    return behind
}

 

ํ…Œ์ŠคํŠธ

fun test() {
    val head = ListElement<Int>(value = 1).insert(2).insert(3).insert(4).insert(5)
    println("${head.findMeToLastElement(0)?.value}")
}

 

์ด์ค‘ ์—ฐ๊ฒฐ ๋ฆฌ์ŠคํŠธ

 

๋…ธ๋“œ ๊ตฌ์„ฑ : link(์•ž์— ์žˆ๋Š” ๋…ธ๋“œ์— ๋Œ€ํ•œ ํฌ์ธํ„ฐ๋‚˜ ๋ ˆํผ๋Ÿฐ์Šค) + ๋ฐ์ดํ„ฐ + link(๋’ค์— ์˜ค๋Š” ๋…ธ๋“œ์— ๋Œ€ํ•œ ํฌ์ธํ„ฐ๋‚˜ ๋ ˆํผ๋Ÿฐ์Šค)
์ฒซ ๋ฒˆ ์งธ ๋…ธ๋“œ : ๋จธ๋ฆฌ header. ์ด์ „ ๋…ธ๋“œ์— ๋Œ€ํ•œ link๋Š” ๋น„์›Œ๋‘๊ฑฐ๋‚˜ null๋กœ ์ง€์ •.

๋งˆ์ง€๋ง‰ ๋…ธ๋“œ : ๊ผฌ๋ฆฌ tail. ๋‹ค์Œ ๋…ธ๋“œ์— ๋Œ€ํ•œ link๋Š” ๋น„์›Œ๋‘๊ฑฐ๋‚˜ null๋กœ ์ง€์ •.
๋ฆฌ์ŠคํŠธ ์–ด๋Š ๋ฐฉํ–ฅ์ด๋“  ์ข…์ฃผ ๊ฐ€๋Šฅํ•˜๋‹ค.

์–ด๋–ค ์›์†Œ์—์„œ ์‹œ์ž‘ํ•˜๋“  ๋ฆฌ์ŠคํŠธ ์ „์ฒด๋ฅผ ์ข…์ฃผํ•˜๋Š” ๊ฒƒ์ด ๊ฐ€๋Šฅํ•˜๋‹ค.

๋…ธ๋“œ. ์ฝ”ํ‹€๋ฆฐ์œผ๋กœ ์ž‘์„ฑ

class DoubleyLinkedListElement<T>(
        val value: T,
        var previous: DoubleyLinkedListElement<T>? = null,
        var next: DoubleyLinkedListElement<T>? = null)

 

์›ํ˜• ์—ฐ๊ฒฐ ๋ฆฌ์ŠคํŠธ


๋‹จ์ผ ์—ฐ๊ฒฐ ๋ฆฌ์ŠคํŠธ๋กœ ๋œ ๊ฒƒ๋„ ์žˆ๊ณ , ์ด์ค‘ ์—ฐ๊ฒฐ ๋ฆฌ์ŠคํŠธ๋กœ ์žˆ๋Š” ๊ฒƒ๋„ ์žˆ๋‹ค.
๋จธ๋ฆฌ๋‚˜ ๊ผฌ๋ฆฌ๊ฐ€ ์—†๋‹ค.
๋ชจ๋“  ๋…ธ๋“œ์—์„œ ๋‹ค์Œ ๋…ธ๋“œ๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” ํฌ์ธํ„ฐ๋‚˜ ๋ ˆํผ๋Ÿฐ์Šค์—๋Š” ๋ฐ˜๋“œ์‹œ null์ด ์•„๋‹Œ ์–ด๋–ค ์›์†Œ๊ฐ€ ๋“ค์–ด๊ฐ„๋‹ค. ์ด์ค‘ ์—ฐ๊ฒฐ ๋ฆฌ์ŠคํŠธ๋ผ๋ฉด ์ด์ „ ํฌ์ธํ„ฐ/๋ ˆํผ๋Ÿฐ์Šค๋„ ๋งˆ์ฐฌ๊ฐ€์ง€์ด๋‹ค.
๋…ธ๋“œ๊ฐ€ ํ•˜๋‚˜ ๋ฐ–์— ์—†๋Š” ๋ฆฌ์ŠคํŠธ๋ผ๋ฉด ๊ทธ๋ƒฅ ์ž๊ธฐ ์ž์‹ ์„ ๊ฐ€๋ฆฌํ‚จ๋‹ค.
์ข…์ฃผ ์‹œ ๋ฌดํ•œ๋ฃจํ”„๊ฐ€ ์ƒ๊ธฐ์ง€ ์•Š๊ฒŒ ์ฃผ์˜ํ•ด์•ผ ํ•œ๋‹ค. ์‹œ์ž‘์ ์„ ์ œ๋Œ€๋กœ ํŒŒ์•…ํ•˜์ง€ ์•Š์œผ๋ฉด ๋ฆฌ์ŠคํŠธ๋ฅผ ํ•œ์—†์ด ๋Œ๊ฒŒ ๋œ๋‹ค.