讲解ppt
#include
#include
#include
#include
using namespace std;
vector> findNodes(vector>& arr);
bool isOrigin(vector& a, vector& b);
bool isOnLeft(vector curNode, vector topMinuOne, vector top);
double distance(vector &a, vector &b);
void test1();
void test2();
int main() {
test1(); //当坐标数组为空时候,测试1
test2(); //当扫描时候有多个坐标在一条直线上时,测试2
}
void test1() {
cout << "test1()输入为空数组:" << endl;
vector> temp;
if (findNodes(temp).size() == 0) {
cout << "test1()输出为空数组,正确" << endl << endl << "-------------" << endl;
}
else {
cout << "test1()输出不为空数组,错误:" << endl << endl << "--------------" << endl;
}
}
void test2() {
vector> temp = { { 1,1 },{ 2,2 },{ 2,0 },{ 2,4 },{ 3,3 },{ 4,2 } };
//vector> temp = { {1,1},{2,1},{3,1},{2,2},{3,3},{2,3},{1,3} };
//vector> temp = { {1,1},{1,1},{1,1},{1,1},{1,1},{1,1} };
cout << "test2()输入是: " << "{
{1,1},{2,2},{2,0},{2,4},{3,3},{4,2}}" << endl;
vector> ans = findNodes(temp);
cout << "test2()输出结果是:{";
for (int i = 0; i < ans.size(); i++) {
cout << '{' << ans[i][0] << "," << ans[i][1] << "},";
}
cout << '}' << endl;
cout << "test2()正确结果是:" << "{
{2,0},{4,2},{2,4},{1,1}}";
}
//Description: 找出凸包上的坐标点,会先找到一个极点然后进行逆时针扫描
vector> findNodes(vector>& arr) {
sort(arr.begin(), arr.end(), isOrigin); //排序目的有两个,一是用于查找第一个节点(左下角)
int nodeNum = arr.size(); //二是为了给坐标点去重
for (int i = 0; i < nodeNum - 1; i++) {
if ((arr[i][0] == arr[i + 1][0]) && (arr[i][1] == arr[i + 1][1])) {
arr.erase(arr.begin() + i);
nodeNum = arr.size();
i--;
}
}
nodeNum = arr.size(); //计算去重后剩下的坐标点的个数
if (nodeNum <= 2) { //数组为空或者坐标点为1,2这些简单情况就直接返回
return arr;
}
int originPoint = 0;
vector> ans;
ans.push_back(arr[0]); //把极点先存入
int curPoint = originPoint;
do {
int nextPoint = -1; //表示随便选一个点就可以
for (int i = 0; i < arr.size(); i++) {
if (i != curPoint && i != nextPoint && (nextPoint == -1 || !isOnLeft(arr[i], arr[curPoint], arr[nextPoint]))) {
nextPoint = i;
}
}
ans.push_back(arr[nextPoint]);
curPoint = nextPoint;
} while (originPoint != curPoint);
ans.pop_back();
return ans;
}
//Description: 判断三点构成的连线的相对位置
bool isOnLeft(vector cur, vector topMinuOne, vector top) {
int cross = (cur[0] - topMinuOne[0])*(top[1] - topMinuOne[1]) - (top[0] - topMinuOne[0])*(cur[1] - topMinuOne[1]); //x1y2-x2y1 计算叉积
if (cross > 0) {
return false;
}
else if (cross < 0) {
return true;
}
else { //叉积等于0的时候,说明点共线,要进行判断一下
if (distance(cur, topMinuOne) > distance(top, topMinuOne)) {
return false;
}
return true;
}
}
bool isOrigin(vector& a, vector& b) {
if (a[1] == b[1]) { //纵坐标相等的时候,横坐标小的在前
return a[0] < b[0];
}
return a[1] < b[1];
}
double distance(vector &a, vector &b) {
return (pow((a[0] - b[0]), 2) + pow((a[1] - b[1]), 2));
}