演算法系列15天速成 第五天 五大經典查詢 中

2021-09-08 03:47:54 字數 4810 閱讀 4514

原文:

演算法系列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...