algorithm - 根据其元素的成对从属关系对列表进行排序

标签 algorithm sorting graph-theory greedy

给定一个元素列表,例如 [1,2,3,4],以及它们的成对从属关系,例如

[[0,  0.5, 1,  0.1]
 [0.5, 0,  1,  0.9]
 [ 1,  1,  0,  0.2]
 [0.1, 0.9, 0.2, 0]]

对于熟悉图论的人来说,这基本上是一个邻接矩阵

什么是最快的排序列表的方法,使得列表中的距离与成对的从属关系最相关,即具有高从属关系的节点对应该彼此靠近。

有没有办法做到这一点(即使是贪心算法也可以)而不用过多地研究 MDSordination理论?

作为奖励问题:

请注意,一些成对的从属关系可以完美地表示,例如列表 [1,2,3] 和成对的从属关系:

[[0, 0, 1]
 [0, 0, 1]
 [1, 1, 0]]

完美的顺序是[1,3,2]。但是有些隶属关系不能,比如这个:

[[0, 1, 1]
 [1, 0, 1]
 [1, 1, 0]]

任何订单同样好/坏。

有没有办法判断订单的质量?从它代表成对隶属关系的角度来看?

最佳答案

这是一个经过简单测试的算法,它采用邻接矩阵,按出现顺序设置元素/节点,然后尝试找到平衡点。因为它是 1d,所以我只是选择了一个非常简单的吸引力公式。也许增加排斥力会改善它。

/*
 * Sort the nodes of an adjacency matrix
 * @return {Array<number>} sorted list of node indices
 */
function sort1d(mat) {
    var n = mat.length;
    // equilibrium total force threshold
    var threshold = 1 / (n * n);
    var map = new Map(); // <index, position>
    // initial positions
    for(var i = 0; i < n; i++) {
        map.set(i, i);
    }
    // find an equilibrium (local minima)
    var prevTotalForce;
    var totalForce = n * n;
    do {
        prevTotalForce = totalForce;
        totalForce = 0;      
        for(var i = 0; i < n; i++) {
            var posi = map.get(i);
            var force = 0;
            for(var j = i + 1; j < n; j++) {
                var posj = map.get(j);
                var weight = mat[i][j];
                var delta = posj - posi;
                force += weight * (delta / n);
            }
            // force = Sum[i, j=i+1..n]( W_ij * ( D_ij / n )
            map.set(i, posi + force);
            totalForce += force;
        }
        console.log(totalForce, prevTotalForce);
    } while(totalForce < prevTotalForce && totalForce >= threshold);
    var list = [];
    // Map to List<[position, index]>
    map.forEach(function(v, k) { list.push([v, k]); });
    // sort list by position
    list.sort(function(a, b) { return a[0] - b[0]; });
    // return sorted indices
    return list.map(function(vk) { return vk[1]; });
}

var mat = [
    [0,  0.5, 1,  0.1],
    [0.5, 0,  1,  0.9],
    [1,  1,  0,  0.2],
    [0.1, 0.9, 0.2, 0]
];
var mat2 = [
    [0, 1, 1],
    [1, 0, 1],
    [1, 1, 0]
];
console.log(sort1d(mat)); // [2, 0, 1, 3]
console.log(sort1d(mat2)); // [0, 1, 2]

关于algorithm - 根据其元素的成对从属关系对列表进行排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31832773/

相关文章:

c++ - 排序多维数组/vector

graph-theory - DFS中的边缘分类

algorithm - 给定无向图中的完整子图数

algorithm - 将水果放入盒子中的最小 Action

java - 如何在JAVA中一次传递一个类的两个单独实例来对该类中的一些数据进行排序

c++ - C++中的合并排序程序不起作用

用于存储排序的唯一值的 C++ 容器,具有不同的谓词以实现排序和唯一性

macos - 什么是适用于 MacOS 的好的图表编辑器?

algorithm - 动态规划算法(Kadane)

arrays - 汇总行值的所有排列