P2-2017級演算法第二次上機 A ModricWang's Real QuickSort Query
阿新 • • 發佈:2018-12-27
題目描述
羊瑞大佬說:"現在的年輕人啊,寫個快排都能寫錯,比如那個辣雞的ModricWang"覺得他說的情況是真的,決定幫自己複習一下快排的寫法。
快排的一個基礎操作就是劃分(partition),就是將當前的陣列分為前後兩個部分。
一種較為經典的partition方法是,將陣列中處於中間位置(注意,只和位置有關,和大小無關)的元素作為分隔元素,然後將小於它的元素放到左側,大於它的元素放到右側,然後對左右兩側分別進行遞迴操作。在此題中為了統一,如果陣列長度為偶數,取靠後的一個作為分隔元素。
需要注意的是,快排的劃分是一種原地劃分,而且左右兩邊的長度是未知的,因此它在操作時採取以下的一種方式:
- 設陣列為arr[n],元素從0開始儲存
- 令i=0,j=n−1,mid=arr[n/2]
- 如果i≤j,轉到4,否則轉到步驟7
- 如果arr[i]<mid,重複執行直到arr[i]≥mid
- 如果arr[j]>mid,重複執行直到arr[j]≤mid
- 如果i≤j,交換arr[i]和arr[j],i++,j−−,轉到步驟4
- 退出
進行第一次遞迴時,陣列被分為左右兩個部分:[0,i)和[i,n),其中i就是執行partition時的i[0,i)和[i,n),其中i就是執行partition時的i 。進行第二層的遞迴時,陣列總共被分為4個部分。現在ModricWang 想讓你輸出第二層遞迴時從左往右的第二部分的元素。
輸入
第一個數為陣列長度n,16≤n≤106
第二行n個整數,為待排序的元素,保證在int範圍內且不重複
輸出
輸出一行,第二層遞迴時從左往右的第二部分的元素。
資料保證這一部分不為空。
輸入樣例
16
10 6 2 7 14 4 1 13 8 15 5 3 9 11 12 16
輸出樣例
7 6 8
HINT
原資料
10 6 2 7 14 4 1 13 8 15 5 3 9 11 12 16
第一次遞迴
3 6 2 7 5 4 1 8 / 13 15 14 10 9 11 12 16
第二次遞迴
3 1 2 4 5 / 7 6 8 / 9 / 15 14 10 13 11 12 16
思路
無
參考程式碼
1 #include<stdio.h> 2 #define MAXN 1000002 3 int arr[MAXN]; 4 int main() 5 { 6 int n; 7 scanf("%d",&n); 8 int i; 9 for(i = 0;i < n;i++) 10 scanf("%d",&arr[i]); 11 quicksort(0,n-1,1); 12 } 13 14 void quicksort(int l,int r,int depth) 15 { 16 int i = l,j = r,mid = arr[(i+j+1)/2]; 17 while(i <= j){ 18 while(arr[i] < mid) 19 i++; 20 while(arr[j] > mid) 21 j--; 22 if(i <= j){ 23 swap(&arr[i],&arr[j]); 24 i++;j--; 25 } 26 } 27 if(depth == 2){ 28 for(;i <= r;i++) 29 printf("%d ",arr[i]); 30 printf("\n"); 31 exit(0); 32 } 33 if(l < j) 34 quicksort(l,j,depth+1); 35 if(r > i) 36 quicksort(i,r,depth+1); 37 } 38 39 void swap(int *a,int *b) 40 { 41 int tmp; 42 tmp = *a; 43 *a = *b; 44 *b = tmp; 45 }