# 归并排序（MergeSort）详解（附动画代码）

def exchange(arr,i,j):
temp=arr[i]
arr[i]=arr[j]
arr[j]=temp

#归并需要一个额外数组存放归并前的子数组排序状态
def merge(arr,start,mid,end):
i=start
j=mid+1
aux[start:end+1]=arr[start:end+1]
for idx in range(start,end+1):
if i>mid:
arr[idx] = aux[j]
j += 1
elif j > end:
arr[idx] = aux[i]
i += 1
elif aux[j] < aux[i]:
arr[idx] = aux[j]
j += 1
else:
arr[idx] = aux[i]
i += 1
record.append(arr.copy())#动画代码

def sortUB(arr,start,end):
if start>=end:
return
mid=start+(end-start)//2
sortUB(arr,start,mid)
sortUB(arr,mid+1,end)
merge(arr,start,mid,end)

def sortBU(arr):
n = len(arr)
size = 1
while size < n:
idx = 0
while idx < n - size:
start=idx
mid=idx + size - 1
end=min(idx + 2 * size - 1,n-1)
merge(arr,start,mid,end)
idx += 2*size
size *= 2

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.patches as patches
import matplotlib.path as path
import matplotlib.animation as animation

record=[]
n=100
data=np.random.randint(0,100,n)
record.append(data.copy())
aux=data.copy()
sortBU(data)
bins=np.arange(n+1)
left = np.array(bins[:-1])
right = np.array(bins[1:])
bottom = np.zeros(len(left))
top = bottom + data
nrects = len(left)

# here comes the tricky part -- we have to set up the vertex and path
# codes arrays using moveto, lineto and closepoly

# for each rect: 1 for the MOVETO, 3 for the LINETO, 1 for the
# CLOSEPOLY; the vert for the closepoly is ignored but we still need
# it to keep the codes aligned with the vertices
nverts = nrects*(1 + 3 + 1)
verts = np.zeros((nverts, 2))
codes = np.ones(nverts, int) * path.Path.LINETO
codes[0::5] = path.Path.MOVETO
codes[4::5] = path.Path.CLOSEPOLY
verts[0::5, 0] = left
verts[0::5, 1] = bottom
verts[1::5, 0] = left
verts[1::5, 1] = top
verts[2::5, 0] = right
verts[2::5, 1] = top
verts[3::5, 0] = right
verts[3::5, 1] = bottom

fig, ax = plt.subplots()
barpath = path.Path(verts, codes)
patch = patches.PathPatch(
barpath, facecolor='green', edgecolor='yellow', alpha=0.5)
ax.set_xlim(left[0], right[-1])
ax.set_ylim(bottom.min(), top.max())

def animate(i):
# simulate new data coming in
top = bottom + record[i]
verts[1::5, 1] = top
verts[2::5, 1] = top
return [patch, ]

ani = animation.FuncAnimation(fig, animate, len(record), interval=10,repeat=False, blit=True)
plt.show()