- 数据结构与算法
- DSA - 首页
- DSA - 概述
- DSA - 环境设置
- DSA - 算法基础
- DSA - 渐进分析
- 数据结构
- DSA - 数据结构基础
- DSA - 数据结构和类型
- DSA - 数组数据结构
- 链表
- DSA - 链表数据结构
- DSA - 双向链表数据结构
- DSA - 循环链表数据结构
- 栈与队列
- DSA - 栈数据结构
- DSA - 表达式解析
- DSA - 队列数据结构
- 搜索算法
- DSA - 搜索算法
- DSA - 线性搜索算法
- DSA - 二分搜索算法
- DSA - 插值搜索
- DSA - 跳跃搜索算法
- DSA - 指数搜索
- DSA - 斐波那契搜索
- DSA - 子列表搜索
- DSA - 哈希表
- 排序算法
- DSA - 排序算法
- DSA - 冒泡排序算法
- DSA - 插入排序算法
- DSA - 选择排序算法
- DSA - 归并排序算法
- DSA - 希尔排序算法
- DSA - 堆排序
- DSA - 桶排序算法
- DSA - 计数排序算法
- DSA - 基数排序算法
- DSA - 快速排序算法
- 图数据结构
- DSA - 图数据结构
- DSA - 深度优先遍历
- DSA - 广度优先遍历
- DSA - 生成树
- 树数据结构
- DSA - 树数据结构
- DSA - 树的遍历
- DSA - 二叉搜索树
- DSA - AVL树
- DSA - 红黑树
- DSA - B树
- DSA - B+树
- DSA - 伸展树
- DSA - 字典树
- DSA - 堆数据结构
- 递归
- DSA - 递归算法
- DSA - 使用递归实现汉诺塔
- DSA - 使用递归实现斐波那契数列
- 分治法
- DSA - 分治法
- DSA - 最大最小问题
- DSA - Strassen矩阵乘法
- DSA - Karatsuba算法
- 贪心算法
- DSA - 贪心算法
- DSA - 旅行商问题(贪心算法)
- DSA - Prim最小生成树
- DSA - Kruskal最小生成树
- DSA - Dijkstra最短路径算法
- DSA - 地图着色算法
- DSA - 分数背包问题
- DSA - 带截止日期的作业排序
- DSA - 最优合并模式算法
- 动态规划
- DSA - 动态规划
- DSA - 矩阵链乘法
- DSA - Floyd-Warshall算法
- DSA - 0-1背包问题
- DSA - 最长公共子序列算法
- DSA - 旅行商问题(动态规划)
- 近似算法
- DSA - 近似算法
- DSA - 顶点覆盖算法
- DSA - 集合覆盖问题
- DSA - 旅行商问题(近似算法)
- 随机算法
- DSA - 随机算法
- DSA - 随机快速排序算法
- DSA - Karger最小割算法
- DSA - Fisher-Yates洗牌算法
- DSA有用资源
- DSA - 问答
- DSA - 快速指南
- DSA - 有用资源
- DSA - 讨论
DSA - 几何算法
几何算法被定义为用于解决与几何形状及其属性相关的问题的程序。这些算法可以应用于点、线、多边形和其他几何图形等形状。我们可以在计算机图形学、计算机辅助设计、机器人技术和地理信息系统等各个领域找到其应用。
与几何算法相关的问题
可以使用几何算法解决的一些常见问题包括:
它可以用于解决不同多边形的面积,例如三角形、矩形等。
我们可以使用几何算法来查找两条线的交点。
计算凸包问题。
查找不同几何形状内部的点。
几何算法可以解决多边形三角剖分问题。
重要的几何算法
一些重要的几何算法包括:
Graham扫描算法
扫描线算法
Graham扫描算法
Graham扫描算法由Ronald Graham于1972年提出。该算法主要用于解决凸包问题和最大距离问题。它的应用也可以在其他领域看到,例如图像处理、机器人技术、配送系统等等。
以下步骤解释了Graham扫描算法的工作原理:
首先,找到y坐标最小的点。如果多个点共享最低的y坐标,则选择x坐标最低的点。
根据其余点相对于最低点的极角对它们进行排序。
对点排序后,从最低点和其他两个附加点开始。这三个点构成凸包的初始部分。
对于每个新点,确定从前两个点出发是否构成左转或右转。如果是右转,则倒数第二个点不在凸包内。
重复此过程,直到遇到左转集。
示例
以下示例以实际方式演示了Graham扫描算法的工作原理。
#include <stdio.h>
#include <stdlib.h>
// Structure for a point
struct Point2D {
int x, y;
};
// Global variable for the initial point
struct Point2D initialPoint;
// Function to get the second top element
struct Point2D getSecondTop(struct Point2D Stack[], int* top) {
return Stack[(*top)-1];
}
// Function to calculate square of distance between two points
int calcDistSq(struct Point2D p1, struct Point2D p2) {
return (p1.x - p2.x)*(p1.x - p2.x) + (p1.y - p2.y)*(p1.y - p2.y);
}
// Function to find orientation of ordered triplet of points
int getOrientation(struct Point2D p, struct Point2D q, struct Point2D r) {
int val = (q.y - p.y) * (r.x - q.x) - (q.x - p.x) * (r.y - q.y);
if (val == 0) return 0;
return (val > 0)? 1: 2;
}
// Function to compare two points
int comparePoints(const void *vp1, const void *vp2) {
struct Point2D *p1 = (struct Point2D *)vp1;
struct Point2D *p2 = (struct Point2D *)vp2;
int o = getOrientation(initialPoint, *p1, *p2);
if (o == 0)
return (calcDistSq(initialPoint, *p2) >= calcDistSq(initialPoint, *p1))? -1 : 1;
return (o == 2)? -1: 1;
}
// Function to compute the convex hull
void computeConvexHull(struct Point2D points[], int n) {
int ymin = points[0].y, min = 0;
for (int i = 1; i < n; i++) {
int y = points[i].y;
if ((y < ymin) || (ymin == y && points[i].x < points[min].x))
ymin = points[i].y, min = i;
}
// Swapping
struct Point2D temp = points[0];
points[0] = points[min];
points[min] = temp;
// Initial point
initialPoint = points[0];
// Sort array of points
qsort(&points[1], n-1, sizeof(struct Point2D), comparePoints);
int m = 1;
for (int i=1; i<n; i++) {
while (i < n-1 && getOrientation(initialPoint, points[i], points[i+1]) == 0)
i++;
points[m] = points[i];
m++;
}
if (m < 3) return;
// Stack to store the points on the convex hull
struct Point2D Stack[n];
int top = -1;
// Push the first three points into the stack
Stack[++top] = points[0];
Stack[++top] = points[1];
Stack[++top] = points[2];
// For the rest of the points
for (int i = 3; i < m; i++) {
while (getOrientation(getSecondTop(Stack, &top), Stack[top], points[i]) != 2)
top--;
Stack[++top] = points[i];
}
// Print the point
while (top != -1) {
struct Point2D p = Stack[top--];
printf("(%d, %d)\n", p.x, p.y);
}
}
int main() {
struct Point2D points[] = {{0, 1}, {1, 2}, {2, 3}, {4, 5}, {0, 0}, {2, 1}, {3, 1}, {3, 3}};
int n = sizeof(points)/ sizeof(points[0]);
computeConvexHull(points, n);
return 0;
}
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
// structure for a point
struct Point2D {
int x, y;
};
// initial point
Point2D initialPoint;
// Function to get the next top element
Point2D getSecondTop(vector<Point2D> &Stack) {
return Stack[Stack.size()-2];
}
// Function to calculate square of distance between two points
int calcDistSq(Point2D p1, Point2D p2) {
return (p1.x - p2.x)*(p1.x - p2.x) + (p1.y - p2.y)*(p1.y - p2.y);
}
// Function to find orientation of ordered triplet of points
int getOrientation(Point2D p, Point2D q, Point2D r) {
int val = (q.y - p.y) * (r.x - q.x) - (q.x - p.x) * (r.y - q.y);
if (val == 0) return 0;
// checking clock or counterclock wise
return (val > 0)? 1: 2;
}
// Function to compare two points
int comparePoints(const void *vp1, const void *vp2) {
Point2D *p1 = (Point2D *)vp1;
Point2D *p2 = (Point2D *)vp2;
int o = getOrientation(initialPoint, *p1, *p2);
if (o == 0)
return (calcDistSq(initialPoint, *p2) >= calcDistSq(initialPoint, *p1))? -1 : 1;
return (o == 2)? -1: 1;
}
// Function to compute the convex hull
void computeConvexHull(Point2D points[], int n) {
int ymin = points[0].y, min = 0;
for (int i = 1; i < n; i++) {
int y = points[i].y;
if ((y < ymin) || (ymin == y && points[i].x < points[min].x))
ymin = points[i].y, min = i;
}
// swapping
swap(points[0], points[min]);
// initial point
initialPoint = points[0];
// Sort array of points
qsort(&points[1], n-1, sizeof(Point2D), comparePoints);
int m = 1;
for (int i=1; i<n; i++) {
while (i < n-1 && getOrientation(initialPoint, points[i], points[i+1]) == 0)
i++;
points[m] = points[i];
m++;
}
if (m < 3) return;
// stack to store the points on the convex hull
vector<Point2D> Stack;
// Push the first three points into the stack
Stack.push_back(points[0]);
Stack.push_back(points[1]);
Stack.push_back(points[2]);
// For the rest of the points
for (int i = 3; i < m; i++) {
while (getOrientation(getSecondTop(Stack), Stack.back(), points[i]) != 2)
Stack.pop_back();
Stack.push_back(points[i]);
}
// Print the point
while (!Stack.empty()) {
Point2D p = Stack.back();
cout << "(" << p.x << ", " << p.y <<")" << endl;
Stack.pop_back();
}
}
int main() {
Point2D points[] = {{0, 1}, {1, 2}, {2, 3}, {4, 5}, {0, 0}, {2, 1}, {3, 1}, {3, 3}};
int n = sizeof(points)/ sizeof(points[0]);
computeConvexHull(points, n);
return 0;
}
import java.util.*;
// class to represent points with x and y coordinates
class Cords {
int xCoord, yCoord;
// Constructor
Cords(int x, int y) {
this.xCoord = x;
this.yCoord = y;
}
}
// class to find the convex hull
public class ConvexHullFinder {
// initial point
Cords initialPoint;
// Method to get the next to top element
Cords getSecondTop(Stack<Cords> stack) {
Cords temp = stack.pop();
Cords result = stack.peek();
stack.push(temp);
return result;
}
// Method to swap two points
void swapPoints(Cords p1, Cords p2) {
Cords temp = p1;
p1 = p2;
p2 = temp;
}
// Method to calculate the square of the distance between two points
int distanceSquare(Cords p1, Cords p2) {
return (p1.xCoord - p2.xCoord)*(p1.xCoord - p2.xCoord) + (p1.yCoord - p2.yCoord)*(p1.yCoord - p2.yCoord);
}
// Method to find the orientation of an ordered triplet of points
int findOrientation(Cords p, Cords q, Cords r) {
int value = (q.yCoord - p.yCoord) * (r.xCoord - q.xCoord) - (q.xCoord - p.xCoord) * (r.yCoord - q.yCoord);
if (value == 0) return 0;
// checking clock or counterclock wise
return (value > 0)? 1: 2;
}
// Method to check if two points have same slope
boolean sameSlope(Cords p1, Cords p2, Cords p3) {
return (p2.yCoord - p1.yCoord) * (p3.xCoord - p2.xCoord) == (p3.yCoord - p2.yCoord) * (p2.xCoord - p1.xCoord);
}
// method to calculate convex hull
void calculateConvexHull(Cords points[], int n) {
int yMin = points[0].yCoord, min = 0;
for (int i = 1; i < n; i++) {
int y = points[i].yCoord;
if ((y < yMin) || (yMin == y && points[i].xCoord < points[min].xCoord)) {
yMin = points[i].yCoord;
min = i;
}
}
// Swapping
swapPoints(points[0], points[min]);
// initial point
initialPoint = points[0];
// Sort array of points
Arrays.sort(points, new Comparator<Cords>() {
@Override
public int compare(Cords p1, Cords p2) {
if (sameSlope(initialPoint, p1, p2)) {
if (distanceSquare(initialPoint, p2) >= distanceSquare(initialPoint, p1)) {
return -1;
} else {
return 1;
}
}
if (findOrientation(initialPoint, p1, p2) == 2) {
return -1;
} else {
return 1;
}
}
});
// Create a stack and push the first three points into it
Stack<Cords> stack = new Stack<>();
stack.push(points[0]);
stack.push(points[1]);
stack.push(points[2]);
// keep removing top of stack while we get a clockwise turn
for (int i = 3; i < n; i++) {
while (stack.size() > 1 && findOrientation(getSecondTop(stack), stack.peek(), points[i]) != 2)
stack.pop();
stack.push(points[i]);
}
// print result
while (!stack.empty()) {
Cords p = stack.peek();
System.out.println("(" + p.xCoord + ", " + p.yCoord + ")");
stack.pop();
}
}
public static void main(String[] args) {
// points
Cords points[] = {new Cords(0, 1), new Cords(1, 2), new Cords(2, 3), new Cords(4, 5),
new Cords(0, 0), new Cords(2, 1), new Cords(3, 1), new Cords(3, 3)};
int n = points.length;
ConvexHullFinder finder = new ConvexHullFinder();
finder.calculateConvexHull(points, n);
}
}
from functools import cmp_to_key
import math
# Class to represent points with x and y coordinates
class Cords:
def __init__(self, x, y):
self.xCoord = x
self.yCoord = y
# Class to find the convex hull
class ConvexHullFinder:
# Initial point
initialPoint = None
# Method to get the next to top element
def getSecondTop(self, stack):
return stack[-2]
# Method to swap two points
def swapPoints(self, p1, p2):
return p2, p1
# Method to calculate the square of the distance between two points
def distanceSquare(self, p1, p2):
return (p1.xCoord - p2.xCoord)**2 + (p1.yCoord - p2.yCoord)**2
# Method to find the orientation of an ordered triplet of points
def findOrientation(self, p, q, r):
value = (q.yCoord - p.yCoord) * (r.xCoord - q.xCoord) - (q.xCoord - p.xCoord) * (r.yCoord - q.yCoord)
if value == 0: return 0
return 1 if value > 0 else 2
# Method to check if two points have same slope
def sameSlope(self, p1, p2, p3):
return (p2.yCoord - p1.yCoord) * (p3.xCoord - p2.xCoord) == (p3.yCoord - p2.yCoord) * (p2.xCoord - p1.xCoord)
# Method to calculate convex hull
def calculateConvexHull(self, points):
n = len(points)
ymin = points[0].yCoord
min = 0
for i in range(1, n):
y = points[i].yCoord
if (y < ymin) or (ymin == y and points[i].xCoord < points[min].xCoord):
ymin = points[i].yCoord
min = i
# Swapping
points[0], points[min] = self.swapPoints(points[0], points[min])
# Initial point
self.initialPoint = points[0]
# Sort array of points
def compare(p1, p2):
if self.sameSlope(self.initialPoint, p1, p2):
if self.distanceSquare(self.initialPoint, p2) >= self.distanceSquare(self.initialPoint, p1):
return -1
else:
return 1
if self.findOrientation(self.initialPoint, p1, p2) == 2:
return -1
else:
return 1
points = sorted(points, key=cmp_to_key(compare))
# Create a stack and push the first three points into it
stack = []
stack.append(points[0])
stack.append(points[1])
stack.append(points[2])
# Keep removing top of stack while we get a clockwise turn
for i in range(3, n):
while len(stack) > 1 and self.findOrientation(self.getSecondTop(stack), stack[-1], points[i]) != 2:
stack.pop()
stack.append(points[i])
# Print result
while stack:
p = stack[-1]
print("(", p.xCoord, ", ", p.yCoord, ")")
stack.pop()
# Points
points = [Cords(0, 1), Cords(1, 2), Cords(2, 3), Cords(4, 5),
Cords(0, 0), Cords(2, 1), Cords(3, 1), Cords(3, 3)]
finder = ConvexHullFinder()
finder.calculateConvexHull(points)
输出
(0, 1) (4, 5) (3, 1) (0, 0)
扫描线算法
扫描线算法用于解决涉及沿特定方向移动的对象的动态集合的几何和其他问题。假设一条垂直线(称为扫描线)从左到右穿过平面。当扫描线遇到线段的端点时,我们跟踪每个时间点哪些线段相交。通过分析交互,我们可以有效地解决各种问题。
以下是扫描线算法涉及的步骤:
扫描线从问题空间的一端开始,向另一端移动。
在规则的间隔内,算法更新一个合适的数据结构,具体取决于问题。根据扫描线位置的当前配置,它计算距离、交点、面积或其他所需的输出。
最终的数据结构或累积结果提供了问题的解决方案。
示例
以下是说明扫描线算法在各种编程语言中的示例。
#include <stdio.h>
#include <math.h>
// Structure to represent a coordinate
typedef struct {
double a, b;
} Coordinate;
// Structure to represent a line segment
typedef struct {
Coordinate start, end;
} Segment;
// Function to check if two line segments intersect
int checkIntersection(Segment s1, Segment s2) {
//
return 0;
}
// Function to find the intersection point of two line segments
Coordinate findIntersection(Segment s1, Segment s2) {
// coordinates of the start and end points of the first line segment
double a1 = s1.start.a, b1 = s1.start.b;
double a2 = s1.end.a, b2 = s1.end.b;
// coordinates of the start and end points of the second line segment
double a3 = s2.start.a, b3 = s2.start.b;
double a4 = s2.end.a, b4 = s2.end.b;
// Calculate the denominator of the intersection formula
double denominator = (b4 - b3) * (a2 - a1) - (a4 - a3) * (b2 - b1);
double numerator1 = (a4 - a3) * (b1 - b3) - (b4 - b3) * (a1 - a3);
double numerator2 = (a2 - a1) * (b1 - b3) - (b2 - b1) * (a1 - a3);
// If the denominator is zero, the lines are parallel
if (denominator == 0) {
return (Coordinate){ INFINITY, INFINITY };
}
double u = numerator1 / denominator;
double v = numerator2 / denominator;
if (u >= 0 && u <= 1 && v >= 0 && v <= 1) {
double a = a1 + u * (a2 - a1);
double b = b1 + u * (b2 - b1);
return (Coordinate){ a, b };
}
return (Coordinate){ INFINITY, INFINITY };
}
int main() {
// line segments
Segment s1 = { { 1, 2 }, { 3, 2 } };
Segment s2 = { { 2, 1 }, { 2, 3 } };
// If the line segments intersect
if (checkIntersection(s1, s2)) {
// Find the intersection point
Coordinate c = findIntersection(s1, s2);
printf("Intersection point: (%f, %f)\n", c.a, c.b);
} else {
printf("Segments do not intersect\n");
}
return 0;
}
#include <bits/stdc++.h>
#include <iostream>
using namespace std;
// structure to represent a coordinate
struct Coordinate {
double a, b;
};
// structure to represent a line segment
struct Segment {
Coordinate start, end;
};
// Function to check if two line segments intersect
bool checkIntersection(Segment s1, Segment s2)
{
//
}
// Function to find the intersection point of two line segments
Coordinate findIntersection(Segment s1, Segment s2) {
// coordinates of the start and end points of the first line segment
double a1 = s1.start.a, b1 = s1.start.b;
double a2 = s1.end.a, b2 = s1.end.b;
// coordinates of the start and end points of the second line segment
double a3 = s2.start.a, b3 = s2.start.b;
double a4 = s2.end.a, b4 = s2.end.b;
// Calculate the denominator of the intersection formula
double denominator = (b4 - b3) * (a2 - a1) - (a4 - a3) * (b2 - b1);
// Calculate the numerators of the intersection formula
double numerator1 = (a4 - a3) * (b1 - b3) - (b4 - b3) * (a1 - a3);
double numerator2 = (a2 - a1) * (b1 - b3) - (b2 - b1) * (a1 - a3);
// If the denominator is zero, the lines are parallel
if (denominator == 0) {
return { INFINITY, INFINITY };
}
double u = numerator1 / denominator;
double v = numerator2 / denominator;
// If u and v are both between 0 and 1, the line segments intersect
if (u >= 0 && u <= 1 && v >= 0 && v <= 1) {
// Calculate the coordinates of the intersection point
double a = a1 + u * (a2 - a1);
double b = b1 + u * (b2 - b1);
return { a, b };
}
// If u or v is not between 0 and 1, the line segments do not intersect
return { INFINITY, INFINITY };
}
int main(){
// line segments
Segment s1 = { { 1, 2 }, { 3, 2 } };
Segment s2 = { { 2, 1 }, { 2, 3 } };
// If the line segments intersect
if (checkIntersection(s1, s2)) {
// Find the intersection point
Coordinate c = findIntersection(s1, s2);
// Print the intersection point
cout << "Intersection point: (" << c.a << ", " << c.b << ")" << endl;
} else {
cout << "Segments do not intersect" << endl;
}
return 0;
}
public class Main {
// Class to represent a coordinate
static class Coordinate {
double a, b;
Coordinate(double a, double b) {
this.a = a;
this.b = b;
}
}
// Class to represent a line segment
static class Segment {
Coordinate start, end;
Segment(Coordinate start, Coordinate end) {
this.start = start;
this.end = end;
}
}
// Method to check if two line segments intersect
static boolean checkIntersection(Segment s1, Segment s2) {
return false;
}
// Method to find the intersection point of two line segments
static Coordinate findIntersection(Segment s1, Segment s2) {
double a1 = s1.start.a, b1 = s1.start.b;
double a2 = s1.end.a, b2 = s1.end.b;
double a3 = s2.start.a, b3 = s2.start.b;
double a4 = s2.end.a, b4 = s2.end.b;
double denominator = (b4 - b3) * (a2 - a1) - (a4 - a3) * (b2 - b1);
double numerator1 = (a4 - a3) * (b1 - b3) - (b4 - b3) * (a1 - a3);
double numerator2 = (a2 - a1) * (b1 - b3) - (b2 - b1) * (a1 - a3);
if (denominator == 0) {
return new Coordinate(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY);
}
double u = numerator1 / denominator;
double v = numerator2 / denominator;
if (u >= 0 && u <= 1 && v >= 0 && v <= 1) {
double a = a1 + u * (a2 - a1);
double b = b1 + u * (b2 - b1);
return new Coordinate(a, b);
}
return new Coordinate(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY);
}
public static void main(String[] args) {
Segment s1 = new Segment(new Coordinate(1, 2), new Coordinate(3, 2));
Segment s2 = new Segment(new Coordinate(2, 1), new Coordinate(2, 3));
if (checkIntersection(s1, s2)) {
Coordinate c = findIntersection(s1, s2);
System.out.println("Intersection point: (" + c.a + ", " + c.b + ")");
} else {
System.out.println("Segments do not intersect");
}
}
}
import math
# Class to represent a coordinate
class Coordinate:
def __init__(self, a, b):
self.a = a
self.b = b
# Class to represent a line segment
class Segment:
def __init__(self, start, end):
self.start = start
self.end = end
# Function to check if two line segments intersect
def checkIntersection(s1, s2):
# Implement intersection checking algorithm here
return False # Placeholder return statement
# Function to find the intersection point of two line segments
def findIntersection(s1, s2):
a1, b1 = s1.start.a, s1.start.b
a2, b2 = s1.end.a, s1.end.b
a3, b3 = s2.start.a, s2.start.b
a4, b4 = s2.end.a, s2.end.b
denominator = (b4 - b3) * (a2 - a1) - (a4 - a3) * (b2 - b1)
numerator1 = (a4 - a3) * (b1 - b3) - (b4 - b3) * (a1 - a3)
numerator2 = (a2 - a1) * (b1 - b3) - (b2 - b1) * (a1 - a3)
if denominator == 0:
return Coordinate(math.inf, math.inf)
u = numerator1 / denominator
v = numerator2 / denominator
if 0 <= u <= 1 and 0 <= v <= 1:
a = a1 + u * (a2 - a1)
b = b1 + u * (b2 - b1)
return Coordinate(a, b)
return Coordinate(math.inf, math.inf)
# Test the functions
s1 = Segment(Coordinate(1, 2), Coordinate(3, 2))
s2 = Segment(Coordinate(2, 1), Coordinate(2, 3))
if checkIntersection(s1, s2):
c = findIntersection(s1, s2)
print(f"Intersection point: ({c.a}, {c.b})")
else:
print("Segments do not intersect")
输出
Segments do not intersect