题目:
借用快排的划分思路,以某个元素为主元,把区域划分成三段,第一段都小于主元,第二段都等于主元
重点是划分,区间如果重叠的部分,就把它们看做是相等的,并提取公共部分继续划分
a.end < b.start ==> a < b
a.start > b.end ==> a > b
其它情况 ==> a = b
为了避免类似于(2,2) (7,7) (1,8)这样的情况,相等时要提取公因子,并更新主元(主元不一等是某个元素)
具体解释都在代码中
代码:
#include <iostream>
using namespace std;
struct node
{
int start;
int end;
bool operator<(const node & b)const
{
return end < b.start;
}
bool operator==(const node & b)const
{
return (end >= b .start) && (start <= b.end);
}
bool operator>(const node & b)const
{
return start > b.end;
}
};
//划分结果:0 -> a小于主元,a+1 -> b-1等于主元,b -> length_A大于主元
struct divid
{
int a;
int b;
};
node A[11];
int length_A = 10;
//按划分结果分三行显示
void Print(divid d)
{
int i = 1;
if(d.a > 0)
{
for(i = 1; i <= d.a; i++)
cout<<'('<<A[i].start<<','<<A[i].end<<") ";
cout<<endl;
i = d.a + 1;
}
if(d.b > 0)
{
for(; i < d.b; i++)
cout<<'('<<A[i].start<<','<<A[i].end<<") ";
cout<<endl;
i = d.b;
}
if(i <= length_A)
{
for(; i <= length_A; i++)
cout<<'('<<A[i].start<<','<<A[i].end<<") ";
cout<<endl;
}
cout<<endl;
}
//交换
void Exchange(node &a, node &b)
{
node temp;
temp = a;
a = b;
b = temp;
}
//划分是重点
divid Partition(node *A, int p, int r)
{
//先取任意一个元素为主元
node x = A[r];
int i = p-1, j = r+1, k = p;
while(k <=r && k < j)
{
//如果小于主元,交换到前面
if(A[k] < x)
{
i++;
Exchange(A[i], A[k]);
k++;
}
//如果大于,交换到后面
else if(A[k] > x)
{
j--;
Exchange(A[j], A[k]);
//这里不能k++,因为交换过来的元素也可能大于主元
}
else
{
//如果相等,不交换,但是要提取公因子
x.end = min(x.end, A[k].end);
x.start = max(x.start, A[k].start);
k++;
}
}
//返回划分结果
divid ret = {i, j};
if(ret.a < p)ret.a = -1;
if(ret.b > r)ret.b = -1;
Print(ret);
return ret;
}
void QuickSort(node *A, int p, int r)
{
if(p >= r)
return;
//把数组划分为三段
divid q = Partition(A, p, r);
//如果存在第一段,对第一段排序
if(q.a > 0)
QuickSort(A, p, q.a);
//如果存在第三段,对第三段排序
if(q.b > 0)
QuickSort(A, q.b, r);
}
int main()
{
int i, n;
cin>>n;
length_A = n;
//init data by random
for(i = 1; i <= length_A; i++)
{
A[i].start = rand() % 100;
A[i].end = rand() % 100;
if(A[i].start > A[i].end)
swap(A[i].start, A[i].end);
}
divid d = {-1, -1};
Print(d);
//sort
QuickSort(A, 1, length_A);
return 0;
}