二分法查找算法


   二分法查找具有驚人的查找速度,尤其是對於海量數據的時候,作用更加明顯,時間復雜度用大O表示法,即是(logn),這種(logn)時間復雜度是非常神奇的,比如 n 等於 2 的 32 次方,這個數很大了吧?大約是42億,也就是說,如果我們在 42 億個數據中用二分查找一個數據,最多需要比較 32 次。

  但是,二分查找是有局限性的:

(1)二分查找依賴的是順序表結構,簡單點說就是數組。

解釋:主要原因是二分查找算法需要按照下標隨機訪問元素。

(2)二分查找針對的是有序數據。

(3)數據量太小不適合二分查找。

(4)數據量太大也不適合二分查找。

解釋:二分查找的底層需要依賴數組這種數據結構,而數組為了支持隨機訪問的特性,要求內存空間連續,對內存的空間要求比較苛刻。比如,我們有1GB的數據,那就需要1GB內存空間。

接下來是二分算法的代碼了:

  1 //二分法查找給定值 普通Java實現
  2 public int bsearch(int[] a, int n, int value) {
  3   int low = 0;
  4   int high = n - 1;
  5 
  6   while (low <= high) {
  7     int mid = (low + high) / 2;
  8     if (a[mid] == value) {
  9       return mid;
 10     } else if (a[mid] < value) {
 11       low = mid + 1;
 12     } else {
 13       high = mid - 1;
 14     }
 15   }
 16 
 17   return -1;
 18 }
 19 
 20 // 二分查找的遞歸實現
 21 public int bsearch(int[] a, int n, int val) {
 22   return bsearchInternally(a, 0, n - 1, val);
 23 }
 24 
 25 private int bsearchInternally(int[] a, int low, int high, int value) {
 26   if (low > high) return -1;
 27 
 28   int mid =  low + ((high - low) >> 1);
 29   if (a[mid] == value) {
 30     return mid;
 31   } else if (a[mid] < value) {
 32     return bsearchInternally(a, mid+1, high, value);
 33   } else {
 34     return bsearchInternally(a, low, mid-1, value);
 35   }
 36 }
 37 
 38     //查找第一個值等於給定值的元素
 39     public int bsearch1(int[] a, int n, int value){
 40         int low = 0;
 41         int high = n - 1;
 42         
 43         while(low <= high){
 44             //這里用到的(右移)>>運算符  右移運算符簡單理解就是 除以2的移動次冪 下面這個就是 等同於(high-low)/2^1
 45             int mid = low + ((high-low) >> 1);
 46             if(a[mid] > value){
 47                 //說明value 在前半部分 把排好序的數組 從中間一切兩半
 48                 high = mid - 1;
 49             }else if(a[mid] < value){
 50                 //說明value 在后半部分
 51                 low = mid + 1;
 52             }else{
 53                 //a[mid] == value
 54                 //但是我們要查找的是第一個 等於改定值的元素 還需要確認一下a[mid] 是不是第一個
 55                 if(mid == 0 || a[mid - 1] != value){
 56                     //當mid == 0 的時候,說明這是第一個元素,肯定是我們要找的
 57                     //當a[mid] 前面的元素不等於 value的時候,說明a[mid]肯定就是第一個等於給定值的元素
 58                     //因為該數組是有序的,這里就是默認從小到大排序
 59                     return mid;
 60                 }else{
 61                     high = mid - 1;
 62                 }
 63             }
 64         }
 65         //這個 -1 代表的就是沒有找到
 66         return -1;
 67     }
 68     
 69     //查找最后一個值等於給定元素
 70     public int bsearch2(int[] a, int n, int value){
 71         int low = 0;
 72         int high = n - 1;
 73         
 74         while(low <= high){
 75             int mid = low + ((low+high) >> 1);
 76             if(a[mid] > value){
 77                 high = mid - 1;
 78             }else if(a[mid] < value){
 79                 low = mid + 1;
 80             }else{
 81                 if(mid == n-1 || a[mid+1] != value){
 82                     //同理
 83                     return mid;
 84                 }else{
 85                     low = mid + 1;
 86                 }
 87             }
 88         }
 89         return -1;
 90     }
 91     
 92     //查找第一個大於等於給定值的元素
 93     public int bsearch3(int[] a, int n, int value){
 94         int low = 0;
 95         int high = n - 1;
 96         
 97         while(low <= high){
 98             int mid = low + ((low+high) >> 1);
 99             if(a[mid] >= value){
100                 if(mid == 0 || a[mid-1] < value){
101                     //a[mid] 是第一個數,但是a[mid]大於等於value的數,所以肯定就是它了
102                     //a[mid - 1] 是小於 value 的數,它的前一個數是小於value的,肯定也是它了
103                     return mid;
104                 }else{
105                     high = mid - 1;
106                 }
107             }else{
108                 low = mid + 1;
109             }
110         }
111         return -1;
112     }
113     
114     //查找最后一個小於等於給定值得元素
115     public int bsearch4(int[] a, int n, int value){
116         int low = 0;
117         int high = n -1;
118         
119         while(low <= high){
120             int mid = low + ((low+high) >> 1);
121             if(a[mid] > value){
122                 high = mid - 1;
123             }else{
124                 if(mid == n-1 || a[mid+1] > value){
125                     //同理
126                     return mid;
127                 }else{
128                     low = mid + 1;
129                 }
130             }
131         }    
132         return -1;
133     } 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM