一、題目
考慮這樣一種排序問題,即無法準確的知道等排序的各個數字到底是多大.對於其中的每個數字,我們只知道它落在實軸上的某個區間內.亦即,給定的 n 個形如[ai, bi ]的閉區間,其中ai,≤bi .演算法的目標是對這些區間進行模糊排序(fuzzy-sort),亦即,產生各區間的一個排序<i1, i2,
i3, i4,…in >,使得存在一個 cj ∈[ai, bi ],滿足c1≤c2≤…≤cn .a) 為n個區間的模糊排序設計一個演算法,你的演算法應該具有演算法的一般結構,它可以快速排序左部端點(即各ai ),也要能充分利用重疊區間來改善已耗用時間.(隨著各區間重疊得越來越多,對各區間的排序的問題會變得越來越容易,你的演算法應該能充分利用這種重疊.)b) 證明:
在一般情況下,你的演算法的區望已耗用時間為 O(n*lgn),但當所有的區間都重疊時,期望的已耗用時間為O(n) (亦即,當存在一個值 x, 使得對所有的 i, 都有x∈[ai, bi ] ).你的演算法不應顯式的檢查這種情況,而是應當隨著重疊量的增加,效能自然地有所改善.
二、思考
借用快排的劃分思路,以某個元素為主元,把地區劃分成三段,第一段都小於主元,第二段都等於主元
重點是劃分,區間如果重疊的部分,就把它們看做是相等的,並提取公用部分繼續劃分
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 randomfor(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);//sortQuickSort(A, 1, length_A);return 0;}