golang实现hash表(散列)

使用hash原理,模拟数据库保存数据,直接操作内存编辑数据,

package main

import (
	"errors"
	"fmt"
	"os"
)

//hash链表的基本使用

//思路
//1、创建一个hash结构体,里面保存自己自定义数量的链表数组
//2、创建一个链表,用来保存用户数据
//3、每次插入前先计算插入的哪一个数组,根据id从小到大依次插入,这样做是为了查询快

//定义方法
type HashFunc interface {
	Push(link *Link) error
	Find(id int) (*Link, error)
	Del(id int) error
	Update(id int) error
	Each()
}

//用户数据链表
type Link struct {
	Id   int
	Name string
	Next *Link
}

//hashTable
type HashTable struct {
	Table *[7]*Link
}

func (this *Link) publish(link *Link) (*Link, error) {

	//当这张表为空时
	if this == nil {
		this = link
		return this, nil
	}

	//插入的元素小于第一个元素时
	tmp := this
	if this.Id > link.Id {
		link.Next = tmp
		this = link
	} else {

		for {
			if tmp.Next == nil {
				break
			}

			if tmp.Next.Id < link.Id {
				tmp = tmp.Next
			} else {
				break
			}
		}

		link.Next = tmp.Next
		tmp.Next = link
	}

	return this, nil
}

//获取插入表id
func getHashIndex(id int) int {
	return id % 7
}

//添加元素方法
func (this *HashTable) Push(link *Link) error {
	//把hashTable的7个数组看成7张表,当我们插入元素时根据自己的规则获取需要插入到哪张表,这样设计的目的是提高我们操作数据的数度,理论上有多少张表就可以提高多少倍的熟读;

	//获取需要插入到那张表
	index := getHashIndex(link.Id)

	k, err := this.Table[index].publish(link)
	if err != nil {
		return err
	}
	this.Table[index] = k

	return nil
}

//查询方法
func (this *HashTable) Find(id int) (*Link, error) {
	//获取表索引
	index := getHashIndex(id)

	//判断表是否为空
	if this.Table[index] == nil {
		return nil,errors.New("数据不存在")
	}

	tmp := this.Table[index]
	for {
		if 	tmp.Id == id {
			return tmp,nil
		}else {
			if tmp.Next != nil{
				tmp = tmp.Next
			}else {
				return nil,errors.New("数据不存在")
			}
		}
	}
}

//删除方法
func (this *HashTable) Del(id int) error {
	//获取表索引
	index := getHashIndex(id)

	//判断hash是否存在
	tmp := this.Table[index]
	if tmp == nil {
		return errors.New("链表为空")
	}

	//判断第一个元素是否等于需要删除的元素
	if tmp.Id == id {
		this.Table[index] = tmp.Next
		return nil
	}

	//第一个元素不等于需要删除的元素,所以从第二个开始查找
	for {
		if tmp.Next == nil {
			return errors.New("id is not find")
		}

		if tmp.Next.Id == id {
			tmp.Next = tmp.Next.Next
		}else {
			tmp = tmp.Next
		}
	}
}

//修改方法
func (this *HashTable) Update(id int,name string) error {
	//获取表索引
	index := getHashIndex(id)

	//判断hash是否存在
	tmp := this.Table[index]
	if tmp == nil {
		return errors.New("链表为空")
	}

	for {
		if tmp.Id == id {
			tmp.Name = name;
			return nil
		}

		if tmp.Next != nil{
			tmp = tmp.Next
		}else {
			break
		}
	}

	return errors.New("id is not find")
}

//查看所有元素
func (this *HashTable) Each() {
	table := this.Table

	for key, val := range table {
		if val == nil {
			fmt.Printf("表%v为空\n",key)
			continue
		}

		for {
			fmt.Println(val)
			if val.Next == nil {
				break
			}else {
				val = val.Next
			}
		}
		fmt.Println("------------------------------------")
	}
}

func main() {
	hashTale := new(HashTable)

	table := [7]*Link{}
	hashTale.Table = &table

	link := &Link{}
	fmt.Println("程序已启动。。。")
	var flag int
	for{
		fmt.Println("|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|")
		fmt.Println("1 查看列表")
		fmt.Println("2 查找成员")
		fmt.Println("3 修改成员")
		fmt.Println("4 删除成员")
		fmt.Println("5 添加成员")
		fmt.Println("0 退出系统")
		fmt.Print("请输入指令:")
		_, err := fmt.Scan(&flag)
		if err != nil {
			fmt.Print("指令输入错误,请重新输入")
			continue
		}

		switch flag {
		case 1:
			hashTale.Each()
		case 2:
			fmt.Print("成员ID:")
			_, err := fmt.Scan(&link.Id)
			if err != nil {
				fmt.Print("指令输入错误,请重新输入")
				continue
			}
			res, err := hashTale.Find(link.Id)
			if err != nil {
				fmt.Println(err)
			}else {
				fmt.Println(res)
			}
		case 3:
			fmt.Print("成员ID:")
			_, err := fmt.Scan(&link.Id)
			if err != nil {
				fmt.Print("指令输入错误,请重新输入")
				continue
			}
			fmt.Print("成员name:")
			_, err = fmt.Scan(&link.Name)
			if err != nil {
				fmt.Print("指令输入错误,请重新输入")
				continue
			}
			if err := hashTale.Update(link.Id,link.Name);err != nil{
				fmt.Println(err)
			}
		case 4:
			fmt.Print("成员ID:")
			_, err := fmt.Scan(&link.Id)
			if err != nil {
				fmt.Print("指令输入错误,请重新输入")
				continue
			}

			if err := hashTale.Del(link.Id);err != nil {
				fmt.Println(err)
			}
		case 5:
			fmt.Print("成员ID:")
			_, err := fmt.Scan(&link.Id)
			if err != nil {
				fmt.Print("指令输入错误,请重新输入")
				continue
			}
			fmt.Print("成员name:")
			_, err = fmt.Scan(&link.Name)
			if err != nil {
				fmt.Print("指令输入错误,请重新输入")
				continue
			}
			if err := hashTale.Push(link);err != nil{
				fmt.Println(err)
			}else {
				fmt.Println("添加成功")
			}
		case 0:
			os.Exit(0)
		}
		fmt.Println()
	}
}

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值