写在前面
在学习Go语言中的结构体实现单链表时,发现参考资料给的一些例子都是十分简单。上网查了一圈,也没有找到更多的稍微复杂一些的例子,于是结合以前学习Python操作单链表的思路,给出了Go语言的版本,仅供学习参考。
package main
import "fmt"
// ListNode 链表的节点
type ListNode struct {
val int
next *ListNode
}
// is_empty判断一个链表是否为空
func (l *ListNode) is_empty() bool {
return l.next == nil
}
// link_len 检查链表的长度
func (l *ListNode) link_len() int {
count := 0
cur := l.next
for cur != nil {
count++
cur = cur.next
}
return count
}
// append 从尾部插入节点
func (l *ListNode) append(elm int) {
node := new(ListNode)
node.val = elm
if l.is_empty() {
l.next = node
} else {
cur := l.next
for cur.next != nil {
cur = cur.next
}
cur.next = node
}
}
// add 从头部插入节点
func (l *ListNode) add(elm int) {
node := new(ListNode)
node.val = elm
if l.is_empty() {
l.next = node
} else {
node.next = l.next
l.next = node
}
}
// Insert 从指定位置插入节点
func (l *ListNode) Insert(pos int, elm int) {
node := new(ListNode)
node.val = elm
if l.is_empty() {
l.next = node
} else if pos >= l.link_len() {
l.append(elm)
} else if pos <= 0 {
l.add(elm)
} else {
count := 1
cur := l.next
for cur != nil {
if pos == count {
node.next = cur.next
cur.next = node
break
} else {
count++
cur = cur.next
}
}
}
}
// delete 删除链表中的元素
func (l *ListNode) delete(pos int) {
if l.is_empty() {
fmt.Println("链表为空!!!")
return
} else if l.link_len() == 1 {
l.next = nil
} else if pos <= 0 {
l.next = l.next.next
} else if pos >= l.link_len() {
pre := l.next
cur := l.next
for cur.next != nil {
pre = cur
cur = cur.next
}
pre.next = nil
} else {
pre := l.next
cur := l.next
count := 0
for cur.next != nil {
if pos == count {
pre.next = cur.next
break
}
count++
pre = cur
cur = cur.next
}
}
}
// Reverse 链表逆序
func (l *ListNode) Reverse() {
if l.is_empty() {
fmt.Println("链表为空!!!")
return
} else {
cur := l.next
next := cur.next
pre := new(ListNode)
for cur.next != nil {
cur.next = pre.next
pre.next = cur
cur = next
next = cur.next
}
cur.next = pre.next
l.next = cur
}
}
// RemoveTheSame 从无序链表中移除重复项
func (l *ListNode) RemoveTheSame() {
if l.is_empty() {
fmt.Println("链表为空!!!")
return
} else {
cur := l.next
for cur != nil {
next := cur.next
pre := cur
for next != nil {
if next.val == cur.val {
pre.next = next.next
next = next.next
} else {
pre = next
next = next.next
}
}
cur = cur.next
}
}
}
// Traverse 遍历链表
func (l *ListNode) Traverse() {
cur := l.next
for cur != nil {
fmt.Printf("%d ", cur.val)
cur = cur.next
}
fmt.Printf("\n")
}
func main() {
link := new(ListNode)
fmt.Println("the link is empty?", link.is_empty())
fmt.Println("从尾部插入节点--------")
link.append(1)
link.append(2)
link.append(3)
link.Traverse()
fmt.Println("--------从尾部插入节点")
fmt.Println("从头部插入节点--------")
link.add(100)
link.Traverse()
fmt.Println("--------从头部插入节点")
fmt.Println("the length of link is:", link.link_len())
fmt.Println("从任意位置插入节点--------")
fmt.Println("原始链表")
link.Traverse()
fmt.Println("↓在-1位置插入200")
link.Insert(-1, 200)
link.Traverse()
fmt.Println("↓在5位置插入300")
link.Insert(5, 300)
link.Traverse()
fmt.Println("↓在2位置插入666")
link.Insert(2, 666)
link.Traverse()
fmt.Println("--------从任意位置插入节点")
fmt.Println("链表反转--------")
fmt.Println("原始链表")
link.Traverse()
fmt.Println("↓反转后")
link.Reverse()
link.Traverse()
fmt.Println("--------链表反转")
fmt.Println("删除链表中的重复项--------")
link.Insert(1, 2)
link.Insert(3, 2)
link.append(666)
fmt.Println("原始链表")
link.Traverse()
fmt.Println("删除重复元素")
link.RemoveTheSame()
link.Traverse()
fmt.Println("--------删除链表中的重复项")
fmt.Println("删除链表元素--------")
fmt.Println("原始链表")
link.Traverse()
fmt.Println("↓删除第0个元素")
link.delete(0)
link.Traverse()
fmt.Println("↓删除第3个元素")
link.delete(3)
link.Traverse()
fmt.Println("↓删除第10个元素")
link.delete(10)
link.Traverse()
fmt.Println("--------删除链表元素")
}
运行结果如下:
the link is empty? true
从尾部插入节点--------
1 2 3
--------从尾部插入节点
从头部插入节点--------
100 1 2 3
--------从头部插入节点
the length of link is: 4
从任意位置插入节点--------
原始链表
100 1 2 3
↓在-1位置插入200
200 100 1 2 3
↓在5位置插入300
200 100 1 2 3 300
↓在2位置插入666
200 100 666 1 2 3 300
--------从任意位置插入节点
链表反转--------
原始链表
200 100 666 1 2 3 300
↓反转后
300 3 2 1 666 100 200
--------链表反转
删除链表中的重复项--------
原始链表
300 2 3 2 2 1 666 100 200 666
删除重复元素
300 2 3 1 666 100 200
--------删除链表中的重复项
删除链表元素--------
原始链表
300 2 3 1 666 100 200
↓删除第0个元素
2 3 1 666 100 200
↓删除第3个元素
2 3 1 100 200
↓删除第10个元素
2 3 1 100
--------删除链表元素
本文操作单链表的思路与我的一篇博客(数据结构与算法之单链表(一))一致,有兴趣的朋友可以阅读。
最后
在力扣题库里面找了一条简单的链表题
将两个升序链表合并为一个新的升序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
示例:
输入:1->2->4, 1->3->4
输出:1->1->2->3->4->4
/**
* Definition for singly-linked list.
* type ListNode struct {
* Val int
* Next *ListNode
* }
*/
// 常规思路
func mergeTwoLists(l1 *ListNode, l2 *ListNode) *ListNode {
head := new(ListNode) // 申明一个新的链表用于存储有序链表,head是头节点,代表整个链表
cur := head // 申明一个游标,操作的是结构体指针,所以修改有效
for l1 != nil && l2 != nil {
if l1.Val <= l2.Val {
cur.Next = l1
l1 = l1.Next
} else {
cur.Next = l2
l2 = l2.Next
}
cur = cur.Next
}
// 如果链表不等长,直接将剩余追加到新链表后面
if l1 == nil {
cur.Next = l2
}
if l2 == nil {
cur.Next = l1
}
return head.Next
}
// 递归
func mergeTwoLists(l1 *ListNode, l2 *ListNode) *ListNode {
if l1 == nil {
return l2
}
if l2 == nil {
return l1
}
head := new(ListNode)
if l1.Val <= l2.Val {
head = l1
head.Next = mergeTwoLists(l1.Next, l2)
}else{
head = l2
head.Next = mergeTwoLists(l1, l2.Next)
}
return head
}
使用递归的方法会在内存上消耗的多一点,但是不得不说go语言要比Python快多了(36ms,11.5M)。