最壞情況為線性的選擇演算法
阿新 • • 發佈:2018-12-08
基本思想
主體上是在期望為線性的選擇演算法上進行改進,將其中的隨機的劃分元素改為取中位數,使劃分更均勻,從而達到最壞時時間複雜度也為線性.需要注意的是實現時裡面的索引很暈,別搞混了.我就是先寫了個很亂,然後實在改不下去了,就重寫了,總共我大概寫了5,6個小時吧.(可能我太菜了)
圖解
程式碼
虛擬碼
這裡書中未給虛擬碼,僅給了整個演算法的流程,但並不影響我們的實現
C程式碼
#include <stdio.h> #define N 50 void show(int *a, int p, int r); int Partition(int * a, int p, int r, int x)//以值x來進行分割 { int k; int pos; for(k = p; k <= r; k++)//先把值x與末尾r交換位置,不太好,因為我還遍歷了陣列來找x的索引值 { if(a[k] == x) pos = k; } int temp; int t = a[pos]; a[pos] = a[r]; a[r] = t; int i, j; i = p-1; for(j = p; j <= r; j++) { if(a[j] <= t) { i+=1; temp = a[i]; a[i] = a[j]; a[j] = temp; } } return i;//返回劃分後的x所對應的索引 } int Insertion_sort(int * a, int p, int r)//用來對每組元素進行插排 { int i, j; for(i = p+1; i <= r; i++) { j = i; while(j > p && a[j] < a[j-1]) { int temp = a[j]; a[j] = a[j-1]; a[j-1] = temp; j--; } } } int Select(int *a, int p, int r, int i, int len)//返回第i個元素的值 { if(p==r)//僅一個元素時直接返回 { return a[p]; } int midval[N]; int group = len%5==0 ? len/5 : len/5+1; if(len%5==0)//每組剛好5人 { int i; for(i = 0; i < group; i++) { Insertion_sort(a,p+5*i,p+5*i+4); midval[i] = a[p+i*5+2]; } } else//最後一組不滿5人 { int i; for(i = 0; i < group-1; i++) { Insertion_sort(a,p+5*i,p+5*i+4); midval[i] = a[p+i*5+2]; } //單獨處理最後一組 int lastgroupsize = len%5; Insertion_sort(a,p+5*i,r); midval[i] = a[p+i*5+lastgroupsize/2]; } int pos2 = Select(midval,0,group-1,group/2,group);//對midval[]遞迴查詢其中位數 int q = Partition(a,p,r,pos2);//以中位數pos2來劃分元素 int k = q-p;//劃分元素的相對位置 if(i == k) return a[q];//劃分元素剛好為所查元素,返回 else if(i < k) return Select(a,p,p+k-1,i,k);//繼續處理左半邊 else return Select(a,p+k+1,r,i-k-1,r-p-k);//繼續處理右半邊 } int main() { int a[] = {34,65,21,32,555,11,4,78,64,99,25,100,24}; int len = sizeof(a)/sizeof(int); int k; int i; for(i = 0; i < len; i++) { printf("%d ", a[i]); } printf("\ninput nth to search\n"); scanf("%d",&k); int ans = Select(a,0,12,k,13); printf("ans %d\n", ans); return 0; } //演算法流程不難,但實現起來其中的細節很多,尤其這裡面的下標很繞人
時間複雜度
O(n)