數據結構筆記之查找

         我們學習數據結構之前的那些查找,比如說查找數據庫,僅僅是查找,這種自作查找操作的查找表稱爲靜態查找表

而在查找過程中,同時插入查找表最後中不存在的數據元素,還可以刪除某些不要的項的情況,叫做動態查找表   :查找時插入數據元素,查找時候刪除動態元素

靜態查找表:

1:順序查找表

         一般在普通的數據集中,比如說數組,要找到我們要的那個記錄就是判斷關鍵字和我們的關鍵字是否一致,一般是判斷兩次,關鍵字是否相同,是否越界

這並不是完美的,可以增加一個哨兵,我們把要搜索的數據從1開始存放,到n,a[0]放哨兵(也可以是最後一個),然後在一個循環裏面判斷關鍵字,返回後判斷一次,如果返回的值的下標如果是0(其他寫法的話,也有可能是最後一個),證明是沒找到結果,這樣處理就少了半數的判斷,效率提高不知一點點啊

順序表對於表裏面的數據是否有序不作要求,因此這個查找通用,但是效率不是很高,特別是數據量比較大的時候

鑑於這個原因有序表的查找就顯得高效多了

2:有序表查找

折半查找

        有序表查找中,最有代表性的查找方法是折半查找

       折半查找的思路簡單就是,和那個非常6+1差不多,給一個區間,比如說猜一個數,範圍1-100,先說50,李詠會說大了或者小了,如果小了,就猜51和100間的中值75,這樣下去很快就出答案了,這就是典型的折半查找的例子

實際代碼的處理是

int low =0,high = n,mid;

while(low<high)

{

mid = (low +high)/2;

if(key<a[mid])

{

high = mid-1;

}else if(key>a[mid])

{

low = mid+1;

}

else

return mid;

}

循環的條件是low <high 這樣就消除了邊界問題


        折半查找的效率已經是很牛逼了,但是這還沒到最完美,假說,查字典,一般記錄值是a~z按序列的,如果我們要查找apple顯然不是從a-z的中間開始,因爲明顯可可知道在記錄的前面,這時候折半還沒有達到最優,這時候要說另外一個算法,插值查找

插值查找 

        對於上面說折半查找的這種情況效率不高,那麼插值查找就要在mid這個地方下功夫,到這多少,折一半,還是1/4,還是1/8

由於折半查找是不管key是多少,都是一次折一半,插值查找會根據這個key的值來確定mid的值,個人覺得這也算是一種權重把,不像折半那樣管你是誰,老子就折一半,插值根據這個key的值來做一些影響,具體的賦值是

本來 :mid = (low + high)/2  = low/2 + high/2 = low + high/2- low/2 = low + 1/2(high -  low)

插值查找就把這個1/2給做了改動 改爲(key -a[low])/ (a[high] - a[low] ) ,這樣可看出,key越小,插得值越小,key越大 插的值越大,這樣字普遍來說更加高效


        還有另外一種有序表的查找方法,叫費波那契查找 利用了黃金分割原理來實現的


       事實上,雖然折半,插值,費波那契 ,這些查找雖然十分高效,但他們的要求是記錄有序,但是在很多情況下,要查找的記錄有序的話,代價太高,因此還要考慮到普通的並非有序的記錄,有對於無序的數據又要很快的查找到記錄怎麼辦呢,這裏有一種方法,叫建立索引,把數據的位置拿出來放到一張表中,這樣查表就可以查的記錄了(快吧 -!!) 索引有多種,我們就學重點看三種,稠密索引 ,分塊索引,倒排索引


動態查找表

    對於有序的數據 :如果是使用存儲,我們在查找的時候可以用非常高效的算法,如折半查找,插值查找,費波那契查找,但是,我的數據是會增加的,如果有一個新的記錄進來的新的記錄的大小處於原來的數據集合的中間位置你那麼如果要插入的話,那就要移動半數的數據,有或者要刪除順序存儲中的中間的一個數據,那麼後半部的數據就都要往前移動一步,太麻煩了,效率太低,如果又要有序,又要插入高效,怎麼辦呢,這就要用到二叉排序樹

二叉排序樹

      二叉排序樹,他是排過序的二叉樹,也就是雙親節點的數據大小比左孩子大,比右孩子小,這種樹查找的時候先從根結點開始比較,等則返回,比根結點大就去到右孩子,比跟節點小則去左孩子,這樣的話最多查找到葉子就出結果,次數最多爲層數插入新節點的時候也是這樣,比較,找到合適位置就插入,新節點插入都是葉子,這樣字貌似解決了有序且插入高效的難題,但順序是還不是最好的解決方案,我們知道,查找的最差情況是數的層數,如果這顆二叉樹每層都只有一個孩子那麼處於葉子位置的節點就會好倒黴,查找他太慢,這個時候,會想到,完全二叉樹是最理想的情況,但是往往給出的數據沒有那麼巧,我們可以儘量使得二叉樹的左右子樹一樣高,這樣的話,節點分佈比較均勻,查找更高效,因此提出了平衡二叉樹


平衡二叉樹

    平衡二叉樹的要求是每個節點的左右子樹的高度之差不能超過1,這就有3種可能,左子樹比右子樹 的高度 大1 小1,相等,但是新插入的點是未知的,所以很有可能會打亂平衡,因此,要對不平衡的子樹進行調整
 

      經過調整後的二叉樹變平衡了,這樣的話查找效率就高了,雖然avl二叉樹比二叉排序樹的效率要高的多,但是我門也看到插入或者刪除一個節點的時候,經常要進行調整旋轉操作,這樣又付出了一些時間,能不能做一個折中處理呢,查找效率又高,調整有沒那麼頻繁呢,答案是有,叫紅黑樹(red black tree)RB樹,(普遍的實際應用中驗證,紅黑樹的效率要比avl樹高一些)

在海量數據處理中,二叉樹的規模會非常大,爲了緩解這個爲問題,提出了B樹,也就是不止二叉,多一些節點那麼樹的高度就會小,查詢的效率也會高,B樹也被國內稱爲B-樹,B+樹是B樹的拓展,B*樹是B+樹的拓展,這個還不熟悉,以後再寫心得






發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章