在julia中合并两个排序的数组

时间:2016-03-07 00:34:21

标签: arrays algorithm sorting julia

julia中是否有一个整洁的函数,它将合并两个已排序的数组并为我返回已排序的数组?我写了:

c=1
p=1
i=1
n=length(tc)+length(tp)
t=Array{Float64}(n)
while(c<=length(tc) && p<=length(tp))
    if(tp[p]<tc[c])
        t[i]=tp[p]
        p=p+1;
        i=i+1;
    else
        t[i]=tc[c]
        c=c+1;
        i=i+1;
    end
end
while(p<=length(tp))
    t[i]=tp[p]
    i=i+1
    p=p+1
end
while(c<=length(tc))
    t[i]=tc[c]
    i=i+1
    c=c+1
end

但基础朱莉亚没有本地功能吗?

4 个答案:

答案 0 :(得分:4)

与其他答案相反,事实上有一种方法可以在基础朱莉娅这样做。但是,它仅适用于整数数组,并且仅当数组是唯一的时才起作用(在任何一个数组中都没有重复整数)。只需使用IntSet类型,如下所示:

a = [2, 3, 4, 8]
b = [1, 5]
union(IntSet(a), IntSet(b))

如果您运行上面的代码,您会注意到union函数会从输出中删除重复项,这就是为什么我最初声明您的数组必须是唯一的(否则您必须乐意在输出中删除了重复项。您还会注意到union上的IntSet操作比排序union上的Vector{Int}更快IntSet预先排序的事实。

当然,上述内容并非真正符合问题的精神,更为关注的是定义lt运算符的任何类型的解决方案,以及允许重复。

这是一个有效查找两个预先排序的唯一向量的并集的函数。我自己从来没有需要非独特的案例,所以没有写出一个涵盖我害怕的案例的函数:

"union <- Return the union of the inputs as a new sorted vector"
function union_vec(x::Vector{T}, y::Vector{T})::Vector{T} where {T}
    (nx, ny) = (1, 1)
    z = T[]
    while nx <= length(x) && ny <= length(y)
        if x[nx] < y[ny]
            push!(z, x[nx])
            nx += 1
        elseif y[ny] < x[nx]
            push!(z, y[ny])
            ny += 1
        else
            push!(z, x[nx])
            nx += 1
            ny += 1
        end
    end
    if nx <= length(x)
        [ push!(z, x[n]) for n = nx:length(x) ]
    elseif ny <= length(y)
        [ push!(z, y[n]) for n = ny:length(y) ]
    end
    return z
end

另一种选择是查看DataStructures.jl包中提供的已排序词典。我自己还没有完成它,但是一个方法只是将所有观察结果插入到排序字典中(随时检查密钥重复)然后迭代(keys, values)也应该是一种相当有效的方法来攻击它问题。

答案 1 :(得分:2)

不,such function does not exist。事实上,我还没有看到开箱即用的语言。

要做到这一点,你必须在每个数组中保持两个指针,比较值并移动较小的数据(基于我所看到的,这正是你所做的)。

答案 2 :(得分:2)

虽然似乎缺少合并两个已排序向量的显式函数,但可以从现有构建块中轻松构造一个(实际上已经证明了这个问题,但它没有定义函数)。

以下方法尝试利用现有的sort代码并仍然保持高效。

在代码中:

mergesorted(a,b) = sort!(vcat(a,b))

以下是一个例子:

julia> a = [1:2:11...];

julia> b = [2:3:20...];

julia> show(a)
[1,3,5,7,9,11]
julia> show(b)
[2,5,8,11,14,17,20]
julia> show(mergesorted(a,b))
[1,2,3,5,5,7,8,9,11,11,14,17,20]

我没有对该函数进行基准测试,但QuickSort(默认排序算法)通常在预排序数组上表现良好,因此它应该没问题,并且在任何实现中都需要分配结果向量。 / p>

答案 3 :(得分:1)

我在不同的项目中不断遇到这个,所以我创建了一个包MergeSorted(https://github.com/vvjn/MergeSorted.jl)。您可以按如下方式使用它。

using MergeSorted

a = sort!(rand(1000))
b = sort!(rand(1000))
c = mergesorted(a,b)
sort!(vcat(a,b)) == c 

或者没有分配新内存。

mergesorted!(c, a, b)

您还可以使用所有sort选项。

a = sort!(rand(1000), order=Base.Reverse)
b = sort!(rand(1000), order=Base.Reverse)
c = mergesorted(a,b, order=Base.Reverse)
sort!(vcat(a,b), order=Base.Reverse) == c 

sort!(vcat(a,b))快约4-6倍,QuickSort默认使用sort!(vcat(a,b), alg=MergeSort),速度是MergeSort的两倍,但{{1}}使用的内存更多。