Preparata的算法是一种递归的分而治之算法,其中计算每个输入键的等级,并根据其等级输出键。
C++
m[i, j] := M[i, j]
for 1 <= i, j <= n in parallel;
for
r : = 1 to logn do
{
Step 1. In parallel set q[i, j, k] := m[i, j] + m[j, k] for
1 <= i, j, k <= n.
Step 2. In parallel set m[i, j] := min
{
q[i, l, j], q[i, 2, j], ..., q[i, n, j]
}
for
1 <= i, j <= n.
}
Put M(i)(i):=0 for all i and M(i)(j):=m[i, j] for i≠j
Python3
# Python program to implement Preparata's
# a time-optimal parallel algorithm
class func:
def __init__(self, x, y):
self.x = x
self.y = y
# Function to find the left index of
# the given set of points
def Left_index(points):
# Finding the point on plane
minn = 0
# Traverse the given points
for i in range(1, len(points)):
# Update the value of minn
if points[i].x < points[minn].x:
minn = i
elif points[i].x == points[minn].x:
if points[i].y > points[minn].y:
minn = i
# Return the value of min
return minn
# Function to perform the parallel
# process in the preparata's algorithm
# according to the value of p, q, r
def parallel(p, q, r):
# For the three-dimensional
val = (q.y - p.y) * (r.x - q.x) - \
(q.x - p.x) * (r.y - q.y)
if val == 0:
return 0
elif val > 0:
return 1
else:
return 2
# Function to perform the parallel
# process in the preparata's algorithm
def preparata(points, n):
# There must be at least 3 points
if n < 3:
return
# Find the leftmost point
l = Left_index(points)
pre = []
p = l
q = 0
while(True):
# Add current point to result
pre.append(p)
q = (p + 1) % n
for i in range(n):
# If i is more counterclockwise
# than current q, then update q
if(parallel(points[p],
points[i], points[q]) == 2):
q = i
p = q
# While it doesn't come to first point
if(p == l):
break
# Print Result
for each in pre:
print(points[each].x, points[each].y)
# Driver Code
algo = []
algo.append(func(0, 3))
algo.append(func(2, 2))
algo.append(func(1, 1))
algo.append(func(2, 1))
algo.append(func(3, 0))
algo.append(func(0, 0))
algo.append(func(3, 3))
# Function Call
preparata(algo, len(algo))
在上述过程中,通过使用变量m [i,j]表示1≤i,j≤N ,使用q [i,j,k]表示1≤i,j,k≤N ,使用O(N 3 )全局存储器。
- 初始化需要O(N 2 )时间的m []。
- 上述算法的第1步在使用3个处理器时花费O(1)时间。
- 在步骤2中,计算N 2个不同的m [i,j] 。
单个m [z,j]的计算涉及计算最少N个数,因此可以使用N 2个CRCW PRAM处理器在O(1)时间内完成。实际上,对于任何固定e> 0 ,也可以使用n (1 + e)个处理器在O(1)时间内计算出该最小值。
使用n (3 + e)普通CRCW PRAM处理器,可以在O(1)时间内完成第2步。因此,for循环以O(log N)时间运行。 M的最终计算也可以使用N 2个处理器在O(1)时间内完成。
通过对R的归纳可以证明上述算法的正确性。可以证明,在for循环的第r次迭代结束时,m [i,j]的值为min,最小值取{{,2,…,N}的所有元素序列使得k <2R 。上面的算法可以专门解决一些问题,包括传递闭包,连接的组件,最小生成树等。
令k1,k2,…,kn为输入序列。如果对数N,则Preparata的算法将输入划分为对数N部分K1,K2…。每个部分都有N / log N个键。
如果k是输入中的任何键,则其在输入中的排名计算如下。首先,对每个i计算k的秩Ri , 1 然后,k的总秩计算为 。使用上述算法的结果之一。
Preparata算法的细节在下面给出。
认为T(N)是使用N * log N个处理器的Preparata算法的运行时间。显然,步骤1花费T(N / log N)时间,而步骤2和3一起花费O(log(log N))时间。因此,有
T(n) = T(N/log N) + O(log(log N))
可以通过重复替换得到T(N)= O(log N)来解决。同样,每个步骤中使用的处理器数量为N * logN。
Preparata的排序算法
以下是Preparata排序算法的步骤:
- 如果N是一个小常数,请使用任何算法对键进行排序并退出。
- 将给定的N个键划分为对数N个部分,每个部分中包含N /(log N)个键。
- 递归并行地对每个部分进行排序,并为每个部分分配N个处理器。令S 1 , S 2 ,…, S log N为排序序列。
- 并行将S i与S j合并为1 这可以通过为每对(i,j)分配N / (log N)个处理器来完成。也就是说,使用N * log N个处理器,可以使用算法在O(log(log N))时间内完成此步骤。作为此合并步骤的副产品,计算S i ‘s(1 log N )的每一个中每个键的等级。
- 分配log N个处理器以计算原始输入中每个键的等级。通过添加在步骤2中为每个键计算的对数N等级,对所有键并行执行此操作。这可以使用前缀计算算法在O(log(log N))时间内完成。
- 最后,键按其顺序写入。
下面是上述方法的实现:
Python3
# Python program to implement Preparata's
# a time-optimal parallel algorithm
class func:
def __init__(self, x, y):
self.x = x
self.y = y
# Function to find the left index of
# the given set of points
def Left_index(points):
# Finding the point on plane
minn = 0
# Traverse the given points
for i in range(1, len(points)):
# Update the value of minn
if points[i].x < points[minn].x:
minn = i
elif points[i].x == points[minn].x:
if points[i].y > points[minn].y:
minn = i
# Return the value of min
return minn
# Function to perform the parallel
# process in the preparata's algorithm
# according to the value of p, q, r
def parallel(p, q, r):
# For the three-dimensional
val = (q.y - p.y) * (r.x - q.x) - \
(q.x - p.x) * (r.y - q.y)
if val == 0:
return 0
elif val > 0:
return 1
else:
return 2
# Function to perform the parallel
# process in the preparata's algorithm
def preparata(points, n):
# There must be at least 3 points
if n < 3:
return
# Find the leftmost point
l = Left_index(points)
pre = []
p = l
q = 0
while(True):
# Add current point to result
pre.append(p)
q = (p + 1) % n
for i in range(n):
# If i is more counterclockwise
# than current q, then update q
if(parallel(points[p],
points[i], points[q]) == 2):
q = i
p = q
# While it doesn't come to first point
if(p == l):
break
# Print Result
for each in pre:
print(points[each].x, points[each].y)
# Driver Code
algo = []
algo.append(func(0, 3))
algo.append(func(2, 2))
algo.append(func(1, 1))
algo.append(func(2, 1))
algo.append(func(3, 0))
algo.append(func(0, 0))
algo.append(func(3, 3))
# Function Call
preparata(algo, len(algo))
0 3
0 0
3 0
3 3
如果您希望与行业专家一起参加现场课程,请参阅《 Geeks现场课程》和《 Geeks现场课程美国》。