拓扑排序的kotlin和typescript简易实现

直接上代码:

kotlin版本

package org

import java.util.*
import kotlin.collections.*

interface DependencyNode<T> {
    val value: T

    fun dependsOn(node: DependencyNode<T>)
}

interface DependencyManager<T> {
    fun createNode(value: T): DependencyNode<T>

    fun toposort(): List<T>
}

class DependencyManagerEx<T> : DependencyManager<T> {
    private val list = LinkedList<DepsNode<T>>()

    override fun createNode(value: T): DependencyNode<T> = DepsNode(value).apply {
        list.add(this)
    }

    override fun toposort(): List<T> {
        if (list.isEmpty()) {
            return emptyList()
        }
        val result = ArrayList<T>()
        for (depsNode in list) {
            if (depsNode.visited) {
                continue
            }
            toposort(depsNode, depsNode, result)
        }
        return result
    }

    fun reset() {
        for (depsNode in list) {
            depsNode.visited = false
        }
    }

    private fun toposort(node: DepsNode<T>, from: DepsNode<T>, result: MutableList<T>) {
        for (dependency in node.dependencies) {
            if (dependency == from) {
                throw IllegalStateException("has cycle")
            }
            toposort(dependency, from, result)
        }
        if (!node.visited) {
            result.add(node.value)
            node.visited = true
        }
    }

    private class DepsNode<T>(
        override val value: T,
    ) : DependencyNode<T> {
        val dependencies: MutableList<DepsNode<T>> = ArrayList()
        var visited = false

        override fun dependsOn(node: DependencyNode<T>) {
            dependencies.add(node as DepsNode)
        }

        override fun toString(): String {
            return "DepsNode(value=$value, dependencies=${dependencies.size}, visited=$visited)"
        }
    }
}

class DependencyManagerImpl<T> : DependencyManager<T> {
    private val map = LinkedHashMap<DepsNode<T>, LinkedList<DepsNode<T>>>()

    private fun dependsOn(from: DepsNode<T>, to: DepsNode<T>) {
        map[from]!!.add(to.apply { inDegree++ })
    }

    override fun createNode(value: T): DependencyNode<T> = DepsNode(value, this).apply {
        map.putIfAbsent(this, LinkedList<DepsNode<T>>())
    }

    override fun toposort(): List<T> {
        if (map.isEmpty()) {
            return emptyList()
        }
        val result = ArrayList<T>()
        var size = 0
        while (size != map.size && map.isNotEmpty()) {
            size = map.size
            val iter = map.keys.toMutableSet().iterator()
            while (iter.hasNext()) {
                val node = iter.next()
                if (node.inDegree == 0) {
                    result.add(node.value)
                    map[node]!!.forEach {
                        it.inDegree--
                    }
                    map.remove(node)
                }
            }
        }
        if (map.isNotEmpty()) {
            throw IllegalStateException("has cycle")
        }
        return result
    }

    private class DepsNode<T>(
        override val value: T,
        val manager: DependencyManagerImpl<T>,
    ) : DependencyNode<T> {
        var inDegree = 0

        override fun dependsOn(node: DependencyNode<T>) {
            manager.dependsOn(node as DepsNode, this)
        }

        override fun toString(): String {
            return "DepsNode(value=$value, inDegree=$inDegree)"
        }
    }
}

fun main() {
    println(makeNodes(DependencyManagerEx())) // [1, 6, 3, 8, 4, 9, 5, 7, 11]
    println(makeNodes(DependencyManagerImpl())) // [1, 6, 8, 3, 9, 11, 4, 5, 7]
    println(DependencyManagerEx<Int>().toposort()) // []
    println(DependencyManagerImpl<Int>().toposort()) // []
    try {
        println(makeNodes(DependencyManagerEx(), cyclic = true))
    } catch (e: IllegalStateException) {
        println(e) // java.lang.IllegalStateException: has cycle
    }
    try {
        println(makeNodes(DependencyManagerImpl(), cyclic = true))
    } catch (e: IllegalStateException) {
        println(e) // java.lang.IllegalStateException: has cycle
    }
}

private fun makeNodes(manager: DependencyManager<Int>, cyclic: Boolean = false): List<Int> {
    val task1 = manager.createNode(1)
    val task6 = manager.createNode(6)
    val task7 = manager.createNode(7)
    val task4 = manager.createNode(4)
    val task8 = manager.createNode(8)
    val task5 = manager.createNode(5)
    val task3 = manager.createNode(3)
    val task9 = manager.createNode(9)
    val task11 = manager.createNode(11)
    task4.dependsOn(task1)
    task4.dependsOn(task3)
    task4.dependsOn(task8)
    task5.dependsOn(task6)
    task5.dependsOn(task9)
    task7.dependsOn(task4)
    task7.dependsOn(task5)
    task11.dependsOn(task9)
    if (cyclic) {
        task1.dependsOn(task7)
    }
    return manager.toposort()
}

Typescript

