双调序列
双调序列(Bitonic Sequence)是指由一个非严格增序列X和非严格减序列Y构成的序列,比如序列(23,10,8,3,5,7,11,78)。
定义:一个序列a1,a2,…,an是双调序列(Bitonic Sequence),如果:
(1)存在一个ak(1≤k≤n), 使得a1≥…≥ak≤…≤an成立;或者
(2)序列能够循环移位满足条件(1)
Batcher定理
将任意一个长为2n的双调序列A分为等长的两半X和Y,将X中的元素与Y中的元素一一按原序比较,即a[i]与a[i+n] (i < n)比较,将较大者放入MAX序列,较小者放入MIN序列。则得到的MAX和MIN序列仍然是双调序列,并且MAX序列中的任意一个元素不小于MIN序列中的任意一个元素。
Bitonic merge(双调合并)
假设我们有一个双调序列,则我们根据Batcher定理,将该序列划分成2个双调序列,然后继续对每个双调序列递归划分,得到更短的双调序列,直到得到的子序列长度为1为止。这时的输出序列按单调递增顺序排列。
由于每次划分后问题长度都会减半,故所需要的划分次数为log n。
这个应用双调划分来对双调序列进行排序的过程称为Bitonic merge(双调合并)。
双调合并网络
Bitonic Sort(双调排序)
对于两个元素x,y,如果x<=y,则x,y都位于双调序列的递增部分,而递减部分没有元素,如果x>=y,则x,y都位于双调序列的递减部分,而递增部分没有元素,于是x和y构成一个双调序列。因此,任何无序的序列都是由若干个只有2个元素的双调序列连接而成。
于是,对于一个无序序列,我们按照递增和递减顺序合并相邻的双调序列,按照双调序列的定义,通过连接递增和递减序列得到的序列是双调的。最终,我们可以将若干个只有2个元素的双调序列合并成1个有n个元素的双调序列。
def compAndSwap(a, i, j, dire):
if (dire == 1 and a[i] > a[j]) or (dire == 0 and a[i] < a[j]):
a[i], a[j] = a[j], a[i]
def bitonicMerge(a, low, cnt, dire):
if cnt > 1:
k = int(cnt / 2)
for i in range(low, low + k):
compAndSwap(a, i, i + k, dire)
bitonicMerge(a, low, k, dire)
bitonicMerge(a, low + k, k, dire)
def bitonicSort(a, low, cnt, dire):
if cnt > 1:
k = int(cnt / 2)
bitonicSort(a, low, k, 1)
bitonicSort(a, low + k, k, 0)
bitonicMerge(a, low, cnt, dire)
def sort(a, N, up):
bitonicSort(a, 0, N, up)
if __name__ == "__main__":
# Driver code to test above
a = []
n = int(input().strip())
for i in range(n):
a.append(int(input().strip()))
up = 1
sort(a, n, up)
print("\n\nSorted array is")
for i in range(n):
print("%d" % a[i])