python的就地合并排序(找不到错误)

python的就地合并排序(找不到错误),python,merge,mergesort,Python,Merge,Mergesort,我在我的算法书(第三版Cormen算法简介)中读到了关于合并排序(就地)的内容,我决定用Python实现它。问题是我找不到我做错了什么。。。我在C++中看到了一些代码,但是即使是这样我也无法修复它。p> 这是我的密码: def MERGE(A,start,mid,end): L=[0]*(mid - start + 1) for i in range(len(L) - 1): L[i] = A[start+i] L[len(L) - 1] = 100000

我在我的算法书(第三版Cormen算法简介)中读到了关于合并排序(就地)的内容,我决定用Python实现它。问题是我找不到我做错了什么。。。我在C++中看到了一些代码,但是即使是这样我也无法修复它。p> 这是我的密码:

def MERGE(A,start,mid,end):
    L=[0]*(mid - start + 1)
    for i in range(len(L) - 1):
        L[i] = A[start+i]
    L[len(L) - 1] = 100000 # centinel, (fix)
    R=[0]*(end - mid + 2)
    for j in range(len(R) - 1):
        R[j] = A[mid+j]

    R[len(R) - 1] = 100000
    i = 0
    j = 0
    k = start
    for l in range(k,end):
        if(L[i] < R[j]):
            A[l] = L[i]
            i = i + 1
        else:
            A[k] = R[j]
            j = j + 1   

def mergeSort(A,p,r):
    if p < r:
        mid = int((p+r)/2)
        mergeSort(A,p,mid)
        mergeSort(A,mid+1,r)
        MERGE(A,p,mid,r) 

A  = [20, 30, 15, 21, 42, 45, 31, 0, 9]
mergeSort(A,0,len(A)]
我知道这可能是一个“愚蠢的问题”,也有一些相关的帖子,但我尝试了其中的建议,它对我不起作用

有人能帮我吗?T 谢谢

此代码工作正常:

def MERGE(A,start,mid,end):
    L = A[start:mid]
    R = A[mid:end]
    i = 0
    j = 0
    k = start
    for l in range(k,end):
        if j >= len(R) or (i < len(L) and L[i] < R[j]):
            A[l] = L[i]
            i = i + 1
        else:
            A[l] = R[j]
            j = j + 1  

def mergeSort(A,p,r):
    if r - p > 1:
        mid = int((p+r)/2)
        mergeSort(A,p,mid)
        mergeSort(A,mid,r)
        MERGE(A,p,mid,r)

A  = [20, 30, 21, 15, 42, 45, 31, 0, 9]
mergeSort(A,0,len(A))
print A
结果如下:

[20, 30, 21, 15] [42, 45, 31, 0, 9]
[20, 30] [21, 15]
[20] [30]
[21] [15]
[42, 45] [31, 0, 9]
[42] [45]
[31] [0, 9]
[0] [9]
这就是我们想要的。但是,“mid+1”会产生无效结果。以下是测试代码:

def MERGE(A,start,mid,end):
    # Do nothing
    pass

def mergeSort(A,p,r):
    if r - p > 1:
        mid = int((p+r)/2)
        print A[p:mid],A[mid+1:r]    # Changed
        mergeSort(A,p,mid)
        mergeSort(A,mid+1,r)         # Changed
        MERGE(A,p,mid,r)

A  = [20, 30, 21, 15, 42, 45, 31, 0, 9]
mergeSort(A,0,len(A))
结果:

[20, 30, 21, 15] [45, 31, 0, 9]
[20, 30] [15]
[20] []
[45, 31] [9]
[45] []

(新增)

下面是使用“mid+1”的代码:

# New indexing function that includes the right index.
def get_partial_list(origin_list, left_index, right_index): # Added
    return origin_list[left_index:right_index+1]


def MERGE(A,start,mid,end):
    L = get_partial_list(A,start,mid)
    R = get_partial_list(A,mid+1,end)
    i = 0
    j = 0
    k = start
    for l in range(k,end+1):            # changed
        if j >= len(R) or (i < len(L) and L[i] < R[j]):
            A[l] = L[i]
            i = i + 1
        else:
            A[l] = R[j]
            j = j + 1  

