#include<iostream>
#include<stdlib.h>
#include<cmath>
using namespace std;
#define xmin -1000
#define xmax 1000
#define ymin -1000
#define ymax 1000
struct pointnode
{
int x;
int y;
};
struct chainnode
{
struct pointnode point;
struct chainnode *leftnode;
struct chainnode *rightnode;
};
class doublelist
{
public:
doublelist(int initiationsize=5);
~doublelist();
void insertnode(int index,struct pointnode);
void printlist();
void erasenode(int index);
void erasenode(chainnode* x);
void printreverse();
int size(){return listsize;}
int issameline();
struct chainnode* get(int index);
pointnode makepointx(pointnode x1,pointnode x2,pointnode x3);
pointnode findonepoint(int index);
void sortlist();
void convexclosure();
int is_ins(pointnode z);
private:
chainnode* firstnode;
int listsize;
};
int obtuseangle(pointnode x,pointnode rx,pointnode rrx);
double distance(pointnode z,pointnode x);
double polar(pointnode z,pointnode x);
void doublelist::convexclosure()
{
if(listsize<3)return;
//若共线返回两端点,未实现
sortlist();
cout<<endl<<"after sort:"<<endl;
printlist();
pointnode yminnode=findonepoint(4);
chainnode *p=firstnode,*x,*rx,*rrx;
for(int i=0;i<listsize;i++)
{
if((p->point.x==yminnode.x)&&(p->point.y==yminnode.y))
break;
p=p->rightnode;
}
cout<<"the point min y is:"<<p->point.x<<","<<p->point.y<<endl;
int firstflag=0;
x=p;
rx=x->rightnode;
for(;(p!=rx)||(!firstflag);)
{
rrx=rx->rightnode;
if(obtuseangle(x->point,rx->point,rrx->point))
{
x=rx;rx=rx->rightnode;
firstflag++;
}
else
{
erasenode(x);//erase x next node;
rx=x;
x=x->leftnode;
}
}
}
int main(void)
{
doublelist one;
int n;
cin>>n;
struct pointnode z;
for(int i=0;i<n;i++)
{
cin>>z.x>>z.y;
one.insertnode(i,z);
}
// one.printreverse();
one.convexclosure();
one.printlist();
return 0;
}
/*
13
1 0
3 3
5 4
4 5
4 7
2 6
1 5
-1 7
-2 4
-3 3
-4 2
-3 0
-1 3
13
-1 3
-1 7
-2 4
4 5
1 0
3 3
5 4
-3 3
-3 0
-4 2
4 7
1 5
2 6
*/
doublelist::doublelist(int initiationsize)
{
firstnode=NULL;
listsize=0;
}
doublelist::~doublelist()
{
for(int i=0;i<listsize;i++)
{
struct chainnode* tempnode=firstnode->rightnode;
delete firstnode;;
firstnode=tempnode;
}
}
void doublelist::printlist()
{
struct chainnode *tempnode=firstnode;
cout<<"this chain has node:"<<listsize<<endl;
for(int i=0;i<listsize;i++)
{
cout<<tempnode->point.x<<" "<<tempnode->point.y<<endl;
tempnode=tempnode->rightnode;
}
cout<<endl;
}
void doublelist::erasenode(int index)
{
struct chainnode* tempnode=firstnode,*deletenode;
for(int i=0;i<index-1;i++)
tempnode=tempnode->rightnode;
deletenode=tempnode->rightnode;
tempnode->rightnode=tempnode->rightnode->rightnode;
tempnode->rightnode->leftnode=tempnode;
listsize--;
}
void doublelist::erasenode(chainnode* x)
{
struct chainnode *tempnode=x;
if(x->rightnode==firstnode)
firstnode=x->rightnode->rightnode;
tempnode->rightnode=tempnode->rightnode->rightnode;
tempnode->rightnode->leftnode=tempnode;
listsize--;
}
void doublelist::printreverse()
{
cout<<"print reverse list is:"<<endl;
struct chainnode *tempnode=firstnode->leftnode;
tempnode=tempnode->leftnode;
struct chainnode *endnode=tempnode;
while(tempnode->leftnode!=endnode)
{
cout<<tempnode->point.x<<" "<<tempnode->point.y<<endl;
tempnode=tempnode->leftnode;
}
cout<<tempnode->point.x<<" "<<tempnode->point.y<<endl;
cout<<endl;
}
void doublelist::insertnode(int index,struct pointnode z)
{
if(listsize==0)
{
struct chainnode *tempnode=new struct chainnode;
tempnode->point=z;
tempnode->rightnode=tempnode;
tempnode->leftnode=tempnode;
firstnode=tempnode;
}
else
{
if(index==0)
{
struct chainnode *tempnode=new struct chainnode;
tempnode->point=z;
tempnode->rightnode=firstnode;
tempnode->leftnode=firstnode->leftnode;
firstnode->leftnode=tempnode;
firstnode=tempnode;
}
else
{
struct chainnode* tempnode=firstnode;
for(int i=0;i<index-1;i++)
tempnode=tempnode->rightnode;
tempnode->rightnode=new chainnode{z,tempnode,tempnode->rightnode};
tempnode->rightnode->rightnode->leftnode=tempnode->rightnode;
}}
listsize++;
}
int doublelist::issameline()
{
if(listsize<3)return -1;
chainnode *tempnode=firstnode;
pointnode x,rx,rrx;
for(int i=0;i<(listsize-2);i++)
{
x=tempnode->point;
rx=tempnode->rightnode->point;
rrx=tempnode->rightnode->rightnode->point;
if(((rx.y-x.y)*1.0/(rx.x-x.x))!=((rx.y-rrx.y)*1.0/(rx.x-rrx.x)))
return 0;
tempnode=tempnode->rightnode;
}
return 1;
}
struct chainnode* doublelist::get(int index)
{
int i=0;
chainnode *tempnode=firstnode;
if(index==0)
return tempnode;
else
{
while((i++<(index-1))&&(tempnode->rightnode!=NULL))
tempnode=tempnode->rightnode;
return tempnode->rightnode;
}
}
pointnode doublelist::makepointx(pointnode x1,pointnode x2,pointnode x3)
{
int x4,y4,y41,y42,flag=0;
pointnode z=x1;
while((!flag)||(is_ins(z)))//直到找到一点合适z
{
x4=rand()%(x3.x-x1.x-1)+x1.x+1;
if(x3.x>x2.x)
{
if(x4<=x2.x)
y41=(int)(((x2.y-x1.y)*x4+(x1.y*x2.x-x2.y*x1.x))/(x2.x-x1.x));
else
y41=(int)(((x3.y-x2.y)*x4+(x2.y*x3.x-x3.y*x2.x))/(x3.x-x2.x));
y42=(int)(((x3.y-x1.y)*x4+(x1.y*x3.x-x3.y*x1.x))/(x3.x-x1.x));
}
else if(x3.x<x2.x)
{
y41=(int)(((x2.y-x1.y)*x4+(x1.y*x2.x-x2.y*x1.x))/(x2.x-x1.x));
if(x4>x3.x)
y42=(int)(((x3.y-x2.y)*x4+(x2.y*x3.x-x3.y*x2.x))/(x3.x-x2.x));
else
y42=(int)(((x3.y-x1.y)*x4+(x1.y*x3.x-x3.y*x1.x))/(x3.x-x1.x));
}
else
{
y41=(int)(((x2.y-x1.y)*x4+(x1.y*x2.x-x2.y*x1.x))/(x2.x-x1.x));
y42=(int)(((x3.y-x1.y)*x4+(x1.y*x3.x-x3.y*x1.x))/(x3.x-x1.x));
}
if(y41<=(y42+1))continue;
else y4=rand()%(y41-y42-1)+y42+1;
if((y4<=y42)||(y4>=y41))
flag=0;
else
flag=1;
z.x=x4;
z.y=y4;
}
return z;
}
int obtuseangle(pointnode x,pointnode rx,pointnode rrx)
{//greater than 180 return 1;
struct pointnode vectorquantity1,vectorquantity2;
vectorquantity1.x=-(x.y-rx.y);
vectorquantity1.y=x.x-rx.x;
vectorquantity2.x=rrx.x-rx.x;
vectorquantity2.y=rrx.y-rx.y;
if((vectorquantity1.x*vectorquantity2.x+vectorquantity1.y*vectorquantity2.y)<0)
return 1;
else
return 0;
}
double distance(pointnode z,pointnode x)
{
return sqrt((x.x-z.x)*(x.x-z.x)+(x.y-z.y)*(x.y-z.y));
}
double polar(pointnode z,pointnode x)
{
if((x.x>=z.x)&&(x.y<=z.y))
return (x.x-z.x)/distance(z,x);
else if((x.x>=z.x)&&(x.y>z.y))
return 2-((x.x-z.x)/distance(z,x));
else if((x.x<z.x)&&(x.y>=z.y))
return (z.x-x.x)/distance(z,x)+2;
//if((x.x<z.x)&&(x.y<z.y))
else
return 4-((z.x-x.x)/distance(z,x));
}
pointnode doublelist::findonepoint(int index)
{//1-xmin,2-ymax,3-xmax,4-ymin
pointnode datanode;
chainnode* tempnode=firstnode;
datanode=firstnode->point;
for(int i=0;i<listsize;i++)
{
if((index==1)&&(tempnode->point.x<datanode.x))
datanode=tempnode->point;
if((index==2)&&(tempnode->point.y>datanode.y))
datanode=tempnode->point;
if((index==3)&&(tempnode->point.x>datanode.x))
datanode=tempnode->point;
if((index==4)&&(tempnode->point.y<datanode.y))
datanode=tempnode->point;
tempnode=tempnode->rightnode;
}
return datanode;
}
void doublelist::sortlist()
{
int i,j;
pointnode z=makepointx(findonepoint(1),findonepoint(2),findonepoint(3));
cout<<"point rand make z is:"<<z.x<<","<<z.y<<endl;
chainnode* inode,*jnode;
pointnode tempnode;
for(i=0;i<listsize;i++)
for(j=i+1;j<listsize;j++)
{
inode=get(i);
jnode=get(j);
if(polar(z,jnode->point)<polar(z,inode->point)) {tempnode=inode->point;inode->point=jnode->point;jnode->point=tempnode;}
else if((polar(z,jnode->point)==polar(z,inode->point))&&(distance(z,jnode->point)<distance(z,inode->point)))
{tempnode=inode->point;inode->point=jnode->point;jnode->point=tempnode;}
}
}
int doublelist::is_ins(pointnode z)
{
int flag=0;
chainnode* tempnode=firstnode;
for(int i=0;i<listsize;i++)
{
if((tempnode->point.x==z.x)&&(tempnode->point.y==z.y))
{flag=1; break;}
tempnode=tempnode->rightnode;
}
return flag;
}