Golang 实现链表类型及相关操作

Golang 实现链表类型及相关操作

最近工作用到了 golang,并且需要我实现一个链表的类型来作为生产者-消费者的“仓库”。由于自己是边用边学,就先写一个小 demo 熟悉一下,在里面实现了一个链表的类型,并包括了遍历以及增、查、删等操作,代码如下:

package main

import "fmt"

type StuInfo struct {
	id, name string
	age      int
	address  string
}

type Node struct {
	*StuInfo
	next *Node
}

type List struct {
	head, tail *Node
	cnt        int
}

func NewStu(id, name string, age int, address string) *StuInfo {
	stu := &StuInfo{
		id:      id,
		name:    name,
		age:     age,
		address: address,
	}
	return stu
}

func NewNode(stu *StuInfo) *Node {
	return &Node{
		StuInfo: stu,
		next:    nil,
	}
}

// 尾插法
func (li *List) AddTail(newNode *Node) {
	if li.head == nil && li.tail == nil {
		// 向空链表插入一个新节点
		li.head = newNode
		li.tail = newNode
		li.cnt += 1
		return
	}
	li.tail.next = newNode
	li.tail = newNode
	li.cnt += 1
}

// 根据 id 查找节点
func (li *List) Search(id string) (result *Node, ret bool) {
	if li.cnt == 0 {
		fmt.Println("list is empty!")
		return nil, false
	}

	result = li.head
	ret = false
	for result != li.tail {
		if result.id == id {
			ret = true
			break
		} else {
			result = result.next
		}
	}
	if !ret {
		// 遍历链表未找到目标节点
		return nil, ret
	}
	// 找到了目标节点
	return result, ret
}

// 根据 id 删除一个节点
func (li *List) Delete(id string) (ret bool) {
	if li.cnt == 0 {
		fmt.Println("list is empty!")
		return false
	}
	if li.head.id == id {
		// 如果要删除的节点是头结点
		li.cnt -= 1
		if li.head.next == nil {
			// 如果只有一个节点,并且刚好被删除
			li.head = nil
			li.tail = nil
			return true
		}
		// 否则直接将头节点后移
		li.head = li.head.next
		return true
	}
	// 若链表不为空且要删除的点不是头结点,就进行查找并删除
	pre := li.head
	cur := li.head.next
	for cur != nil {
		if cur.id == id {
			// 找到目标节点,删除
			pre.next = cur.next
			if cur == li.tail {
				// 如果目标节点是尾结点
				li.tail = pre
			}
			cur.next = nil
			cur = nil
			li.cnt -= 1
			return true
		}
		pre = cur
		cur = cur.next
	}
	// 目标节点不在链表中
	fmt.Printf("%s is not our student\n", id)
	return false
}

// 遍历链表
func (li *List) Traversal() {
	if li.cnt == 0 {
		fmt.Println("list is empty!")
		return
	}
	fmt.Println("now list size is", li.cnt)
	cur := li.head
	for cur != nil {
		fmt.Printf("stu: %s\t%s\t%d\t%s\n", cur.id, cur.name, cur.age, cur.address)
		cur = cur.next
	}
}

func listTest() {
	l1 := *new(List)

	stu1 := NewStu("22001", "LingHuChong", 23, "ShanXi")
	stu2 := NewStu("22002", "HuangRong", 19, "HuBei")
	stu3 := NewStu("22003", "XiaoFeng", 27, "BeiJing")
	node1 := NewNode(stu1)
	node2 := NewNode(stu2)
	node3 := NewNode(stu3)

	l1.Traversal()
	l1.Delete("22001")
	l1.AddTail(node1)
	l1.AddTail(node2)
	l1.AddTail(node3)
	l1.Traversal()
	target := "22001"
	s, ret := l1.Search(target)
	if !ret {
		fmt.Printf("didn't find %s\n", target)
	} else {
		fmt.Printf("found %s:  %s\t%d\t%s\n", target, s.name, s.age, s.address)
	}
	if l1.Delete(target) {
		fmt.Println("deleted", target)
	}
	l1.Traversal()
	if l1.Delete("22002") {
		fmt.Println("deleted 22002")
	}
	l1.Traversal()
	if l1.Delete("22003") {
		fmt.Println("deleted 22003")
	}
	l1.Traversal()
}

func main() {
	listTest()
}

运行结果如下:
在这里插入图片描述
写在最后,实际上不需要链表,利用 golang 内置的切片类型,完全可以满足一般的需求

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值