Go语言数据结构-单链表入门

Go语言数据结构-单链表入门

go-链表示意图

链表相关概念

首先链表是一种线性表,是一个有序的序列。这意味着表中的各个表项是相继排序的,且每两项都有直接前驱和直接后继的关系,也就是说,线性表存在唯一的第一表项和唯一的最后表项。
L = ( a 1 , … , a i , a i + 1 , … , a n ) L = (a_1,\dots,a_i,a_{i+1},\dots,a_n) L=(a1,,ai,ai+1,,an)
单链表是一种最简单的链表表示,也叫作线性链表。它的表项主要由储存数据和储存节点组成,储存节点用于实现与其他表项的逻辑关系。

单链表的特点是长度可以很方便地进行扩充。单链表的数据元素的顺序与各节点的物理顺序可能不一致,它们是通过节点指针相联系的。

Go语言单链表实现

在Go语言中单链表使用一个结构体来实现。

image-20220321024756577

对于一个存储数据类型为type的数据的单链表typeNode节点结构体可以这样声明:

type typeNode struct {
    data type		// 存储的数据
    next *typeNode	// 指向下一个节点的指针
}

单链表的创建与操作都需要辅助节点变量来完成。创建时需要一个头结点head,操作时需要辅助节点temp。所有的方法编写也是针对头结点head指针编写的。

插入

image-20220321034513163 image-20220321034552502 image-20220321034628394
// temp是一个辅助节点,表示Node_i
newNode.next = temp.next
temp.next = newNode
length++

删除

image-20220321034947923 image-20220321035155666
// temp是一个辅助节点,表示Node_i
temp.next = temp.next.next
length--

单链表实例

  • 创建一个存储水浒英雄的单链表,有英雄名称name string和英雄编号no int
  • 可以实现链表元素的添加与删除
  • 另外想办法可以得到按编号排序好的英雄单链表

代码参考

package main

import (
	"fmt"
)

// 定义节点
type heroNode struct {
	no   int
	name string
	next *heroNode // nextNode
}

var length = 0 // 用全局变量来记录链表节点数,注意这样只能创建一个链表

// 链表插入节点
// 从最后插入
func (head *heroNode) insert(newHeroNode *heroNode) {
	// 1.创建辅助节点
	temp := head
	// 2.先定位到最后的节点
	for {
		if temp.next == nil { // 表示找到最后
			break
		}
		temp = temp.next // 不断的找向下一个节点
	}
	// 3.插入节点
	temp.next = newHeroNode
	length++ // 长度增加
}

// 排序插入(按照编号从小到大排序)
func (head *heroNode) sortInsert(newHeroNode *heroNode) {
	// 1.创建辅助节点和标记
	temp := head
	flag := false
	// 2.先定位要插入的排序位置
	for {
		if temp.next == nil {
			break
		} else if temp.next.no > newHeroNode.no {
			break
		} else if temp.next.no == newHeroNode.no {
			flag = true
		}
		temp = temp.next
	}
	// 3.插入第一个节点
	if !flag { // 确保此编号的元素并不在链表中
		newHeroNode.next = temp.next
		temp.next = newHeroNode
        length++
	}
}

// 获取长度
func (head *heroNode) Length() int {
	return length
}

// 删除节点
func (head *heroNode) delete(heroNo int) {
	// 1.创建辅助节点和标记
	temp := head
	flag := false
	// 2.先定位要插入的排序位置
	for {
		if temp.next == nil {
			break
		} else if temp.next.no == heroNo {
			flag = true
			break
		}
		temp = temp.next
	}
    // 3.节点删除
	if flag {	// 表示找到了
		temp.next = temp.next.next	// 删除节点
		length--
	}
}

// 清楚所有节点
func (head *heroNode) clear() {
	head.next = nil
	length = 0 // 长度归零
}

// 显示链表的所有节点
func (head *heroNode) printNode() {
	// 1.创建辅助节点
	temp := head
	// 2.遍历整个链表
	if temp.next == nil { // 不能是空链表
		fmt.Println("...")
		return
	}
	temp = temp.next
	for {
		// 3.打印输出
		fmt.Printf("[%d,%s]", temp.no, temp.name)
		temp = temp.next
		if temp == nil { // 最后节点
			fmt.Println()
			break
		}
	}
}

// -----------------------------------------main----------------------------------------
func main() {
	// 1.构建头结点
	head := &heroNode{}
	// 2.添加新节点
	head.insert(&heroNode{1, "宋江", nil})
	head.insert(&heroNode{2, "卢俊义", nil})
	head.insert(&heroNode{3, "吴用", nil})
	head.insert(&heroNode{4, "公孙胜", nil})
	println(head.Length(), "----------------------") // 4
	head.printNode()	// [1,宋江][2,卢俊义][3,吴用][4,公孙胜]
	// 3.删除节点
	head.delete(3)
	println(head.Length(), "----------------------") // 3
	head.printNode()	// [1,宋江][2,卢俊义][4,公孙胜]
	// 4.清除节点
	head.clear()
	println(head.Length(), "----------------------") // 0
	head.printNode()	// ...
	// 5.有序插入节点
	head.sortInsert(&heroNode{4, "公孙胜", nil})
	head.sortInsert(&heroNode{2, "卢俊义", nil})
	head.sortInsert(&heroNode{3, "吴用", nil})
	head.sortInsert(&heroNode{7, "秦明", nil})
	head.sortInsert(&heroNode{1, "宋江", nil})
	head.sortInsert(&heroNode{6, "林冲", nil})
	head.sortInsert(&heroNode{5, "关胜", nil})
	head.sortInsert(&heroNode{8, "呼延灼", nil})
	println(head.Length(), "----------------------") // 8
	head.printNode()	// [1,宋江][2,卢俊义][3,吴用][4,公孙胜][5,关胜][6,林冲][7,秦明][8,呼延灼]
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值