📜  Preparata算法

📅  最后修改于: 2021-08-27 04:35:53             🧑  作者: Mango

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的秩Ri1 然后,k的总秩计算为\sum_{i}^{log N} R_i 。使用上述算法的结果之一。

Preparata算法的细节在下面给出。

认为T(N)是使用N * log N个处理器的Preparata算法的运行时间。显然,步骤1花费T(N / log N)时间,而步骤2和3一起花费O(log(log N))时间。因此,有

可以通过重复替换得到T(N)= O(log N)来解决。同样,每个步骤中使用的处理器数量为N * logN。

Preparata的排序算法

以下是Preparata排序算法的步骤:

  • 如果N是一个小常数,请使用任何算法对键进行排序并退出。
  • 将给定的N个键划分为对数N个部分,每个部分中包含N /(log N)个键。
  • 递归并行地对每个部分进行排序,并为每个部分分配N个处理器。S 1S 2 ,…, S log N为排序序列。
  • 并行将S iS 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现场课程美国》。