原文:
演算法系列15天速成——第五天 五大經典查詢【中】
大家可否知道,其實查詢中有一種o(1)的查詢,即所謂的秒殺。
雜湊查詢:
對的,他就是雜湊查詢,說到雜湊,大家肯定要提到雜湊函式,呵呵,這東西已經在我們腦子裡面形成
固有思維了。大家一定要知道「雜湊「中的對應關係。
比如說: 」5「是乙個要儲存的數,然後我丟給雜湊函式,雜湊函式給我返回乙個」2",那麼此時的」5「
和「2」就建立一種對應關係,這種關係就是所謂的「雜湊關係」,在實際應用中也就形成了」2「是key,」5「是value。
那麼有的朋友就會問如何做雜湊,首先做雜湊必須要遵守兩點原則:
①: key盡可能的分散,也就是我丟乙個「6」和「5」給你,你都返回乙個「2」,那麼這樣的雜湊函式不盡完美。
②: 雜湊函式盡可能的簡單,也就是說丟乙個「6」給你,你雜湊函式要搞1小時才能給我,這樣也是不好的。
其實常用的做雜湊的手法有「五種」:
第一種:」直接定址法「。
很容易理解,key=value+c; 這個「c"是常量。value+c其實就是乙個簡單的雜湊函式。
第二種:「除法取餘法」。
很容易理解, key=value%c;解釋同上。
第三種:「數字分析法」。
這種蠻有意思,比如有一組value1=112233,value2=112633,value3=119033,
針對這樣的數我們分析數中間兩個數比較波動,其他數不變。那麼我們取key的值就可以是
key1=22,key2=26,key3=90。
第四種:「平方取中法」。此處忽略,見名識意。
第五種:「摺疊法」。
這種蠻有意思,比如value=135790,要求key是2位數的雜湊值。那麼我們將value變為13+57+90=160,
然後去掉高位「1」,此時key=60,哈哈,這就是他們的雜湊關係,這樣做的目的就是key與每一位value都相
關,來做到「雜湊位址」盡可能分散的目地。
正所謂常在河邊走,哪有不濕鞋。雜湊也一樣,你雜湊函式設計的再好,搞不好哪一次就撞樓了,那麼拋給我們的問題
就是如果來解決「雜湊位址「的衝突。
其實解決衝突常用的手法也就2種:
所謂」開放位址「,其實就是陣列中未使用的位址。也就是說,在發生衝突的地方,後到的那個元素(可採用兩種方式
:①線性探測,②函式探測)向陣列後尋找"開放位址「然後把自己插進入。
這個大家暫時不懂也沒關係,我就先介紹一下原理,就是在每個元素上放乙個」指標域「,在發生衝突的地方,後到的那
個元素將自己的資料域拋給衝突中的元素,此時衝突的地方就形成了乙個鍊錶。
那麼下面就上**了,
設計函式採用:」除法取餘法「。
衝突方面採用:」開放位址線性探測法"。
1結果:using system;
2using system.collections.generic;
3using system.linq;
4using system.text;56
namespace hashsearch
7 ;15
16//
雜湊表長度
17static
int hash = new
int[hashlength];
1819
static
void main(string args)
20
2627 console.writeline("
hash資料:
" + string.join("
,", hash));
2829
while (true)
30
41 }
4243
///44
///hash表檢索資料
45///
46///
47///
48///
49///
50static
int searchhash(int hash, int hashlength, int key)
51
6061
//查詢到了開放單元,表示查詢失敗
62if (hash[hashaddress] == 0)
63return -1;
64return hashaddress;
6566 }
6768
///69
///資料插入hash表
70///
71///
雜湊表72
///73
///74
static
void inserthash(int hash, int hashlength, int data)
75
8586
//將data存入字典中
87 hash[hashaddress] = data;
88 }
89 }
90 }
索引查詢:
一提到「索引」,估計大家第一反應就是「資料庫索引」,對的,其實主鍵建立「索引」,就是方便我們在海量資料中查詢。
關於「索引」的知識,估計大家都比我清楚,我就簡單介紹下。
我們自己寫演算法來實現索引查詢時常使用的三個術語:
第一:主表, 這個很簡單,要查詢的物件。
第二:索引項, 一般我們會用函式將乙個主表劃分成幾個子表,每個子表建立乙個索引,這個索引叫做索引項。
第三:索引表, 索引項的集合也就是索引表。
一般「索引項」包含三種內容:index,start,length
第一: index,也就是索引指向主表的關鍵字。
第二:start, 也就是index在主表中的位置。
第三:length, 也就是子表的區間長度。
1結果:using system;
2using system.collections.generic;
3using system.linq;
4using system.text;56
namespace indexsearchprogram
7 22
23static
void main(string args)
24
4142 console.readline();
43 }
4445
///46
///學生主表
47///
48static
int students = ;
53///
54///
學生索引表
55///
56static indexitem indexitem = ,
58new indexitem(),
59new indexitem(),
60 };
6162
///63
///查詢資料
64///
65///
66///
67public
static
int indexsearch(int key)
68 ;
80break;
81 }
82 }
8384
//如果item為null,則說明在索引中查詢失敗
85if (item == null)
86return -1;
8788
for (int i = item.start; i < item.start + item.length; i++)
89
94 }
95return -1;
96 }
9798
///99
///插入資料
100///
101///
102///
103public
static
int insert(int key)
104 ;
119break;
120 }
121 }
122if (item == null)
123return -1;
124//
更新主表
125 students[item.start + item.length] = key;
126//
更新索引表
127 indexitem[i].length++;
128return
1;129 }
130 }
131 }
ps: 雜湊查詢時間複雜度o(1)。
索引查詢時間複雜度:就拿上面的demo來說是等於o(n/3)+o(length)
演算法系列15天速成 第五天 五大經典查詢 中
大家可否知道,其實查詢中有一種o 1 的查詢,即所謂的秒殺。雜湊查詢 對的,他就是雜湊查詢,說到雜湊,大家肯定要提到雜湊函式,呵呵,這東西已經在我們腦子裡面形成 固有思維了。大家一定要知道 雜湊 中的對應關係。比如說 5 是乙個要儲存的數,然後我丟給雜湊函式,雜湊函式給我返回乙個 2 那麼此時的 5...
演算法系列15天速成 第五天 五大經典查詢 中
大家可否知道,其實查詢中有一種o 1 的查詢,即所謂的秒殺。雜湊查詢 對的,他就是雜湊查詢,說到雜湊,大家肯定要提到雜湊函式,呵呵,這東西已經在我們腦子裡面形成 固有思維了。大家一定要知道 雜湊 中的對應關係。比如說 5 是乙個要儲存的數,然後我丟給雜湊函式,雜湊函式給我返回乙個 2 那麼此時的 5...
演算法系列15天速成 第四天 五大經典查詢 上
在我們的生活中,無處不存在著查詢,比如找一下班裡哪個mm最pl,猜一猜mm的芳齡.對的這些都是查詢。在我們的演算法中,有一種叫做線性查詢。分為 順序查詢。折半查詢。查詢有兩種形態 分為 破壞性查詢,比如有一群mm,我猜她們的年齡,第一位猜到了是23 此時這位mm已經從我腦海裡面的mmlist中rem...