搜索是在一個項目集合中找到一個特定項目的算法過程。搜索一般的答案是真的或假的,由於該項目是否存在。 搜索的幾種常見方法:順序查找、二分法查找、二叉樹查找、哈希查找。python
也就是數據不排序的線性查找,遍歷數據元素。
算法分析:最好狀況是在第一個位置就找到了,此爲O(1);最壞狀況在最後一個位置才找到,此爲O(n);因此平均查找次數爲(n+1)/2。最終時間複雜度爲O(n)算法
# 最基礎的遍歷無序列表的查找算法 # 時間複雜度O(n) def sequential_search(lis, key): length = len(lis) for i in range(length): if lis[i] == key: return i else: return False if __name__ == '__main__': LIST = [1, 5, 8, 123, 22, 54, 7, 99, 300, 222] result = sequential_search(LIST, 123) print(result)
二分查找又稱折半查找,優勢是比較次數少,查找速度快,平均性能好;其缺點是要求待查表爲有序表,且插入刪除困難。所以,折半查找方法適用於不常常變更而查找頻繁的有序列表。首先,假設表中元素是按升序排列,將表中間位置記錄的關鍵字與查找關鍵字比較,若是二者相等,則查找成功;不然利用中間位置記錄將表分紅前、後兩個子表,若是中間位置記錄的關鍵字大於查找關鍵字,則進一步查找前一子表,不然進一步查找後一子表。重複以上過程,直到找到知足條件的記錄,使查找成功,或直到子表不存在爲止,此時查找不成功。數組
算法核心:在查找表中不斷取中間元素與查找值進行比較,以二分之一的倍率進行表範圍的縮小。app
一、二分查找的python代碼實現性能
def binary_search(lis, key): low = 0 high = len(lis) - 1 time = 0 while low < high: time += 1 mid = int((low + high) / 2) if key < lis[mid]: high = mid - 1 elif key > lis[mid]: low = mid + 1 else: # 打印折半的次數 print("times: %s" % time) return mid print("times: %s" % time) return False if __name__ == '__main__': LIST = [1, 5, 7, 8, 22, 54, 99, 123, 200, 222, 444] result = binary_search(LIST, 1) print(result)
運行結果爲:spa
查找次數爲: 3
下表爲:0
二、二分查找的C語言代碼實現code
// main.m // 二分查找 // Created by 侯壘 on 2019/7/1. // Copyright © 2019 可愛的侯老師. All rights reserved. # include <stdio.h> int binary_search(int array[],int key,int len) { int low = 0; int high = len-1; int time = 0; while (low<high) { time++; int mid = (int)(low+high)/2; if (key<array[mid]) { high = mid-1; } else if(key>array[mid]) { low = mid+1; } else { // 打印這本的次數 printf("查詢次數 = %d\n",time); return mid; } } printf("查詢次數 = %d\n",time); return -1; } int main(int argc, const char * argv[]) { int array[11] = {1, 5, 7, 8, 22, 54, 99, 123, 200, 222, 444}; int index = binary_search(array, 1, 11); printf("下標是 = %d\n",index); return 0; }
運行結果爲:blog
查詢次數 = 3 下標是 = 0
在介紹插值查找以前,首先考慮一個新問題,爲何上述算法必定要是折半,而不是折四分之一或者折更多呢?排序
打個比方,在英文字典裏面查「apple」,你下意識翻開字典是翻前面的書頁仍是後面的書頁呢?若是再讓你查「zoo」,你又怎麼查?很顯然,這裏你絕對不會是從中間開始查起,而是有必定目的的往前或日後翻。io
一樣的,好比要在取值範圍1 ~ 10000 之間 100 個元素從小到大均勻分佈的數組中查找5, 咱們天然會考慮從數組下標較小的開始查找。
通過以上分析,折半查找這種查找方式,不是自適應的(也就是說是傻瓜式的)。二分查找中查找點計算以下:
mid=(low+high)/2, 即mid=low+1/2*(high-low);
經過類比,咱們能夠將查找的點改進爲以下:
mid=low+(key-list[low])/(list[high]-list[low])*(high-low),
也就是將上述的比例參數1/2改進爲自適應的,根據關鍵字在整個有序表中所處的位置,讓mid值的變化更靠近關鍵字key,這樣也就間接地減小了比較次數。
基本思想:基於二分查找算法,將查找點的選擇改進爲自適應選擇,能夠提升查找效率。固然,差值查找也屬於有序查找。
注:對於表長較大,而關鍵字分佈又比較均勻的查找表來講,插值查找算法的平均性能比折半查找要好的多。反之,數組中若是分佈很是不均勻,那麼插值查找未必是很合適的選擇。
複雜度分析:查找成功或者失敗的時間複雜度均爲O(log(n))。
一、插值查找的python代碼實現
def chazhi_search(lis, key): low = 0 high = len(lis) - 1 time = 0 while low < high: time += 1 # 計算mid值是插值算法的核心代碼 mid = low + int((key - lis[low])/(lis[high] - lis[low]) * (high - low)) print("mid=%s, low=%s, high=%s" % (mid, low, high)) if key < lis[mid]: high = mid - 1 elif key > lis[mid]: low = mid + 1 else: # 打印查找的次數 print("查詢次數: %s" % time) return mid print("times: %s" % time) return False if __name__ == '__main__': LIST = [1, 5, 7, 8, 22, 54, 99, 123, 200, 222, 444] index = chazhi_search(LIST, 1) print("下標爲:%s"%index)
運行結果爲:
mid=0, low=0, high=10 查詢次數: 1 下標爲:0
二、插值查找的C語言代碼實現
// main.m // 插值查找 // Created by 侯壘 on 2019/7/1. // Copyright © 2019 可愛的侯老師. All rights reserved. #include<stdio.h> int chazhi_search(int array[],int key,int len) { int low = 0; int high = len-1; int time = 0; while (low<high) { time++; // 計算mid值是插值算法的核心代碼 int mid = low + (int)((key - array[low])/(array[high]-array[low])*(high-low)); printf("mid=%d, low=%d, high=%d\n",mid, low, high); if (key<array[mid]) { high = mid-1; } else if (key>array[mid]) { low = mid+1; } else { // 打印查找的次數 printf("查詢次數:%d\n",time); return mid; } } printf("查詢次數:%d\n",time); return -1; } int main(int argc, const char * argv[]) { int arr[] = {1, 5, 7, 8, 22, 54, 99, 123, 200, 222, 444}; int index = chazhi_search(arr, 1, 11); printf("下標爲:%d\n",index); return 0; }
運行結果爲:
mid=0, low=0, high=10 查詢次數:1 下標爲:0