Golang单链表反转(迭代与栈方式)

 

代码如下(代码大意表达,没有考虑和处理各种空等意外情况):

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()
}

  

对于栈方式反转示意图如下

 

 

程序运行结果:

posted @ 2020-06-06 16:26  impluse  阅读(799)  评论(0编辑  收藏  举报