数据结构-树及相关算法

本文详细探讨了二叉树的各种操作,包括镜像翻转、填充节点指针、二叉树展开为链表、最大二叉树等。通过递归框架解析了前序、中序、后序遍历,以及二叉搜索树的特性。同时,介绍了赫夫曼树的概念和编码,并提到了N叉树和扁平化嵌套列表迭代器的操作。
摘要由CSDN通过智能技术生成

二叉树

递归算法的关键要明确函数的定义,相信这个定义,而不要跳进递归细节。

写二叉树的算法题,都是基于递归框架的,我们先要搞清楚 root 节点它自己要做什么,然后根据题目要求选择使用前序,中序,后续的递归框架。

二叉树题目的难点在于如何通过题目的要求思考出每一个节点需要做什么,这个只能通过多刷题进行练习了。

二叉树遍历框架:

/* 二叉树遍历框架 */
void traverse(TreeNode root) {
   
    // 前序遍历
    traverse(root.left)
    // 中序遍历
    traverse(root.right)
    // 后序遍历
}

1,2,3,4,5,6,7

前序遍历:先输出父节点,再遍历左子树和右子树。1, 2, 4, 5, 3, 6, 7

中序遍历:先遍历左子树,在输出父节点,再遍历右子树。4, 2, 5, 1, 6, 3, 7

后序遍历:先遍历左子树,再遍历右子树,最后输出父节点。4, 5, 2, 6, 7, 3, 1

镜像翻转二叉树

剑指 Offer 27. 二叉树的镜像

这个函数的定义就是给我一个节点,我把他的左右子节点翻转
只去想一个节点翻转需要怎么做,这是一个二叉树的前序遍历

public TreeNode invertTree(TreeNode root) {
   
        if (root == null) {
   
		return root;
	}
	//翻转
	TreeNode tempNode = root.left;
	root.left = root.right;
	root.right = tempNode;
	//子节点也去翻转
	invertTree(root.left);
	invertTree(root.right);
	return root;
}

116. 填充每个节点的下一个右侧节点指针

我辅助函数定义就是将你传给我的两个节点,进行连接。
采用前序遍历,然后需要把这两个节点各自的左右节点连接&&这一个节点的左和一个节点的有连接。

// 主函数
Node connect(Node root) {
   
    if (root == null) return null;
    connectTwoNode(root.left, root.right);
    return root;
}

// 辅助函数
void connectTwoNode(Node node1, Node node2) {
   
    if (node1 == null || node2 == null) {
   
        return;
    }
    /**** 前序遍历位置 ****/
    // 将传入的两个节点连接
    node1.next = node2;

    // 连接相同父节点的两个子节点
    connectTwoNode(node1.left, node1.right);
    connectTwoNode(node2.left, node2.right);
    // 连接跨越父节点的两个子节点
    connectTwoNode(node1.right, node2.left);
}

114. 二叉树展开为链表

这个函数的定义是:以传给我的头节点的二叉树拉平成一个链表。

进行后序遍历

具体:把他的左右先进行拉平,然后把左树当做右树,左边为null,最后把原来的右树放到现在右树的下面。

// 定义:将以 root 为根的树拉平为链表
void flatten(TreeNode root) {
   
    // base case
    if (root == null) return;

    flatten(root.left);
    flatten(root.right);

    /**** 后序遍历位置 ****/
    // 1、左右子树已经被拉平成一条链表
    TreeNode left = root.left;
    TreeNode right = root.right;

    // 2、将左子树作为右子树
    root.left = null;
    root.right = left;

    // 3、将原先的右子树接到当前右子树的末端
    TreeNode p = root;
    while (p.right != null) {
   
        p = p.right;
    }
    p.right = right;
}

654. 最大二叉树

test函数的定义:返回给定的数组中的最大值new出的节点。

采用前序遍历,

public TreeNode constructMaximumBinaryTree(int[] nums) {
   
		return test(nums, 0, nums.length - 1);
    }

	public TreeNode test(int[] nums, int start, int end){
   
		if (start > end) {
   
			return null;
		}
		int index = start;
		int max = nums[start];
		for (int i = start + 1; i <= end; i++) {
   
			if (max < nums[i]) {
   
				max = nums[i];
				index = i;
			}
		}
		TreeNode node = new TreeNode(max);

		node.left = test(nums, start, index - 1);
		node.right = test(nums, index +1, end);
		return node;
	}

105. 从前序与中序遍历序列构造二叉树

辅助函数的定义:通过给定的前序,中序数组找到根节点。

流程:根据前序遍历可以知道,根节点就是前序遍历的首位,根节点的下一位就是前序遍历数组的下一位,在通过中序遍历数组就可以确定是左右哪个节点。然后分开去求左右子树。

class Solution {
   
    public TreeNode buildTree(int[] preorder, int[] inorder) {
   
		return test(preorder, 0, preorder.length -1 , inorder, 0 , inorder.length-1);
    }

	public TreeNode test(int[] preorder,int prestart, int preend, int[] inorder, int instart, int inend) {
   
		if (prestart > preend) {
   
			return null;
		}
		int index = 0;
		for (int i = instart; i <= inend; i++) {
   
			if (preorder[prestart] == inorder[i]) {
   
				index = i;
				break
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值