代码如下(代码大意表达,没有考虑和处理各种空等意外情况):
package main
import (
"strings"
"github.com/golang-collections/collections/stack"
)
type node struct {
i int
next *node
}
var linkList *node
func makeList() {
// 创建一个单链表: 0->1->2->3->4->5->6->7->8->9
// 这里依次遍历到尾部追加,也可以使用一个尾指针来指示快速添加
linkList = &node{i: 0}
for i := 1; i < 10; i++ {
linkList := linkList
for {
if linkList.next == nil {
linkList.next = &node{i: i}
break
}
linkList = linkList.next
}
}
}
func traverse() {
// 遍历单链表
iter := linkList
for {
if iter != nil {
if iter.next == nil {
print(iter.i)
} else {
print(iter.i, "->")
}
iter = iter.next
} else {
break
}
}
println()
}
func reverse() {
// 迭代反转链表
var next *node // 反转后所应该指向的下一个节点,默认初始化为空
for {
// 首先保存原链表反转前的下一个节点
tmp := linkList.next
// 反转后所应该指向的下一个节点
linkList.next = next
// 上面两步对于一个节点来说先保存其旧next,然后用新next覆盖
// 当前节点已反转,它应当被下一个待反转节点next指向,这里把它覆盖存入next中
next = linkList
// tmp来自每个节点的next,如果tmp为空,说明已经反转到最后一个节点了
if tmp == nil {
break
} else {
// tmp不为空,将当前节点指针linkList推进到下一个节点,即推进到tmp(反转工作循环前两步已经完成)
linkList = tmp
}
}
}
func reverseByStack() {
// 初始化一个栈
s := stack.New()
for {
if linkList != nil {
// 每个节点依次压栈
s.Push(linkList)
linkList = linkList.next
} else {
break
}
}
// 弹栈,获取最后一个栈元素
iter := s.Pop().(*node)
// 保存最后一个元素(反正后第一个元素)指针
linkList = iter
for {
// 栈不空时,说明所有节点未处理完
if s.Len() > 0 {
// 依次出栈
iter.next = s.Pop().(*node)
// 上一个出栈节点指向当前出栈节点
iter = iter.next
} else {
break
}
}
iter.next = nil
}
func m() {
makeList()
traverse()
reverse()
traverse()
reverse()
traverse()
reverse()
traverse()
}
func n() {
makeList()
traverse()
reverseByStack()
traverse()
reverseByStack()
traverse()
reverseByStack()
traverse()
}
func main() {
m()
println(strings.Repeat("=", 28))
n()
}
对于栈方式反转示意图如下

程序运行结果:
