Python 如何迭代编写合并排序?
我已经编写了合并排序的递归版本。它使用一个单独的Python 如何迭代编写合并排序?,python,algorithm,sorting,mergesort,Python,Algorithm,Sorting,Mergesort,我已经编写了合并排序的递归版本。它使用一个单独的merge例程: def merge(lst1, lst2): i = j = 0 merged = [] while i < len(lst1) and j < len(lst2): if lst1[i] <= lst2[j]: merged.append(lst1[i]) i += 1 else: m
merge
例程:
def merge(lst1, lst2):
i = j = 0
merged = []
while i < len(lst1) and j < len(lst2):
if lst1[i] <= lst2[j]:
merged.append(lst1[i])
i += 1
else:
merged.append(lst2[j])
j += 1
merged.extend(lst1[i:])
merged.extend(lst2[j:])
return merged
def merge_sort(lst):
if len(lst) < 2:
return lst
else:
middle = len(lst) / 2
return merge(merge_sort(lst[:middle]), merge_sort(lst[middle:]))
def合并(lst1,lst2):
i=j=0
合并=[]
而i 如果lst1[i]您将需要一个merge
函数(相同或几乎相同的merge
函数),该函数将被重复调用。因此,您不需要更改merge
函数
这是一个多通道解决方案。从块大小2开始,每次传递时将块大小增加一倍
在每次传递中,将列表划分为大小不等的非重叠块。将每个区块分割为2个,并对这2个部分调用merge
这是一个自底向上的版本。我根据Divya的描述进行了扩展(还添加了一个用于验证的测试函数)。可以通过消除子数组(数据_1和数据_2)并进行适当排序来优化以下代码
def merge_sort_iterative(data):
""" gets the data using merge sort and returns sorted."""
for j in range(1, len(data)):
j *= 2
for i in range(0,len(data),j):
data_1 = data[i:i+(j/2)]
data_2 = data[i+(j/2):j-i]
l = m = 0
while l < len(data_1) and m < len(data_2):
if data_1[l] < data_2[m]:
m += 1
elif data_1[l] > data_2[m]:
data_1[l], data_2[m] = data_2[m], data_1[l]
l += 1
data[i:i+(j/2)], data[i+(j/2):j-i] = data_1, data_2
return data
def test_merge_sort():
"""test function for verifying algorithm correctness"""
import random
import time
sample_size = 5000
sample_data = random.sample(range(sample_size*5), sample_size)
print 'Sample size: ', sample_size
begin = time.time()
sample_data = [5,4,3,2,1]
result = merge_sort_iterative(sample_data)
end = time.time()
expected = sorted(sample_data)
print 'Sorting time: %f \'secs'%(end-begin)
assert result == expected, 'Algorithm failed'
print 'Algorithm correct'
if __name__ == '__main__':
test_merge_sort()
def merge\u sort\u迭代(数据):
“”“使用合并排序获取数据并返回已排序。”“”
对于范围(1,len(数据))中的j:
j*=2
对于范围内的i(0,len(数据),j):
数据_1=数据[i:i+(j/2)]
数据_2=数据[i+(j/2):j-i]
l=m=0
而l数据_2[m]:
数据_1[l],数据_2[m]=数据_2[m],数据_1[l]
l+=1
数据[i:i+(j/2)],数据[i+(j/2):j-i]=数据_1,数据_2
返回数据
def test_merge_sort():
“”“验证算法正确性的测试函数”“”
随机输入
导入时间
样本量=5000
样本数据=随机样本(范围(样本大小*5),样本大小)
打印“样本大小:”,样本大小
begin=time.time()
样本数据=[5,4,3,2,1]
结果=合并\排序\迭代(样本\数据)
end=time.time()
预期=已排序(样本数据)
打印“排序时间:%f秒”“(结束-开始)
断言结果==应为“算法失败”
打印“算法正确”
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
测试\合并\排序()
以下是Java实现
public static <T extends Comparable<? super T>> void iterativeMergeSort(T[] seed) {
for (int i = 1; i <seed.length; i=i+i)
{
for (int j = 0; j < seed.length - i; j = j + i+i)
{
inPlaceMerge(seed, j, j + i-1, Math.min(j+i + i -1, seed.length -1));
}
}
}
public static <T extends Comparable<? super T>> void inPlaceMerge(T[] collection, int low, int mid, int high) {
int left = low;
int right = mid + 1;
if(collection[mid].equals(collection[right])) {
return ;//Skip the merge if required
}
while (left <= mid && right <= high) {
// Select from left: no change, just advance left
if (collection[left].compareTo(collection[right]) <= 0) {
left ++;
} else { // Select from right: rotate [left..right] and correct
T tmp = collection[right]; // Will move to [left]
rotateRight(collection, left, right - left);
collection[left] = tmp;
// EVERYTHING has moved up by one
left ++; right ++; mid ++;
}
}
}
publicstatic递归更直观,因此我更喜欢相同的方法,除非在某些情况下,我希望避免显著的堆栈深度(例如,在使用某些共同例程实现时)。然而,在合并排序的情况下,迭代版本实际上更容易遵循(至少是伪代码)
所需要的只是一个嵌套循环,内部循环对2^k个元素对执行合并,外部循环负责增加k
需要执行的另一个步骤是将任何未配对的组与先前合并的组合并。如果元素数不是2的幂,则会遇到未配对组。未配对的组将始终位于迭代的末尾
e、 g。
[5,7,3,4,1,9]->[5,7][3,4][1,9]->[3,4,5,7][1,9]->[1,3,4,5,7,9]
在上面的示例中[1,9]是一个组,该组最初没有要合并的另一个组。因此,它与先前的组(已合并并排序)合并
下面是一个python实现:
from MergeSort import merge
def sort(arr):
n = len(arr) - 1
c = 1
start = 0
mid = 0
end = 0
while c <= n:
while end < n:
mid = start + c//2
end = start + c
if (start < n) and (end <= n):
merge(arr, start, mid, end)
start = end + 1
else:
merge(arr, start - c - 1, start-1, n)
c = 2*c + 1
start = 0
mid = 0
end = 0
从合并排序导入合并
def分拣(arr):
n=长度(arr)-1
c=1
开始=0
mid=0
结束=0
C考虑这里的答案:
from MergeSort import merge
def sort(arr):
n = len(arr) - 1
c = 1
start = 0
mid = 0
end = 0
while c <= n:
while end < n:
mid = start + c//2
end = start + c
if (start < n) and (end <= n):
merge(arr, start, mid, end)
start = end + 1
else:
merge(arr, start - c - 1, start-1, n)
c = 2*c + 1
start = 0
mid = 0
end = 0
def test_merge_sort_iterative(self):
for i in range(1, 100):
length = randint(10, 5000)
data = [randint(1, 10000) for x in range(1, length)]
IterativeMergeSort.sort(data)
issorted = True
i = 0
while (i < len(data) - 1) & issorted:
if data[i] > data[i + 1]:
issorted = False
i += 1
self.assertTrue(issorted, data)
return