#二叉树 #数据结构 #Java
开源学习资料
在数据结构中,二叉树是非常重要的一个章节。
这里总结一下二叉树的基础概论:
二叉树是一种树状数据结构,每个节点最多有两个子节点,分别为左子节点和右子节点。它具有以下特性:
1. 根节点:树的顶部节点,没有父节点。
2. 子节点:每个节点最多有两个子节点。
3. 叶节点:没有子节点的节点称为叶节点。
4. 深度:根节点到任意节点的唯一路径长度称为深度。
5. 高度:从叶节点到根节点的路径长度称为高度。
6. 层次:树中具有相同深度的节点形成一个层次。
7. 二叉搜索树(BST):左子树的所有节点小于根节点,右子树的所有节点大于根节点。
8. 遍历:二叉树可以通过前序、中序和后序遍历来访问节点。
这种结构经常遇到,不仅是在算法中,在数据库,图像领域中也常见。
这里引入代码随想录中的概括图片:
我们在刷算法题,最主要的是清楚二插树在内存中是如何存储的,掌握二叉树的遍历。
一般我们用到递归,再写递归的时候,都要找到递归的出口,确定函数的返回值。
按照代码随想录总结出来的三要素:
确定递归函数的参数和返回值: 确定哪些参数是递归的过程中需要处理的,那么就在递归函数里加上这个参数, 并且还要明确每次递归的返回值是什么进而确定递归函数的返回类型。
确定终止条件: 写完了递归算法, 运行的时候,经常会遇到栈溢出的错误,就是没写终止条件或者终止条件写的不对,操作系统也是用一个栈的结构来保存每一层递归的信息,如果递归没有终止,操作系统的内存栈必然就会溢出。
确定单层递归的逻辑: 确定每一层递归需要处理的信息。在这里也就会重复调用自己来实现递归的过程。
以下是利用递归——>二叉树的前序遍历:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public List preorderTraversal(TreeNode root) {
List result = new ArrayList();
preorder(root, result);
return result;
}
public void preorder(TreeNode root, List result) {
//递归的出口
if (root == null) {
return;
}
result.add(root.val);
preorder(root.left, result);
preorder(root.right, result);
}
}
二叉树的中序遍历:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public List inorderTraversal(TreeNode root) {
List res = new ArrayList<>();
inorder(root, res);
return res;
}
void inorder(TreeNode root, List list) {
if (root == null) {
return;
}
inorder(root.left, list);
list.add(root.val);
inorder(root.right, list);
}
}
二叉树的后序遍历:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public List postorderTraversal(TreeNode root) {
List res = new ArrayList<>();
postorder(root, res);
return res;
}
void postorder(TreeNode root, List list) {
if (root == null) {
return;
}
postorder(root.left, list);
postorder(root.right, list);
list.add(root.val);
}
}
非递归的方法遍历,本质上就是模拟栈的特性。
非递归前序遍历:
class Solution {
public List preorderTraversal(TreeNode root) {
List result = new ArrayList<>();
if (root == null){
return result;
}
Stack stack = new Stack<>();
stack.push(root);
while (!stack.isEmpty()){
TreeNode node = stack.pop();
result.add(node.val);
if (node.right != null){
stack.push(node.right);
}
if (node.left != null){
stack.push(node.left);
}
}
return result;
}
}
非递归中序遍历:
class Solution {
public List inorderTraversal(TreeNode root) {
List result = new ArrayList<>();
if (root == null){
return result;
}
Stack stack = new Stack<>();
TreeNode cur = root;
while (cur != null || !stack.isEmpty()){
if (cur != null){
stack.push(cur);
cur = cur.left;
}else{
cur = stack.pop();
result.add(cur.val);
cur = cur.right;
}
}
return result;
}
}
非递归后序遍历:
class Solution {
public List postorderTraversal(TreeNode root) {
List result = new ArrayList<>();
if (root == null){
return result;
}
Stack stack = new Stack<>();
stack.push(root);
while (!stack.isEmpty()){
TreeNode node = stack.pop();
result.add(node.val);
if (node.left != null){
stack.push(node.left);
}
if (node.right != null){
stack.push(node.right);
}
}
Collections.reverse(result);
return result;
}
}
今天对二叉树的练习主要是加深对其遍历的理解,最主要的还是对后面深度,广度优先搜索,回溯等内容做好准备。
何须浅碧深红色
自是花中第一流!
Fighting!