def mergeSort(A,p,r):
    if r - p > 0:                          # changed
        mid = int((p+r)/2)
        mergeSort(A,p,mid)
        mergeSort(A,mid+1,r)             # changed
        MERGE(A,p,mid,r)

A  = [20, 30, 21, 15, 42, 45, 31, 0, 9]
mergeSort(A,0,len(A)-1)                 # changed
print A
#包含正确索引的新索引功能。
def get_partial_列表(原点列表、左索引、右索引):#添加
返回原点列表[左索引:右索引+1]
def合并(A、开始、中间、结束):
L=获取部分列表(A、开始、中间)
R=获取部分列表(A,中间+1,结束)
i=0
j=0
k=开始
对于范围内的l(k,结束+1):#更改
如果j>=len(R)或(i0:#更改
mid=int((p+r)/2)
合并排序(A、p、mid)
合并排序(A、mid+1、r)#已更改
合并(A、p、mid、r)
A=[20,30,21,15,42,45,31,0,9]
合并排序(A,0,len(A)-1)#已更改
打印
我添加了新的索引功能。这是您期望的代码吗?

此代码工作正常:

def MERGE(A,start,mid,end):
    L = A[start:mid]
    R = A[mid:end]
    i = 0
    j = 0
    k = start
    for l in range(k,end):
        if j >= len(R) or (i < len(L) and L[i] < R[j]):
            A[l] = L[i]
            i = i + 1
        else:
            A[l] = R[j]
            j = j + 1  

def mergeSort(A,p,r):
    if r - p > 1:
        mid = int((p+r)/2)
        mergeSort(A,p,mid)
        mergeSort(A,mid,r)
        MERGE(A,p,mid,r)

A  = [20, 30, 21, 15, 42, 45, 31, 0, 9]
mergeSort(A,0,len(A))
print A
结果如下:

[20, 30, 21, 15] [42, 45, 31, 0, 9]
[20, 30] [21, 15]
[20] [30]
[21] [15]
[42, 45] [31, 0, 9]
[42] [45]
[31] [0, 9]
[0] [9]
这就是我们想要的。但是,“mid+1”会产生无效结果。以下是测试代码:

def MERGE(A,start,mid,end):
    # Do nothing
    pass

def mergeSort(A,p,r):
    if r - p > 1:
        mid = int((p+r)/2)
        print A[p:mid],A[mid+1:r]    # Changed
        mergeSort(A,p,mid)
        mergeSort(A,mid+1,r)         # Changed
        MERGE(A,p,mid,r)

A  = [20, 30, 21, 15, 42, 45, 31, 0, 9]
mergeSort(A,0,len(A))
结果:

[20, 30, 21, 15] [45, 31, 0, 9]
[20, 30] [15]
[20] []
[45, 31] [9]
[45] []

(新增)

下面是使用“mid+1”的代码:

# New indexing function that includes the right index.
def get_partial_list(origin_list, left_index, right_index): # Added
    return origin_list[left_index:right_index+1]


def MERGE(A,start,mid,end):
    L = get_partial_list(A,start,mid)
    R = get_partial_list(A,mid+1,end)
    i = 0
    j = 0
    k = start
    for l in range(k,end+1):            # changed
        if j >= len(R) or (i < len(L) and L[i] < R[j]):
            A[l] = L[i]
            i = i + 1
        else:
            A[l] = R[j]
            j = j + 1  

def mergeSort(A,p,r):
    if r - p > 0:                          # changed
        mid = int((p+r)/2)
        mergeSort(A,p,mid)
        mergeSort(A,mid+1,r)             # changed
        MERGE(A,p,mid,r)

A  = [20, 30, 21, 15, 42, 45, 31, 0, 9]
mergeSort(A,0,len(A)-1)                 # changed
print A
#包含正确索引的新索引功能。
def get_partial_列表(原点列表、左索引、右索引):#添加
返回原点列表[左索引:右索引+1]
def合并(A、开始、中间、结束):
L=获取部分列表(A、开始、中间)
R=获取部分列表(A,中间+1,结束)
i=0
j=0
k=开始
对于范围内的l(k,结束+1):#更改
如果j>=len(R)或(i0:#更改
mid=int((p+r)/2)
合并排序(A、p、mid)
合并排序(A、mid+1、r)#已更改
合并(A、p、mid、r)
A=[20,30,21,15,42,45,31,0,9]
合并排序(A,0,len(A)-1)#已更改
打印

我添加了新的索引功能。这是您期望的代码吗?

递归地将数组拆分为左右两部分,然后根据您的要求将其合并,即
ASC
DESC
,检查以下代码:

def merge_sort(a):
    if len(a) <= 1:
        return a

    left = [];
    right = [];

    mid = len(a)/2

    left = a[0:mid]
    right = a[mid:(len(a))]

    print left
    print right
    #exit()

    left = merge_sort(left)
    right = merge_sort(right)

    return merge(left, right)

def merge(left, right):
    result = []
    while len(left) > 0 and len(right) > 0:
        lv = left[0]
        rv = right[0]
        if lv <= rv:
            result.append(lv)
            left.pop(0)
        else:
            result.append(rv)
            right.pop(0)
    while len(left) > 0:
        result.append(left.pop(0))

    while len(right) > 0:
        result.append(right.pop(0))

    return result

A  = [20, 30, 21, 15, 42, 45, 31, 0, 9]

print A
print merge_sort(A) 

希望这有助于您理解逻辑。

递归地将阵列拆分为左右两部分,然后根据您的要求将其合并,即
ASC
DESC
,请检查以下代码:

def merge_sort(a):
    if len(a) <= 1:
        return a

    left = [];
    right = [];

    mid = len(a)/2

    left = a[0:mid]
    right = a[mid:(len(a))]

    print left
    print right
    #exit()

    left = merge_sort(left)
    right = merge_sort(right)

    return merge(left, right)

def merge(left, right):
    result = []
    while len(left) > 0 and len(right) > 0:
        lv = left[0]
        rv = right[0]
        if lv <= rv:
            result.append(lv)
            left.pop(0)
        else:
            result.append(rv)
            right.pop(0)
    while len(left) > 0:
        result.append(left.pop(0))

    while len(right) > 0:
        result.append(right.pop(0))

    return result

A  = [20, 30, 21, 15, 42, 45, 31, 0, 9]

print A
print merge_sort(A) 

希望这能帮助你理解逻辑。

兰西夫和克里希纳·普拉萨德提供的解决方案没有空间复杂性O(1)

这是Py3的就地合并排序算法,空间复杂度为O(1)。 主功能
sort\u imerge
使用两个辅助功能
wmerge
wsort

此解决方案基于上讨论的C代码: 等等 您还可以使用doctest找到完整的Python代码

def sort\u imerge(Seq,l=0,u=None):
“”“合并排序,可变输入。
输入顺序已更改到位。
时间:O(n*logn)
日志n--级别
n--必须合并每个级别上的元素
空间(附加):O(1)
输入更改到位
不返回
"""
如果u不是其他u,则u=len(Seq)
如果u-l>1:
m=l+(u-l)//2
w=l+u-m
wsort(序号、长、米、西)
当w-l>2时:
n=w
w=l+(n-l+1)//2
wsort(序号、w、n、l)
wmerge(序列,l,l+n-w,n,u,w)
n=w
n>l时:#回退以插入排序
对于范围内的m(n,u):
如果Seq[m-1]>Seq[m]:
序号[m-1],序号[m]=序号[m],序号[m-1]
n-=1
def wmerge(序列号,i,m,j,n,w):
“”“将子阵列[i,m)和[j,n)合并到工作区w中。
所有索引都指向Seq。
w之后的空间必须足够容纳两个子阵列。
"""
当i1:
m=l+(u-l)//2
排序图(序号、l、m)
排序合并(顺序、m、u)
wmerge(序号、l、m、m、u、w)
其他:
而l
lancif和krishna Prasad提供的解决方案没有空间复杂性O(1)

这是Py3的就地合并排序算法,空间复杂度为O(1)。 主功能
sort\u imerge
使用两个辅助功能
wmerge
wsort

此解决方案基于上讨论的C代码: 等等 您还可以使用doctest找到完整的Python代码

def sort\u imerge(Seq,l=0,u=None):
“”“合并排序,可变输入。
输入顺序已更改到位。
时间:O(n*logn)