【问题标题】:How to count inversions in large dataset?如何计算大型数据集中的反转?
【发布时间】:2023-03-15 02:50:01
【问题描述】:

以下内容适用于最多 1000 个元素的所有列表。然而,它的真正目的是处理非常大的列表,100'000 或更有效。当这样的列表传递给函数时,一切都冻结了!任何线索为什么会这样?

这也与:Merge sort to count split inversions in Python

这是我的代码...

import operator

def merge_and_count_split_inv(left, right, compare):
    result = []
    split_inversions = []
    i, j = 0, 0
    while i < len(left) and j < len(right):
        if compare(left[i], right[j]):
            result.append(left[i])
            i += 1
        else:
            result.append(right[j])
            k = i
            while k < len(left):
                split_inversions.append((left[k], right[j]))
                k += 1
            j += 1
    while i < len(left):
        result.append(left[i])
        i += 1
    while j < len(right):
        result.append(right[j])
        j += 1
    return result, split_inversions

def sort_and_count_inversions(L, compare=operator.lt):
    if len(L) < 2:
        return L[:], []
    else:
        middle_index = len(L)/ 2
        a, left = sort_and_count_inversions(L[:middle_index], compare)
        b, right = sort_and_count_inversions(L[middle_index:], compare)
        c, merged = merge_and_count_split_inv(a, b, compare)
    return c, left+right+merged

【问题讨论】:

  • 尝试对一个有 500 个元素的列表运行一次,然后再运行 1000 个,看看代码的某些部分是否显示出运行时相对较大的增加。
  • 两者几乎都是瞬时的......
  • 递归调用的数量线性增长 - 2n-1sort_and_count_inversionsn-1merge_and_count_split_inv。对于非常大的列表,递归可能不是最好的方法 - 调用会产生开销,并且您可能会达到递归限制。
  • 我也尝试将递归限制设置得非常高,但同样的问题仍然存在。
  • @AhmedAbdelHadyKhedr 尝试切换到迭代方法。它可能不那么易读和直接,但可能更快。

标签: algorithm sorting python-2.7 recursion mergesort


【解决方案1】:

曾经我想计算一个数组的反转数只要10^6。这是我在C++ 中的代码 sn-p 完成了这项工作。 cnt 保存反转计数的总数。

int ary[1000006];
long cnt;

void merge(int p, int q, int r) {  
    int i, ll, rr, n1, n2;

    n1 = q - p + 1;
    n2 = r - q;

    vector < int > left, right;

    for (i = 0; i < n1; i++) left.push_back(ary[p + i]);
    left.push_back(2147483647);     //ends with largest possible value

    for (i = 0; i < n2; i++) right.push_back(ary[q + i + 1]);
    right.push_back(2147483647);    //ends with largest possible value

    for (i = p, ll = 0, rr = 0; i <= r; i++) {
        if (left[ll] <= right[rr]) ary[i] = left[ll++];
        else {
            ary[i] = right[rr++];
            cnt += n1 - ll;     // number of items remaining in left
        }
    }

    left.clear();
    right.clear();
}

void merge_sort(int p, int r) {
    if (p < r) {
        int q = (p + r) / 2;
        merge_sort(p, q);
        merge_sort(q + 1, r);
        merge(p, q, r);
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-02-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-17
    • 2013-06-14
    相关资源
    最近更新 更多