筆者曾經參加過某瀏覽器開發,記得當時在做瀏覽器放大和縮小的時候,產品經理規定滾動滑鼠增加時百分之5,10,15,35,45,50,65,75,85,90,95,100,105,125,150,175,200。當時參加開發的同學就將這組資料做成乙個表,然後每次滾動放大或者縮小都首先獲取當前數值,然後從這個表中查需要改變多少再設定頁面顯示。不過查取的時候那位同學採用折半查詢方法,認為這樣效率很高。
可是事實真的這樣嗎?
總所周知,對於有序陣列的折半查詢可以將時間複雜度從順序查詢的n降低到lgn(以2為底),同時有效提高效率。不過這只是理論值,實際效果如何我們首先來看一組資料。
nkey= 0,遞推查詢= 234ms,非遞推= 188ms,順序=31msnkey= 1,遞推查詢= 156ms,非遞推= 141ms,順序=47ms
nkey= 2,遞推查詢= 219ms,非遞推= 187ms,順序=63ms
nkey= 3,遞推查詢= 281ms,非遞推= 249ms,順序=93ms
nkey= 4,遞推查詢= 94ms,非遞推= 78ms,順序=109ms
nkey= 5,遞推查詢= 219ms,非遞推= 171ms,順序=125ms
nkey= 6,遞推查詢= 156ms,非遞推= 125ms,順序=140ms
nkey= 7,遞推查詢= 218ms,非遞推= 187ms,順序=172ms
nkey= 8,遞推查詢= 280ms,非遞推= 234ms,順序=187ms
nkey= 9,遞推查詢= 359ms,非遞推= 266ms,順序=499ms(不存在元素)
nkey=10,遞推查詢= 32ms,非遞推= 63ms,順序=219ms
nkey=11,遞推查詢= 234ms,非遞推= 187ms,順序=234ms
nkey=12,遞推查詢= 156ms,非遞推= 140ms,順序=265ms
nkey=13,遞推查詢= 281ms,非遞推= 203ms,順序=515ms(不存在元素)
nkey=14,遞推查詢= 234ms,非遞推= 187ms,順序=280ms
nkey=15,遞推查詢= 281ms,非遞推= 250ms,順序=312ms
nkey=16,遞推查詢= 93ms,非遞推= 94ms,順序=328ms
nkey=17,遞推查詢= 218ms,非遞推= 187ms,順序=359ms
nkey=18,遞推查詢= 297ms,非遞推= 250ms,順序=390ms
nkey=19,遞推查詢= 156ms,非遞推= 140ms,順序= 421ms
這組資料是建立乙個0到20的陣列,從中拿掉了9和13,然後用0到20分別採用遞迴二分查詢,迴圈二分查詢和直接順序查詢三種方式分別查5000000次得到的毫秒數。但是順序查詢時沒有採用辨別從左到右還是從右到左邊,以至於後期數值越來越大。但是從中可以看出前一半的成績順序查詢幾乎完勝,而遞迴查詢耗時排名墊底。這是為什麼呢?
相信遞迴查詢和迴圈查詢原理不難理解,因為遞迴的過程中要新開闢記憶體空間,涉及到大量的壓棧和出棧(函式引數+返回位址)操作,當陣列很大時會吃掉所有棧空間使得程式崩潰,這也是很多類似嵌入式等記憶體空間很小的作業系統也或者windows核心驅動基本不允許使用遞迴的原因,而迴圈查詢就沒有這方面耗時。
1int binarysearch(int narry,int nlow,int nhigh,int
key)2
16return -1
; 17}18
19int search(int key,int low,int high,int
k)
2027}28
29return -1
;30 }
那麼非遞迴的二分查詢又為何會敗在循序查詢手上呢?從原始碼裡面我們可以看出,迴圈查詢一次就是兩次比較一處自加,而非遞迴的二分查詢查詢一次一次比較,一次相加,一次除法,再比較兩次,一次加或者減一。整個過程比起循序查詢多出好幾個步驟,甚至還有最耗時的除法計算(由於是除以2,編譯器一般會轉換成移位來提高效率).
所以說二分查詢雖說整體效率理論上高,但是每一次查詢單元耗時卻遠比循序查詢要大,當陣列元素不是太多時效率反而不如循序查詢,這也是上面那瀏覽器放大和縮小我不推薦使用二分查詢的原因。
資料對映 有序陣列
一般來說,如果你希望資料能夠被快速的找到,那麼最主要的兩種技術手段就是二分查詢,或者使用hash函式。今天來介紹乙個最簡單的資料結構,有序陣列來組織的二分查詢,當然,我的主要目標是介紹前人解決問題的思路,而非演算法本身,所以不會嘗試用比較難理解的公式和偽碼來描述問題。使用二分查詢的前提條件是 1.資...
有序陣列中插入資料
問題描述 專案3 有序陣列中插入資料 定義好乙個有10個元素的陣列,先輸入9個呈公升序的數作為前9個元素,再輸入乙個數,要求按原來排序的規律將它插入陣列中。例如,9個呈公升序的數為1 7 8 17 23 24 59 62 101,需要插入的數字為50,輸出的序列則為1 7 8 17 23 24 50...
mysql如何讓設計資料量較少的一對多關係資料表
當我們在設計資料庫的資料表時,經常會遇到一對多的資料結構,如新聞的tag等,比如我們在設計資料表的時候,就碰到了這個問題,當時涉及樓盤資料表 house 物業性質 樓盤的裝修性質等情況的時候,因為乙個樓盤可能會涉及多個物業性質,而且物業性質的數量並不是很多。為了便於搜尋,如果把所有物業性質的id用分...