線性的時間內選擇出rank n的元素

/*


  2013年10月3日
  by --- acton
在線性的時間內選擇出rank n 的元素,一般來說找最值是特殊的情況,但是這裏列出的算法是查找一般的情況,也適用於最值的情況


這個算法是基於快速排序上面的Partition上寫的,但是這個算法的遞歸樹卻是 T(n) = T(n/2) + O(n), 解得遞歸樹的運行的時間爲O(n)
把問題的規模每次都縮小,但是也有極端的情況,與快速排序的原因一樣,也是由於pivotkey的選取的原因可能導致劃分出現一邊沒有元素,
另一邊爲n-1個元素,則T(n)= T(n-1) + O(n) 同樣會是O(n2)的複雜度


說到找特殊值的話,這裏說下找最小和最大值分析:


做法一:
void Select(int A[], int p ,int r ){
int Max = -INFINITY;
int Min = INFINITY;


for (int i= 0 ; i < N ; i ++ ){
if (A[i] < Min){
Min = A[i];
}
if (A[i] > Max){
Max = A[i];
}
}
}


  做法二:
  解法一中需要比較2(n-1)次,它的做法是把每一個元素與最大和最小值都進行了比較,現在我們每次成對的處理元素,先將輸入的一對元素做兩兩之間的比較
  然後把兩兩中較大的與MAX比較,較小的與MIN比較,這樣的話,總共只需要比較3(n/2)次就可以得到最終的結果了


*/


如下的代碼中我先對與要進行選擇的相同的一個數組進行快速排序(未實現RANDOMIZE),打印結果,以便查看Select的正確與否,然後在進行Select選擇打印


# include <stdio.h>
# define N  7


void Exchange(int * p ,int * q){
	int temp = * p ;
	*p = *q;
	*q = temp;
}
int  Partition(int A[], int p, int r){
	int pivotkey =  A[r];
	int i = p - 1;


	for (int j = p ; j < r ; j ++ ){
		if ( A[j] <= pivotkey ){
			i ++ ;
			Exchange(&A[i],&A[j]);
		}
	}


	Exchange(&A[i+1],&A[r]);
	return i+1;
}
int Select(int A[], int p , int r , int i){
	if (p == r){
		return A[r];
	}
	int pivotkey = Partition(A,p,r);
	int k = pivotkey - p +1;
	if (i == k){
		return A[pivotkey];
	}else if (i < k){
		return Select(A,p,pivotkey-1,i);
	}else{
		return Select(A,pivotkey+1,r,i-pivotkey);
	}
}


void Quick_Sort(int A[], int p, int r){
	if (p < r){
		int pivotKey = Partition(A,p,r);
		Quick_Sort(A,p,pivotKey-1);
		Quick_Sort(A,pivotKey+1,r);
	}
}


int main(void){


	int A[] = {9,2,8,10,28,67,3};
	int B[] = {9,2,8,10,28,67,3};


	Quick_Sort(B,0,6);
	for(int i = 0 ; i < 7 ; i ++){
		printf("%5d  ",B[i]);
	}
	putchar(10);
	int rank ;
	while (1){
		scanf("%d",&rank);
		if (rank > N){
			printf("error rank of range !\n");
			continue;
		}
		printf("%5d \n",Select(A,0,6,rank));   
	}


	return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章