查找算法合集

1、順序搜索法數組

因爲不知道要查找元素的具體位置,只能一個元素一個元素的去判斷。ide

平均查找(n+1)/2spa

  1. int find(int array[], int  length, int value)  指針

  2. {  orm

  3.     if(NULL == array || 0 == length)  排序

  4.         return -1;  內存

  5.   

  6.     for(int index = 0; index < length; index++){  hash

  7.         if(value == array[index])  it

  8.             return index;  class

  9.         }  

  10.     return -1;  

  11. }  


2、折半查找

對於一個有序數組,咱們就能夠經過二分查找的方法來提升查找效率。時間複雜度O(lgn)

二分查找有兩種寫法,須要特別注意邊界。

(1)左閉右閉[left,right]

也就是left = 0, right = n-1。這時的判斷條件時left < right。而且當去一邊的時候要mid+1或mid-1

  1. int search(int array[], int n, int v)  

  2. {  

  3.     int left, right, middle;  

  4.   

  5.     left = 0, right = n - 1;    //左閉右閉  

  6.   

  7.     while (left <= right){      //循環條件  

  8.         middle = (left + right) / 2;  

  9.         if (array[middle] > v){  

  10.             right = middle - 1; //因爲middle不符合,全部要middle-1知足右閉  

  11.         }  

  12.         else if (array[middle] < v){  

  13.             left = middle + 1;  //同上,知足左閉  

  14.         }  

  15.         else{  

  16.             return middle;  

  17.         }  

  18.     }  

  19.   

  20.     return -1;  

  21. }  


(2)左閉右開[left,right)


也就是left = 0,right = n。這時不相等時,有left = mid+1 或 right = mid;

  1. int search3(int array[], int n, int v)  

  2. {  

  3.     int left, right, middle;  

  4.   

  5.     left = 0, right = n;    //左閉右開  

  6.   

  7.     while (left < right){   //判斷條件,因爲是開,就必須不能相等  

  8.         middle = (left + right) / 2;  

  9.   

  10.         if (array[middle] > v){  

  11.             right = middle; //知足右開  

  12.         }  

  13.         else if (array[middle] < v){  

  14.             left = middle + 1;  //知足左閉  

  15.         }  

  16.         else{  

  17.             return middle;  

  18.         }  

  19.     }  

  20.   

  21.     return -1;  

  22. }  


在循環體內,計算中間位置的時候,使用的是這個表達式:


middle = (left + right) / 2;


假如,left與right之和超過了所在類型的表示範圍的話,那麼middle就不會獲得正確的值.
因此,更穩妥的作法應該是這樣的:

middle = left + (right - left) / 2;



3、搜索二叉樹

上面的查找是創建在連續內存基礎之上的,那麼若是是指針類型的數據呢?怎麼辦呢?那麼就須要引入排序二叉樹了。排序二叉樹的定義很簡單:(1)非葉子節點至少一邊的分支非NULL;(2)葉子節點左右分支都爲NULL;(3)每個節點記錄一個數據,同時左分支的數據都小於右分支的數據。能夠看看下面的定義:

  1. typedef struct _NODE  

  2. {  

  3.     int data;  

  4.     struct _NODE* left;  

  5.     struct _NODE* right;  

  6. }NODE;  


  1. const NODE* find_data(const NODE* pNode, int data){  

  2.     if(NULL == pNode)  

  3.         return NULL;  

  4.   

  5.     if(data == pNode->data)  

  6.         return pNode;  

  7.     else if(data < pNode->data)  

  8.         return find_data(pNode->left, data);  

  9.     else  

  10.         return find_data(pNode->right, data);          

  11. }  


4、哈希表法-----鏈式查找,相同映射的,放在一個鏈表中


咱們看到(2)、(3)都是創建在徹底排序的基礎之上,那麼有沒有創建在折中基礎之上的查找呢?有,那就是哈希表。哈希表的定義以下:1)每一個數據按照某種聚類運算歸到某一大類,而後全部數據鏈成一個鏈表;2)全部鏈表的頭指針造成一個指針數組。這種方法由於不須要完整排序,因此在處理中等規模數據的時候頗有效。其中節點的定義以下:

  1. typedef struct _LINK_NODE  

  2. {  

  3.     int data;  

  4.     struct _LINK_NODE* next;  

  5. }LINK_NODE;  


 那麼hash表下面的數據怎麼查找呢?

  1. LINK_NODE* hash_find(LINK_NODE* array[], int mod, int data)  

  2. {  

  3.     int index = data % mod;  

  4.     if(NULL == array[index])  

  5.         return NULL;  

  6.   

  7.     LINK_NODE* pLinkNode = array[index];  

  8.     while(pLinkNode){  

  9.         if(data == pLinkNode->data)  

  10.             return pLinkNode;  

  11.         pLinkNode = pLinkNode->next;  

  12.     }  

  13.   

  14.     return pLinkNode;  

  15. }  


 hash表由於不須要排序,只進行簡單的歸類,在數據查找的時候特別方便。查找時間的大小取決於mod的大小。mod越小,那麼hash查找就越接近於普通查找;那麼hash越大呢,那麼hash一次查找成功的機率就大大增長。

相關文章
相關標籤/搜索