一、題目
考慮這樣一種排序問題,即無法準確的知道等排序的各個數字到底是多大.對於其中的每個數字,我們只知道它落在實軸上的某個區間內.亦即,給定的 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)這樣的情況,相等時要提取公因子,並更新主元(主元不一等是某個元素)
具體解釋都在代碼中
三、代碼
[cpp]
view plaincopyprint?
- #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;
- }
#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;}
轉載自:http://blog.csdn.net/mishifangxiangdefeng/article/details/7681109