• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

单链表-Go语言实现

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

单链表;双链表;环形链表;

带头节点的单链表

head -> a1 -> a2 -> a3

有了头结点后,对在第一个元素结点前插入结点和删除第一个结点,其操作与对其它结点的操作统一了。

单链表的优缺点及使用场景

优点:

  • 插入删除操作便捷;
  • 不需要一块集中的内存空间;元素的存储单元是任意的,可连续也可不连续;
  • 不需要限定长度;

缺点:

  • 不支持随机存取,仅可以从头开始查找;其查找时间复杂度为O(n);
  • 存放元素时需要另外开辟一个指针域的空间;额外占用内存空间;

使用场景:

不清楚总体大小,且需要频繁的插入或删除操作;

节点结构

type LinkNode struct {
	Data interface{}	//Data使用接口,可以为任意类型,范性;
	Next *LinkNode
}

type LList LinkNode

实现接口
这里使用接口,写代码的时候忘了用了,直接用结构体的方法了;

type LLister interface {
	Creat_head()                  //头插法创建链表
	Creat_tail()                  //尾插法创建链表
	Insert(v interface{}, i int)  //插入v到第ige
	Delete(index int) interface{} //删除第i+1(i从0开始)个,返回value
	GetLength() int               //统计节点个数(不包括头节点)
	Search(v interface{}) int     //查找值为v的元素,返回所在位置
	Display()
}

创建单链表

  • 头插法:将新增节点插入到头节点之后;

    • 最先插入的在最后;读出链表是倒序;
    • head->9->8->7->6->5->4->3->2->1->0
    func (head *LList) Creat_head() {
    	for i := 0; i < 10; i++ {
    		s := &LinkNode{
    			Data: i,
    		}
    		s.Next = head.Next
    		head.Next = s
    	}
    }
    
  • 尾插法:“正常排队”

    • 先插入在最前
    • head->0->1->2->3->4->5->6->7->8->9
    func (head *LList) Creat_tail() {
    	p := head
    	for i := 0; i < 10; i++ {
    		s := &LinkNode{
    			Data: i,
    		}
    		p.Next = s
    		p = s
    	}
    }
    

单链表插入节点

这是有头节点的情况下,也就是头指针->头节点->第一个元素;

插入要明确插入规则,否则会乱掉;

在自己做练习时,没有特别要求时,确定好插入标准时必要的;

插入位置index,就相当于那个间隙,所以index可以是0~5(5个元素);

当index==length时,相当于尾抽;length==0时相当于头插;

  • 插入位置为index,先判断i是否合理;index < 0 || index > length
  • 移动p(p:=head)到插入位置;
  • 插入;
func (head *LList) Insert(v interface{}, index int) {
	length := head.GetLength()       //链表的长度,如3个就是3
	if index < 0 || index > length { //i=0时相当于头插法;i=length相当于尾插法;i=1时是在第一个节点之后插入
		fmt.Printf("index out of range %d\n", length)
		return
	}
	p := head
	for i := 0; i < index; i++ {
		p = p.Next
	}
	newNode := &LinkNode{Data: v}
	newNode.Next = p.Next
	p.Next = newNode
}

单链表删除

删除和插入类似,边界判断时稍有区别;

index=几就产出间隔后面的元素,比如index=0就删除a1,那么index不能为5,也就是边界条件:index < 0 || index >= length;

func (head *LList) Delete(index int) interface{} {
	length := head.GetLength()
	if index < 0 || index >= length {
		fmt.Printf("index out of range %d\n", length)
		return "index out of range, please check."
	}
	p := head
	for i := 0; i < index; i++ {
		p = p.Next
	}
	deleteNode := p.Next
	p.Next = p.Next.Next
	return deleteNode.Data
}

单链表完整代码

package main

import (
	"fmt"
)

type LinkNode struct {
	Data interface{}
	Next *LinkNode
}

type LList = LinkNode

type LLister interface {
	Creat_head()                  //头插法创建链表
	Creat_tail()                  //尾插法创建链表
	Insert(v interface{}, i int)  //插入v到第ige
	Delete(index int) interface{} //删除第i+1(i从0开始)个,返回value
	GetLength() int               //统计节点个数(不包括头节点)
	Search(v interface{}) int     //查找值为v的元素,返回所在位置
	Display()
}

func newLList() *LList {
	return &LList{Next: nil}
}

func (head *LList) Creat_head() {
	for i := 0; i < 10; i++ {
		s := &LinkNode{
			Data: i,
		}
		s.Next = head.Next
		head.Next = s
	}
}

func (head *LList) Creat_tail() {
	p := head
	for i := 0; i < 10; i++ {
		s := &LinkNode{
			Data: i,
		}
		p.Next = s
		p = s
	}
}

func (head *LList) Insert(v interface{}, index int) {
	length := head.GetLength()       //链表的长度,如3个就是3
	if index < 0 || index > length { //i=0时相当于头插法;i=length相当于尾插法;i=1时是在第一个节点之后插入
		fmt.Printf("index out of range %d\n", length)
		return
	}
	p := head
	for i := 0; i < index; i++ {
		p = p.Next
	}
	newNode := &LinkNode{Data: v}
	newNode.Next = p.Next
	p.Next = newNode
}

func (head *LList) Delete(index int) interface{} {
	length := head.GetLength()
	if index < 0 || index >= length {
		fmt.Printf("index out of range %d\n", length)
		return "index out of range, please check."
	}
	p := head
	for i := 0; i < index; i++ {
		p = p.Next
	}
	deleteNode := p.Next
	p.Next = p.Next.Next
	return deleteNode.Data
}

func (head *LList) GetLength() int {
	p := head.Next
	var length int = 0
	for p != nil {
		length++
		p = p.Next
	}
	return length
}

func (head *LList) Search(value int) interface{} {
	p := head.Next
	index := 1
	for p != nil {
		if p.Data == value {
			return index
		}
		index++
		p = p.Next
	}
	return fmt.Sprintf("the value %v is not in the llist;", value)
}

func (head *LList) Display() {
	p := head.Next
	fmt.Print("head")
	for p != nil {
		fmt.Printf("->%v", p.Data)
		p = p.Next
	}
	fmt.Println()
}

func main() {
	head := newLList()
	head.Creat_tail()
	head.Display()
	head.Insert(99, 10)
	head.Display()
	result := head.Search(99)
	fmt.Printf("search result is: %v\n", result)
	deleteValue := head.Delete(10)
	fmt.Printf("delete node value is %v\n", deleteValue)
	head.Display()
	fmt.Printf("link list length is: %v", head.GetLength())
}

鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
go系列(1)- linux下安装go环境发布时间:2022-07-10
下一篇:
Go语言实现bitmap算法发布时间:2022-07-10
热门推荐
热门话题
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap