package main import ( "errors" "fmt" "log" ) // 单链表 // 特征: // 1. 每个节点都包含指向下一个节点的指针 next // 2. 链表逻辑上是序列,但在内存中存储是不规则的 // 实现: // 1. 头节点(根节点) head 单链表的起始位置,头节点不存放任何数据 // 2. 链表用来实现队列、栈、有序序列(插入排序) // 3. 链表方法: // a. 添加一个节点 Add // b. 移除一个节点 // c. 遍历节点 // ValNode 值节点,存放所需数据,至于数据是什么,已经不重要,重要的是有一个指向下一个值节点的指针 next type ValNode struct { // data 存放数据 data interface{} // 指向下一个节点的值节点指针,如果没有则为空地址 nil next *ValNode } // SingleLink 单链表,包含一个指向链表头部的指针 head type SingleLink struct { // 头指针 head 指向链表的头部 head *ValNode } func NewSingleLink() *SingleLink { return &SingleLink{ head: &ValNode{}, } } // AddNode 在尾部添加一个节点: 找打尾部节点,将尾部节点的next指向新增加的节点 func (sl *SingleLink) AppendNode(v *ValNode) { // 1. 找到尾部 tmp := sl.head for tmp.next != nil { tmp = tmp.next } // 2. 在尾部添加一个节点 tmp.next = v } // 在尾部删除一个节点: 判断链表是否为空,判断链表是否只有一个元素,找到链表最后的上一个元素将next置为nil func (sl *SingleLink) PopNode() (v *ValNode, err error) { // 1. 判断是否是空链表, 空链表则返回空链表错误 if sl.head.next == nil { err = errors.New("链表为空") return } // 2. 判断链表是否只有一个元素,如果为一个元素则将 head头节点的next置为 nil if sl.head.next.next == nil { v = sl.head.next sl.head.next = nil } // 3. 找到链表的上一个元素将next置为nil tmp := sl.head for tmp.next.next != nil { tmp = tmp.next } v = tmp.next tmp.next = nil return } // 在头部删除一个节点: 判断链表是否为空,判断链表是否只有一个元素,将链表头指向链表头指向的下一个元素 func (sl *SingleLink) PopLeftNode() (v *ValNode, err error) { // 1. 判断是否是空链表, 空链表则返回空链表错误 if sl.head.next == nil { err = errors.New("链表为空") return } // 2. 判断链表是否只有一个元素,如果为一个元素则将 head头节点的next置为 nil if sl.head.next.next == nil { v = sl.head.next sl.head.next = nil } // 3. 获取链表头指向的下一个元素,并将链表头指向的下一个元素的下一个元素 v = sl.head.next sl.head.next = sl.head.next.next return } // ListLink 遍历列表,判断链表是否为空 func (sl *SingleLink) ListLink() { // 1. 判断是否是空链表 if sl.head.next == nil { fmt.Println("SingleLink empty") return } // 2. 遍历链表 tmp := sl.head.next for tmp != nil { fmt.Println(tmp.data) tmp = tmp.next } } // 通过链表的 AppendNode 和 PopNode实现了栈 // 通过链表的 AppendNode 和 PopLeftNode实现了队列 func main() { sl := NewSingleLink() node1 := &ValNode{ data: 100, } node2 := &ValNode{ data: 200, } sl.AppendNode(node1) sl.AppendNode(node2) node3, err := sl.PopNode() if err != nil { log.Println(err) } fmt.Println(node3) sl.ListLink() }