Linux C 算法——查找
???? ?所謂“查找”記為在一個含有眾多的數據元素(或記錄)的查找表中找出某個“特定的”數據,即在給定信息集上尋找特定信息元素的過程。
????為了便于討論,必須給出這個“特定的”詞的確切含義。首先,引入一個“關鍵字”的概念;
??? 關鍵字(Key)?是數據元素(或記錄)中某個數據項的值,用它可以標識(識別)一個數據元素(或記錄);
?????查找(Serching)根據給定的某個值,在查找表中確定一個其關鍵字等于給定值的記錄或數據元素。若表中存在這樣的一個記錄,則稱查找成功,此時查找的結果為給出整個記錄的信息,或只是該記錄在查找表中的位置;若表中不存在關鍵字等于給定值的記錄,則稱查找不成功,此時查找的結果可給出一個“空”記錄或“空”指針。
???? 查找方法有順序查找、折半查找、分塊查找、Hash表查找等。查找算法的優劣將影響到計算機的使用效率,應根據應用場合選擇相應的查找算法。評價一個算法的好壞,一是時間復雜度(T(n)),n 為問題的體積,此時為表長;二是空間復雜度(D(n));三是算法的結構等其他特性;
???? 對查找算法,主要分析其T(n)。查找過程是key的比較過程,時間主要耗費在各記錄的key與給定k值的比較上,比較次數越多,算法效率越差(即T(n)量級越高),故用“比較次數”刻畫算法的T(n)。另外,不能以查找某個記錄的時間來作為T(n),一般以“平均查找長度”來衡量 T(n)。
一、順序表的查找
??? ?所謂順序表(Sequential Table),是將表中記錄(R1 、R2。。。Rn)按其序號存儲于一維數組空間,其特點是相鄰記錄的物理位置也是相鄰的。
記錄Ri的類型描述如下:
[cpp]?view plaincopy順序表類型描述如下:
[cpp]?view plaincopy若說明: sqlist r,則(r.data[1],.......r.data[r.len])為記錄表(R1、R2 ...... Rn),Ri.key為r.data[i].key;
算法思路
???設給定值為k,在表(R1、R2。。。Rn)中,從Rn開始,查找key = k的記錄。若存在一個記錄Ri (1<i<n)的key為k,則查找成功,返回記錄序號i;否則,查找失敗,返回0;
算法描述:
第一種:
[cpp]?view plaincopy我們可以看出其比較次數最大是2 * len.
第二種:
[cpp]?view plaincopy這里比較次數最大為len.
第二種算法中引用了“監視哨”這個概念。它是放在data[0]位置的,這就我們前面講a[0]置空的原因;監視哨在這里無需判斷是否越界,這樣比較次數就會少一半,這里現將k存入監視哨,若對某個i 有r.data[i].key = k,則查找成功,返回i ;若i 從n 遞減到1 都無記錄的key為k,i 再減1?為 0 時,必有r.data[0].key = k ,說明查找失敗,返回i = 0;
?對于查找算法,ASL = O(n),則效率是很低的,意味著查找某記錄幾乎要掃描整個表,若表長len很大時,會令人無法忍受。
二、折半查找算法
?折半查找算法即二分法,二分查找算法的前提是表必須是有序的
算法思路:
對給定值k,組不確定待查記錄所在區間,每次將搜索空間減少一半(折半),知道查找成功或失敗為止。
設兩個指針(或游標)low 、high ,分別指向當前待查找表的上界(表頭)和下界(表尾)。對于表(R1、R2。。。Rn),初始時 low = 1、high = n,令:
mid = [ (low + high) / 2 ]
?指向當前待查找表中間的那個記錄,下面舉例說明折半查找的過程:
算法描述:
[cpp]?view plaincopy該例子中記錄表的查找過程可以用二叉樹來表示:
?
我們可以看到:找到第6個元素僅需比較一次,找到第3和第9個元素需比較2次;找到第1、4、7和10個元素許比較3次;找到第2、5、8、11個元素需比較4次;
在這個二叉樹中。樹中每個節點表示表中的一個記錄,節點中的值為該記錄在表中的位置,通常稱這個描述查找過程的二叉樹為判定書,從判定樹上可見,查找20的過程恰好是走了一條從根到節點4的路徑,和給定值進行比較的關鍵字個數為該路徑上的節點數或節點4在判定樹上的層次數。類似地,找到有序表中任意記錄的過程就是走了一條從根節點到該記錄相應的節點的路徑,和給定值進行比較的關鍵字個數恰為該節點在判定樹上的層次數。因此,折半查找法在查找成功時進行比較的關鍵字個數最多不超過樹的深度,而具有n個節點的判定書的深度為[log 2 n] + 1,所以,折半查找法在查找成功時和給定值進行比較的關鍵字個數之多為[log2 n] + 1。n為無窮時,大大優于O(n);
?
三、HASH查找
?????? HASH表,又稱散列表。在前面的討論的順序查找、折半查找中,其時間復雜度都在O(n)~O(log2 n)之間,不論ASL在哪個量級,都與記錄長度n有關。隨著n的擴大,算法的效率會越來越低。ASL 與n 有關是因為記錄在存儲器中的存放是隨機的,或者說記錄的key與記錄的存放地址無關,因而查找只能建立在key的“比較”基礎上。
?????? 理想的查找方法是:對給定的k,不經任何比較便能獲取所需的記錄,其查找的時間復雜度為常數級O(C)。這就要求在建立記錄表時,確定記錄的key與其存儲地址之間的關系f,即使key與記錄的存放地址H相對應。
1、哈希查找(定義)
???? 哈希查找是給定鍵值key,通過公式f (key) 直接計算數據元素的存儲地址(哈希值)進行數據存儲(即建立哈希表)和進行數據查找的一種方法,該公式 f 稱為哈希函數。哈希查找的本質是怎么構造的表就怎么在表中查找,具有O(1)的查找效率。記為?H(key) = f (key);
?????不同的key 可能得到同一個Hash地址,即當 key1 != key2時,可能有 H(key1) = H(key2),此時稱key1和key2為同義詞。這種現象稱為“沖突”或“碰撞”,因為一個單位只可存放一條記錄。一般,選取Hash函數只能做到使沖突盡可能少,卻不能完全避免。這就要求在出現沖突之后,尋求恰當的方法來解決沖突記錄的存放問題。
?
2、哈希查找(步驟)
建立哈希表操作步驟
1)step1取數據元素的關鍵字key,計算其哈希函數值(地址)。若該地址對應的存儲空間還沒有被占用,則該元素存入;否則執行step2解決沖突;
2)step2根據選擇的沖突處理方法,計算關鍵字key的下一個存儲地址。若下一個存儲地址仍被占用,則繼續執行step2,知道找到能用的存儲地址為止。
哈希查找操作步驟:
1)step1對給定key值,計算哈希地址H(key);若該地址上記錄不存在,則查找失敗,若記錄存在且key值匹配則查找成功;否則說明發生沖突,執行step2解決沖突。
2)step2 根據選擇的沖突處理方法,重復計算下一個存儲地址直到找到非空記錄并且key值相等才認為查找成功并結束,否則查找失敗。
?
3、哈希函數構造方法
這里主要介紹兩種構造方法:1)直接地址法 2)保留除數法
4、解決沖突的方法
這里主要介紹兩種解決沖突方法:1)開放地址法 2)鏈地址法
?5、下面介紹Hash查找的使用
1、性探查法解決沖突時Hash表的查找及插入
[cpp]?view plaincopy2、鏈地址法解決沖突時Hash表的查找及插入
[cpp]?view plaincopy總結
以上是生活随笔為你收集整理的Linux C 算法——查找的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Canvas制作动态进度加载水球
- 下一篇: 如何将Eclipse设置为中文版