分别对二叉树和单链表实现翻转!

204 阅读1分钟

单向链表翻转

单向链表说明

单向链表的反转是一个非常常见的链表类面试题,在 leetcode 的中,发现了有许多链表题目的解法,都是以反转链表为基础进行的。所以在这里记录一下单向链表的翻转。如下图所示:

revelink.png

单链表的反转,就如上图一样,而单链表的反转也有几种方式,今天我主要是想记录我用得最频繁的迭代的方式。

先来看下链表节点的定义:

// 定义节点结构体
type Node struct {
	Data interface{}	// 接口类型的数据data
	Next *Node		// 下一个节点
}

这就是最基础的一个链表节点,而反转链表的代码,其实非常的短,关键点就在于理解这几行代码究竟让链表产生了什么变化。

// 单向链表翻转
func (l *LinkList) ReverseList() {
	current := l.Header
	var pre *Node
	for current != nil {
		current, current.Next, pre = current.Next, pre, current
	}
	l.Header = pre
}

二叉树翻转

二叉树翻转实现效果如下图所示:

revelink2.png

先来看下二叉树节点的定义:

type Node struct {
	Key int
	Left *Node
	Right *Node
}

实现翻转的函数(基于 golang 递归方式实现):

// 递归方式实现二叉树翻转
func (n *Node) RevTree() {
	n.Left, n.Right = n.Right, n.Left

	if n.Left != nil {
		n.Left.RevTree()
	}

	if n.Right != nil {
		n.Right.RevTree()
	}
}

完整示例代码:

package main

import (
	"encoding/json"
	"fmt"
)

type Node struct {
	Key int
	Left *Node
	Right *Node
}

// 递归方式实现二叉树翻转
func (n *Node) RevTree() {
	n.Left, n.Right = n.Right, n.Left

	if n.Left != nil {
		n.Left.RevTree()
	}

	if n.Right != nil {
		n.Right.RevTree()
	}
}

// 测试
func main() {
	tree := Node{
		Key:   4,
		Left:  &Node{
			Key:   2,
			Left:  &Node{
				Key:   1,
				Left:  nil,
				Right: nil,
			},
			Right: &Node{
				Key:   3,
				Left:  nil,
				Right: nil,
			},
		},
		Right: &Node{
			Key:   7,
			Left:  &Node{
				Key:   6,
				Left:  nil,
				Right: nil,
			},
			Right: &Node{
				Key:   9,
				Left:  nil,
				Right: nil,
			},
		},
	}

	tree.RevTree()
	out, _ := json.MarshalIndent(tree, "", "    ")
	fmt.Println(string(out))
}

这里为了看一棵比较简单的树的结构,可以用json包序列化打印出来看:json.MarshalIndent(tree, "", " ")