线段排序问题-红黑树

#include <iostream>
#include <vector>
#include <cmath>
#include <algorithm>
#include <map>
using namespace std;

struct Point {
    double x, y;
    Point() {}
    Point(double _x, double _y) : x(_x), y(_y) {}
};

struct Line {
    Point p1, p2;
    double angle;
    Line() {}
    Line(Point _p1, Point _p2) : p1(_p1), p2(_p2) {
        angle = atan2(p2.y - p1.y, p2.x - p1.x);
    }
    bool operator < (const Line& other) const {
        return angle < other.angle;
    }
};

bool is_closed_loop(vector<Line>& lines) {
    map<Point, int> point_count;
    for (const Line& line : lines) {
        point_count[line.p1]++;
        point_count[line.p2]++;
    }
    for (const auto& p : point_count) {
        if (p.second != 2) {
            return false;
        }
    }
    return true;
}

vector<Line> reorder_lines(vector<Line>& lines) {
    // Sort the lines by their angle with respect to the first point
    sort(lines.begin(), lines.end());

    // Find the leftmost point
    Point leftmost_point = lines[0].p1;
    for (const Line& line : lines) {
        if (line.p1.x < leftmost_point.x) {
            leftmost_point = line.p1;
        }
        if (line.p2.x < leftmost_point.x) {
            leftmost_point = line.p2;
        }
    }

    // Build a map of the endpoints of each line
    map<Point, Line*> endpoint_map;
    for (Line& line : lines) {
        endpoint_map[line.p1] = &line;
        endpoint_map[line.p2] = &line;
    }

    // Reorder the lines starting from the leftmost point
    vector<Line> ordered_lines;
    Point current_point = leftmost_point;
    Line* current_line = endpoint_map[current_point];
    ordered_lines.push_back(*current_line);
    endpoint_map.erase(current_point);

    while (!endpoint_map.empty()) {
        // Find the next line in clockwise direction
        Line* next_line = nullptr;
        double min_angle_diff = INFINITY;
        for (auto& p : endpoint_map) {
            Line* line = p.second;
            if (line->p1 == current_point) {
                double angle_diff = line->angle - current_line->angle;
                if (angle_diff < 0) {
                    angle_diff += 2 * M_PI;
                }
                if (angle_diff < min_angle_diff) {
                    next_line = line;
                    min_angle_diff = angle_diff;
                }
            }
            if (line->p2 == current_point) {
                double angle_diff = current_line->angle - line->angle;
                if (angle_diff < 0) {
                    angle_diff += 2 * M_PI;
                }
                if (angle_diff < min_angle_diff) {
                    next_line = line;
                    min_angle_diff = angle_diff;
                }
            }
        }

        // Update the current point and line
        if (next_line == nullptr) {
            cerr << "Error: Failed to find the next line." << endl;
            exit(1);
        }
        current_line = next_line;
        ordered_lines.push_back(*current_line);
        endpoint_map.erase(current_line
//接下来是实现代码的第二部分,即排序和输出结果。

// 定义比较函数,用于平衡树排序
bool cmp(const Line &a, const Line &b) {
    if (a.maxY < b.minY) return true;
    if (a.minY > b.maxY) return false;
    if (a.k != b.k) return a.k < b.k;
    return a.b < b.b;
}

// 排序并输出结果
void sortAndOutput(vector<Line> &lines) {
    // 构造平衡树
    set<Line, bool(*)(const Line&, const Line&)> bst(cmp);
    for (const auto &line : lines) {
        bst.insert(line);
    }

    // 按顺序输出结果
    int cnt = 0;
    for (const auto &line : bst) {
        if (cnt == 0) {
            // 第一条线,保存为起点
            start = line.a;
        }
        else {
            // 连接两条线段
            end = line.b;
            cout << "(" << start.x << "," << start.y << ")" << "->" 
                 << "(" << end.x << "," << end.y << ")" << endl;
            start = end;
        }
        cnt++;
    }

    // 输出最后一条线段
    end = lines[0].a;
    cout << "(" << start.x << "," << start.y << ")" << "->" 
         << "(" << end.x << "," << end.y << ")" << endl;
}

这部分的主要工作是将线段按照从上到下、斜率、截距等方式排序,并使用平衡树进行排序。然后按照顺序输出线段,将它们组成轮廓。

最后,我们可以将上面的所有代码组合在一起,得到完整的算法实现:

#include <iostream>
#include <vector>
#include <algorithm>
#include <set>
using namespace std;

// 线段类
class Line {
public:
    Point a, b;  // 线段的两个端点
    double k, b; // 线段的斜率和截距
    double maxY, minY; // 线段的最大y值和最小y值

    Line(const Point &a, const Point &b) {
        // 确保a是上端点,b是下端点
        if (a.y > b.y) {
            this->a = b;
            this->b = a;
        }
        else {
            this->a = a;
            this->b = b;
        }

        // 计算斜率和截距
        if (this->a.x == this->b.x) {
            k = INFINITY;
            b = this->a.x;
        }
        else {
            k = (double)(this->a.y - this->b.y) / (double)(this->a.x - this->b.x);
            b = this->a.y - k * this->a.x;
        }

        // 计算最大y值和最小y值
        maxY = max(this->a.y, this->b.y);
        minY = min(this->a.y, this->b.y);
    }
};

// 定义比较函数,用于平

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

时间简史u

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值