题目:
考虑这样一种排序问题,我们无法知道准确待排序的数字是什么。但对于每一个数,我们知道它属于实数轴上的某个区间。也就是说,我们得到了n个形如[
解答:
对于该问题的说明,笔者看了知乎上的一篇回答和一篇CSDN上的博客才弄懂题目的意思。
算法导论上的原题提到“你的算法应该有算法的一般结构,它可以对左边端点(即
对于该题,可以利用针对相同元素的快速排序中的思想,将某些重叠的区间归为相等,即针对相同元素的快速排序中的中间部分[q…t],由此来改善该算法的时间性能,使区间重叠越多,模糊排序越容易。该算法的PARTITION同样返回两个值如之前的针对相同元素的快速排序中的PARTITION。
现在我们来定义哪种某些重叠的区间可以归为相等的区间。我们用如下结构体表示区间:
typedef struct interval {
int start;
int end;
} interval_t;
对于两个interval_t的a和pivot,如果:
1.
2.
3.
算法实现如下:
void swap_interval(interval_t *p1, interval_t *p2) {
interval_t temp = *p1;
*p1 = *p2;
*p2 = temp;
}
int comp_interval(interval_t a, interval_t pivot) {
if (a.end < pivot.start) {
return -1;
} else if (a.start <= pivot.start && pivot.start <= a.end) {
return 0;
} else if (a.start > pivot.start) {
return 1;
} else {
fprintf(stderr, "error code\n");
return 404;
}
}
interval_t interval_partitoin(interval_t *source, int head, int tail) {
swap_interval(source + rand() % (tail - head + 1) + head, source + tail);
interval_t pivot = source[tail];
int q = head - 1, t = head - 1;
int j = head;
for (j = head; j < tail; j++) {
int comp_result = comp_interval(source[j], pivot);
if (comp_result == 0) {
t++;
swap_interval(source + j, source + t);
} else if (comp_result == -1) {
q++;
swap_interval(source + j, source + q);
t++;
if (t != q)
swap_interval(source + j, source + t);
}
}
q++;
swap_interval(source + tail, source + q);
t++;
if (q != t)
swap_interval(source + tail, source + t);
interval_t result = {q, t};
return result;
}
void fuzzy_quick_sort_for_interval(interval_t *source, int head, int tail) {
if (head >= tail)
return;
interval_t mid = interval_partitoin(source, head, tail);
fuzzy_quick_sort_for_interval(source, head, mid.start - 1);
fuzzy_quick_sort_for_interval(source, mid.end + 1, tail);
}
代码未经测试,与针对相同元素的快速排序相比只是改了判断大小的逻辑comp_interval和交换的逻辑swap_interval。