哈希表(Hash table)(散列表)
-
散列表(Hash table,也叫哈希表),是根據關鍵碼值(Key value)而直接訪問的數據結構。也就是說,它通過把關鍵碼值映射到表中的一個位置來訪問記錄,以加快查找的速度。這個映射函數叫做散列函數,存放的數組叫做散列表。
給定表M,存在函數f(key),對任意給定的關鍵字值key,帶入函數後若能得到包含該關鍵字的記錄在表中的地址,責成M為哈希表。函數f(key)為哈希函數。
-
實現增刪改查僱員的信息
//僱員信息 type Emp struct { Id int Name string Next *Emp } //僱員鏈錶從 type EmpLink struct { Head *Emp } //鏈錶插入操作 func (this *EmpLink) Insert(emp *Emp) { cur :=this.Head//輔助指針 var pre *Emp//輔助指針,cur之前 //不保留空的頭部,直接賦值 if cur == nil { this.Head = emp return } //如果需要替換頭結點 if cur.Id>emp.Id { emp.Next = cur this.Head = emp return } for { //如果沒到尾部繼續循環 if cur != nil { //如果當前ID大於傳入的僱員ID //就可以退出循環,在此位置添加 if cur.Id>emp.Id{ break } if cur.Id == emp.Id { fmt.Println("不可插入相同的ID!") return } pre = cur cur = cur.Next }else { //如果當前為nil,即循環到尾部 //將最大的ID僱員添加在尾部 break } } pre.Next = emp emp.Next = cur } //鏈錶查找操作,更新操作可複用 func (this *EmpLink) Find(id int) *Emp{ cur := this.Head if cur == nil { fmt.Println("所查鏈錶為空鏈錶") return nil } for { if cur.Id == id { fmt.Printf("已找到id=%d,name=%s",id,cur.Name) fmt.Println() return cur } //順序儲存不會出現要查找的ID大於之前ID的情況 //只可能不存在 if cur.Id > id || cur.Next == nil{ fmt.Println("沒找到") break } cur = cur.Next } return nil } //單鏈表刪除有點需要前結點, // 區別於查找,重新寫了一遍 func (this *EmpLink)Del(id int) { cur := this.Head var pre *Emp if cur == nil { fmt.Println("所刪鏈錶為空鏈錶") return } //如果刪除的是頭結點 if cur.Id == id { fmt.Printf("已刪除頭結點id=%d,name=%s",id,cur.Name) fmt.Println() this.Head = this.Head.Next return } for { pre = cur cur = cur.Next if cur.Id == id { fmt.Printf("已刪除id=%d,name=%s",id,cur.Name) fmt.Println() pre.Next = cur.Next return } if cur.Id > id || cur.Next == nil{ fmt.Println("沒找到") break } } } //更新 func (this *EmpLink)Update(emp *Emp,name string) { emp.Name = name fmt.Printf("已更新id=%d,name=%s",emp.Id,emp.Name) fmt.Println() } //顯示 func (this *EmpLink) ShowLink(no int) { if this.Head == nil { fmt.Printf("鏈錶%d為空",no) fmt.Println() return } for { if this.Head != nil { fmt.Printf("鏈錶%d 僱員名字 id = %d 名字=%s ->",no,this.Head.Id,this.Head.Name) this.Head = this.Head.Next }else { break } } fmt.Println() } //哈希表,含有一個鏈錶數組 type HashTable struct { LinkArr [7]EmpLink } func (this *HashTable) Insert(emp *Emp) { //使用散列函數,確定將僱員添加到哪個鏈錶 linkNo :=this.HashLink(emp.Id) //使用對應的鏈錶添加 this.LinkArr[linkNo].Insert(emp) } func (this *HashTable)Find(id int) { findNo := id % 7 this.LinkArr[findNo].Find(id) } func (this *HashTable)Del(id int) { findNo := id % 7 this.LinkArr[findNo].Del(id) } func (this *HashTable) Update(id int, name string) { findNo := id % 7 emp := this.LinkArr[findNo].Find(id) this.LinkArr[findNo].Update(emp,name) } func (this *HashTable) ShowAll() { for i := 0;i<len(this.LinkArr);i++{ this.LinkArr[i].ShowLink(i) fmt.Println() } } //對應於鏈錶 func (this *HashTable) HashLink(id int) int { return id%7 } func main() { key := "" id := 0 name := "" var hashtable HashTable for { fmt.Println("===========僱員菜單系統===========") fmt.Println("input 表示添加員工") fmt.Println("show 表示顯示員工") fmt.Println("find 表示查找員工") fmt.Println("delete 表示刪除員工") fmt.Println("update 表示更新員工") fmt.Println("exit 表示退出系統") fmt.Println("請輸入指令") fmt.Scanln(&key) switch key { case "input": fmt.Println("輸入僱員id ") fmt.Scanln(&id) fmt.Println("輸入僱員name") fmt.Scanln(&name) emp := &Emp{ Id:id, Name:name, } hashtable.Insert(emp) case "show": hashtable.ShowAll() case "find": fmt.Println("輸入僱員id ") fmt.Scanln(&id) fmt.Println(id) hashtable.Find(id) case "delete": fmt.Println("輸入僱員id ") fmt.Scanln(&id) hashtable.Del(id) case "update": fmt.Println("輸入僱員id ") fmt.Scanln(&id) fmt.Println("輸入僱員new name") fmt.Scanln(&name) hashtable.Update(id,name) case "exit": os.Exit(0) default: fmt.Println("輸入錯誤") } fmt.Println() } }