module org.topo {

    export interface DependencyNode<T> {
        value: T;

        dependsOn(node: DependencyNode<T>):void;
    }

    export interface DependencyManager<T> {
        createNode(value: T): DependencyNode<T>;

        toposort(): T[];
    }

    export class DependencyManagerEx<T> implements DependencyManager<T> {
        private readonly list:DepsNodeEx<T>[] = [];

        createNode(value: T): DependencyNode<T> {
            const node = new DepsNodeEx(value);
            this.list.push(node);
            return node;
        }

        toposort(): T[] {
            if (this.list.length == 0) {
                return [];
            }
            const result: T[] = [];
            for (const depsNode of this.list) {
                if (depsNode.visited) {
                    continue;
                }
                this.toposort0(depsNode, depsNode, result);
            }
            return result;
        }

        private toposort0(node: DepsNodeEx<T>, from: DepsNodeEx<T>, result: T[]) {
            for (const dependency of node.dependencies) {
                if (dependency === from) {
                    throw "has cycle";
                }
                this.toposort0(dependency, from, result);
            }
            if (!node.visited) {
                result.push(node.value);
                node.visited = true;
            }
        }
    }

    class DepsNodeEx<T> implements DependencyNode<T> {
        readonly value: T;
        readonly dependencies: DepsNodeEx<T>[] = [];
        visited = false;

        constructor(value: T) {
            this.value = value;
        }

        dependsOn(node: DependencyNode<T>) {
            this.dependencies.push(node as DepsNodeEx<T>);
        }
    }

    export class DependencyManagerImpl<T> implements DependencyManager<T> {
        private readonly map = new Map<DepsNodeImpl<T>, DepsNodeImpl<T>[]>();

        createNode(value: T): DependencyNode<T> {
            const node = new DepsNodeImpl(value, this);
            const list: DepsNodeImpl<T>[] = [];
            this.map.set(node, list);
            return node;
        }

        toposort(): T[] {
            if (this.map.size == 0) {
                return [];
            }
            const result: T[] = [];
            let size = 0;
            while (size != this.map.size && this.map.size != 0) {
                size = this.map.size;
                for (const keyNode of this.map.keys()) {
                    if (keyNode.inDegree == 0) {
                        result.push(keyNode.value);
                        const list = this.map.get(keyNode);
                        this.map.delete(keyNode);
                        if (list != undefined) {
                            for (const valueNode of list) {
                                valueNode.inDegree--;
                            }
                        }
                    }
                }
            }
            if (this.map.size != 0) {
                throw "has cycle";
            }
            return result;
        }

        dependsOn(from: DepsNodeImpl<T>, to: DepsNodeImpl<T>) {
            to.inDegree++;
            const list = this.map.get(from);
            if (list != undefined) {
                list.push(to);
            }
        }
    }

    class DepsNodeImpl<T> implements DependencyNode<T> {
        readonly value: T;
        readonly manager: DependencyManagerImpl<T>;
        inDegree = 0;

        constructor(value: T, manager: DependencyManagerImpl<T>) {
            this.value = value;
            this.manager = manager;
        }

        dependsOn(node: DependencyNode<T>) {
            this.manager.dependsOn(node as DepsNodeImpl<T>, this);
        }
    }
}

import DependencyManager = org.topo.DependencyManager;
import DependencyManagerEx = org.topo.DependencyManagerEx;
import DependencyManagerImpl = org.topo.DependencyManagerImpl;

function makeNodes(manager: DependencyManager<number>, cyclic: boolean = false): number[] {
    const task1 = manager.createNode(1);
    const task6 = manager.createNode(6);
    const task7 = manager.createNode(7);
    const task4 = manager.createNode(4);
    const task8 = manager.createNode(8);
    const task5 = manager.createNode(5);
    const task3 = manager.createNode(3);
    const task9 = manager.createNode(9);
    const task11 = manager.createNode(11);
    task4.dependsOn(task1);
    task4.dependsOn(task3);
    task4.dependsOn(task8);
    task5.dependsOn(task6);
    task5.dependsOn(task9);
    task7.dependsOn(task4);
    task7.dependsOn(task5);
    task11.dependsOn(task9);
    if (cyclic) {
        task1.dependsOn(task7);
    }
    return manager.toposort();
}

(function main() {
    console.log(makeNodes(new DependencyManagerEx())); // [1, 6, 3, 8, 4, 9, 5, 7, 11]
    console.log(makeNodes(new DependencyManagerImpl())); // [1, 6, 8, 3, 9, 11, 4, 5, 7]
    console.log(new DependencyManagerEx().toposort()); // []
    console.log(new DependencyManagerImpl().toposort()); // []
    try {
        console.log(makeNodes(new DependencyManagerEx(), true));
    } catch (e) {
        console.log(e); // has cycle
    }
    try {
        console.log(makeNodes(new DependencyManagerImpl(), true));
    } catch (e) {
        console.log(e); // has cycle
    }
})();
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值