title: Go数据结构与算法-单链表
tags: go,算法
介绍
有时候数组不一定是最佳的组织数据的数据结构,因为数组通常都是固定大小的,当数据填满时, 再加入新元素就变得很困难。因此如果需要频繁的添加或者删除元素,可以考虑使用链表组织数据,链表是一种线性表,但是不会按照线性的顺序存储数据,而是在每一个节点里面存到写一个节点的指针。作为单链表它最大的特点就是能随意增加长度,也能随意减少长度。
链表的结构我们可以抽象的看成一个火车,火车头代表着链表的头部,车厢代表着链表中的节点,数据则带着每节车厢中的货物。
链表的特性:
- 插入元素容易
- 元素访问困难
链表的操作是通过指针来实现的,这个指针类似一个火车管理员,它可以对火车的车厢进行添加和减少,也可以根据车厢号查找货物。
代码演示
package main
import "fmt"
//线性表中的链式存储结构
//第一个节点为头节点,并不真实保存数据,头节点基本代表了整个链表
// Item 可以理解为范性,也就是任意的数据类型
type Item interface {
}
//声明节点类型
// 一个节点,除了自身的数据之外,还必须指向下一个节点,尾部节点指向为nil
type Node struct {
//数据域
Data Item // 为任意数据类型
//地址域
NextNode *Node
}
var head *Node //声明全局变量,保存头结点
var curr *Node // 保存当前节点
// go语言方法,对比与下面的CreateHeadNode,方法可以理解为面向对象里面对象的方法,虽然实现的功能
// 这个是go语言区别与其他语言的设计方式,也是go语言很重要的一部分。
//创建头结点
func (node *Node)CreateHeadNode(data Item) {
node = new(Node)
node.Data = data
node.NextNode = nil
//保存头结点
head = node
curr = node
//return node
}
//添加新节点
func (node *Node)AddNode(data Item) {
node= new(Node)
node.Data = data
node.NextNode = nil
//挂接节点
curr.NextNode = node
curr = node
}
//遍历链表
func (node *Node)ShowNodes() {
node = head
for {
if node.NextNode == nil {
fmt.Println(node.Data)
break
} else {
fmt.Println(node.Data)
node = node.NextNode
}
}
}
//计算节点的个数
func (node *Node)NodeCnt() int {
var cnt int = 1
node = head
for {
if node.NextNode == nil {
break
} else {
node = node.NextNode
cnt = cnt + 1
}
}
return cnt
}
//插入节点
func (node *Node)InsertNodeByIndex(index int, data Item) {
if index == 0 {
//添加的为新的头节点
// var node *Node = new(Node)
node.Data = data
node.NextNode = head
head = node
} else if index > node.NodeCnt()-1 {
//添加节点
node.AddNode(data)
} else {
//中间插入节点
var n = head
for i := 0; i < index-1; i++ {
n = n.NextNode
}
var newNode *Node = new(Node)
newNode.Data = data
newNode.NextNode = n.NextNode
n.NextNode = newNode
}
//return nil
}
//删除节点
func (node *Node)DeleteNodeByIndex(index int) {
node = head
if index == 0 {
//删除头节点,就是第二个节点为头结点
head = node.NextNode
} else {
for i := 0; i < index-1; i++ {
node = node.NextNode
}
node.NextNode = node.NextNode.NextNode
}
}
//修改指定下标的节点内容
func (node *Node)UpdateNodeByIndex(index int, data Item) {
node = head
if index == 0 {
head.Data = data
} else {
for i := 0; i < index; i++ {
node = node.NextNode
}
node.Data = data
}
}
func main() {
//创建头结点
p :=head
p.CreateHeadNode(0)
//添加节点
for i:=1; i<10;i++{
p.AddNode(i)
}
fmt.Printf("打印所有节点\n")
p.ShowNodes()
fmt.Printf("一共有%d个节点\n", p.NodeCnt())
fmt.Printf("当前节点:")
fmt.Println(p.NodeCnt())
p.DeleteNodeByIndex(2)
fmt.Println("删除节点2")
fmt.Printf("打印所有节点\n")
p.ShowNodes()
fmt.Printf("一共有%d个节点\n", p.NodeCnt())
fmt.Println("插入节点")
p.InsertNodeByIndex(2,2)
fmt.Printf("打印所有节点\n")
p.ShowNodes()
}