给定平面上的一组点。该集合的凸包是包含其所有点的最小凸多边形。
我们强烈建议您先查看以下帖子。
如何检查两个给定的线段是否相交?
Jarvis 算法的思想很简单,我们从最左边的点(或 x 坐标值最小的点)开始,并沿逆时针方向不断包裹点。最大的问题是,给定一个点 p 作为当前点,如何在输出中找到下一个点?这个想法是在这里使用orientation()。下一个点被选为在逆时针方向击败所有其他点的点,即下一个点是 q 如果对于任何其他点 r,我们有“orientation(p, q, r) = 逆时针”。下面是详细的算法。
1)将 p 初始化为最左边的点。
2)在我们不回到第一个(或最左边)点的同时进行跟随。
….. a)下一个点 q 是三元组 (p, q, r) 对于任何其他点 r 是逆时针方向的点。为了找到这一点,我们简单地将 q 初始化为下一个点,然后遍历所有点。对于任何点 i,如果 i 更逆时针,即orientation(p, i, q) 是逆时针,那么我们将q 更新为i。我们最终的 q 值将是最逆时针的点。
….. b) next[p] = q(在输出凸包中将 q 作为 p 的下一个存储)。
….. c) p = q(将 p 设为 q 用于下一次迭代)。
下面是上述算法的实现。
C++
// A C++ program to find convex hull of a set of points. Refer
// https://www.geeksforgeeks.org/orientation-3-ordered-points/
// for explanation of orientation()
#include
using namespace std;
struct Point
{
int x, y;
};
// To find orientation of ordered triplet (p, q, r).
// The function returns following values
// 0 --> p, q and r are colinear
// 1 --> Clockwise
// 2 --> Counterclockwise
int orientation(Point p, Point q, Point r)
{
int val = (q.y - p.y) * (r.x - q.x) -
(q.x - p.x) * (r.y - q.y);
if (val == 0) return 0; // colinear
return (val > 0)? 1: 2; // clock or counterclock wise
}
// Prints convex hull of a set of n points.
void convexHull(Point points[], int n)
{
// There must be at least 3 points
if (n < 3) return;
// Initialize Result
vector hull;
// Find the leftmost point
int l = 0;
for (int i = 1; i < n; i++)
if (points[i].x < points[l].x)
l = i;
// Start from leftmost point, keep moving counterclockwise
// until reach the start point again. This loop runs O(h)
// times where h is number of points in result or output.
int p = l, q;
do
{
// Add current point to result
hull.push_back(points[p]);
// Search for a point 'q' such that orientation(p, q,
// x) is counterclockwise for all points 'x'. The idea
// is to keep track of last visited most counterclock-
// wise point in q. If any point 'i' is more counterclock-
// wise than q, then update q.
q = (p+1)%n;
for (int i = 0; i < n; i++)
{
// If i is more counterclockwise than current q, then
// update q
if (orientation(points[p], points[i], points[q]) == 2)
q = i;
}
// Now q is the most counterclockwise with respect to p
// Set p as q for next iteration, so that q is added to
// result 'hull'
p = q;
} while (p != l); // While we don't come to first point
// Print Result
for (int i = 0; i < hull.size(); i++)
cout << "(" << hull[i].x << ", "
<< hull[i].y << ")\n";
}
// Driver program to test above functions
int main()
{
Point points[] = {{0, 3}, {2, 2}, {1, 1}, {2, 1},
{3, 0}, {0, 0}, {3, 3}};
int n = sizeof(points)/sizeof(points[0]);
convexHull(points, n);
return 0;
}
Java
// Java program to find convex hull of a set of points. Refer
// https://www.geeksforgeeks.org/orientation-3-ordered-points/
// for explanation of orientation()
import java.util.*;
class Point
{
int x, y;
Point(int x, int y){
this.x=x;
this.y=y;
}
}
class GFG {
// To find orientation of ordered triplet (p, q, r).
// The function returns following values
// 0 --> p, q and r are colinear
// 1 --> Clockwise
// 2 --> Counterclockwise
public static int orientation(Point p, Point q, Point r)
{
int val = (q.y - p.y) * (r.x - q.x) -
(q.x - p.x) * (r.y - q.y);
if (val == 0) return 0; // collinear
return (val > 0)? 1: 2; // clock or counterclock wise
}
// Prints convex hull of a set of n points.
public static void convexHull(Point points[], int n)
{
// There must be at least 3 points
if (n < 3) return;
// Initialize Result
Vector hull = new Vector();
// Find the leftmost point
int l = 0;
for (int i = 1; i < n; i++)
if (points[i].x < points[l].x)
l = i;
// Start from leftmost point, keep moving
// counterclockwise until reach the start point
// again. This loop runs O(h) times where h is
// number of points in result or output.
int p = l, q;
do
{
// Add current point to result
hull.add(points[p]);
// Search for a point 'q' such that
// orientation(p, q, x) is counterclockwise
// for all points 'x'. The idea is to keep
// track of last visited most counterclock-
// wise point in q. If any point 'i' is more
// counterclock-wise than q, then update q.
q = (p + 1) % n;
for (int i = 0; i < n; i++)
{
// If i is more counterclockwise than
// current q, then update q
if (orientation(points[p], points[i], points[q])
== 2)
q = i;
}
// Now q is the most counterclockwise with
// respect to p. Set p as q for next iteration,
// so that q is added to result 'hull'
p = q;
} while (p != l); // While we don't come to first
// point
// Print Result
for (Point temp : hull)
System.out.println("(" + temp.x + ", " +
temp.y + ")");
}
/* Driver program to test above function */
public static void main(String[] args)
{
Point points[] = new Point[7];
points[0]=new Point(0, 3);
points[1]=new Point(2, 3);
points[2]=new Point(1, 1);
points[3]=new Point(2, 1);
points[4]=new Point(3, 0);
points[5]=new Point(0, 0);
points[6]=new Point(3, 3);
int n = points.length;
convexHull(points, n);
}
}
// This code is contributed by Arnav Kr. Mandal.
Python3
# C# program to find convex hull of a set of points. Refer
# https://www.geeksforgeeks.org/orientation-3-ordered-points/
# for explanation of orientation()
# point class with x, y as point
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def Left_index(points):
'''
Finding the left most point
'''
minn = 0
for i in range(1,len(points)):
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 minn
def orientation(p, q, r):
'''
To find orientation of ordered triplet (p, q, r).
The function returns following values
0 --> p, q and r are colinear
1 --> Clockwise
2 --> Counterclockwise
'''
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
def convexHull(points, n):
# There must be at least 3 points
if n < 3:
return
# Find the leftmost point
l = Left_index(points)
hull = []
'''
Start from leftmost point, keep moving counterclockwise
until reach the start point again. This loop runs O(h)
times where h is number of points in result or output.
'''
p = l
q = 0
while(True):
# Add current point to result
hull.append(p)
'''
Search for a point 'q' such that orientation(p, q,
x) is counterclockwise for all points 'x'. The idea
is to keep track of last visited most counterclock-
wise point in q. If any point 'i' is more counterclock-
wise than q, then update q.
'''
q = (p + 1) % n
for i in range(n):
# If i is more counterclockwise
# than current q, then update q
if(orientation(points[p],
points[i], points[q]) == 2):
q = i
'''
Now q is the most counterclockwise with respect to p
Set p as q for next iteration, so that q is added to
result 'hull'
'''
p = q
# While we don't come to first point
if(p == l):
break
# Print Result
for each in hull:
print(points[each].x, points[each].y)
# Driver Code
points = []
points.append(Point(0, 3))
points.append(Point(2, 2))
points.append(Point(1, 1))
points.append(Point(2, 1))
points.append(Point(3, 0))
points.append(Point(0, 0))
points.append(Point(3, 3))
convexHull(points, len(points))
# This code is contributed by
# Akarsh Somani, IIIT Kalyani
C#
// C# program to find convex hull of a set of points. Refer
// https://www.geeksforgeeks.org/orientation-3-ordered-points/
// for explanation of orientation()
using System;
using System.Collections.Generic;
public class Point
{
public int x, y;
public Point(int x, int y)
{
this.x = x;
this.y = y;
}
}
public class GFG
{
// To find orientation of ordered triplet (p, q, r).
// The function returns following values
// 0 --> p, q and r are colinear
// 1 --> Clockwise
// 2 --> Counterclockwise
public static int orientation(Point p, Point q, Point r)
{
int val = (q.y - p.y) * (r.x - q.x) -
(q.x - p.x) * (r.y - q.y);
if (val == 0) return 0; // collinear
return (val > 0)? 1: 2; // clock or counterclock wise
}
// Prints convex hull of a set of n points.
public static void convexHull(Point []points, int n)
{
// There must be at least 3 points
if (n < 3) return;
// Initialize Result
List hull = new List();
// Find the leftmost point
int l = 0;
for (int i = 1; i < n; i++)
if (points[i].x < points[l].x)
l = i;
// Start from leftmost point, keep moving
// counterclockwise until reach the start point
// again. This loop runs O(h) times where h is
// number of points in result or output.
int p = l, q;
do
{
// Add current point to result
hull.Add(points[p]);
// Search for a point 'q' such that
// orientation(p, q, x) is counterclockwise
// for all points 'x'. The idea is to keep
// track of last visited most counterclock-
// wise point in q. If any point 'i' is more
// counterclock-wise than q, then update q.
q = (p + 1) % n;
for (int i = 0; i < n; i++)
{
// If i is more counterclockwise than
// current q, then update q
if (orientation(points[p], points[i], points[q])
== 2)
q = i;
}
// Now q is the most counterclockwise with
// respect to p. Set p as q for next iteration,
// so that q is added to result 'hull'
p = q;
} while (p != l); // While we don't come to first
// point
// Print Result
foreach (Point temp in hull)
Console.WriteLine("(" + temp.x + ", " +
temp.y + ")");
}
/* Driver code */
public static void Main(String[] args)
{
Point []points = new Point[7];
points[0]=new Point(0, 3);
points[1]=new Point(2, 3);
points[2]=new Point(1, 1);
points[3]=new Point(2, 1);
points[4]=new Point(3, 0);
points[5]=new Point(0, 0);
points[6]=new Point(3, 3);
int n = points.Length;
convexHull(points, n);
}
}
// This code is contributed by Princi Singh
Javascript
输出:输出是凸包的点。
(0, 3)
(0, 0)
(3, 0)
(3, 3)
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。