今晚的主题
- 二叉树的构建,遍历
- ArrayList和LinkedList的区别
- 使用LinkedList构建栈
首先我们来看一下怎么遍历这个二叉树,常规的有三种方式:
先序遍历:根左右
中序遍历:左根右
后序遍历:左右根
那么java代码应该怎么实现呢?我在网上找了一个比较常规的写法
首先我们需要一个Node类,用来存储每个节点的值
package com.test.letcode;
/**
* 二叉树的节点
*/
public class Node {
Node leftNode;
Node rightNode;
int data;
public Node(int insertData) {
leftNode = null;
rightNode = null;
data = insertData;
}
}
有了节点Node以后,我们就可以构建二叉树了,所以我们需要一个CreateTree类
package com.test.letcode;
import java.util.LinkedList;
import java.util.List;
/**
* 创建树
*/
public class CreateTree {
private List<Node> nodeList = new LinkedList<>();
private int[] datas = {1, 2, 3, 4, 5, 6, 7, 8, 9};
public List<Node> createTree() {
// 将数组中的值转换为一个个的Node存入nodeList
for (int data : datas) {
nodeList.add(new Node(data));
}
// 遍历nodeList,二叉树一共会有(总节点数/2)个父节点,这个地方由于最后一个节点
// 需要特殊处理,所以减了一个1
// 然后按照节点数的索引将值赋值给每个节点
for (int index = 0; index < datas.length / 2 - 1; index++) {
nodeList.get(index).leftNode = nodeList.get(index * 2 + 1);
nodeList.get(index).rightNode = nodeList.get(index * 2 + 2);
}
int lastIndex = datas.length / 2 - 1;
// 左孩子
nodeList.get(lastIndex).leftNode = nodeList.get(lastIndex * 2 + 1);
// 有可能最后一个节点没有右孩子,所以需要判断一下
if (datas.length % 2 == 1) {
nodeList.get(lastIndex).rightNode = nodeList.get(lastIndex * 2 + 2);
}
return nodeList;
}
}
构建以后,我们就开始遍历,所以我们需要一个IteratorTree类
package com.test.letcode;
import java.util.List;
/**
* 遍历树
*/
public class IteratorTree {
// 先序遍历 根左右
public void preorderTraversal(Node node) {
if (node == null) {
return;
}
System.out.print(node.data + " ");
preorderTraversal(node.leftNode);
preorderTraversal(node.rightNode);
}
// 中序遍历 左根右
public void inOrderTraversal(Node node) {
if (node == null) {
return;
}
inOrderTraversal(node.leftNode);
System.out.print(node.data + " ");
inOrderTraversal(node.rightNode);
}
// 后序遍历 左右根
public void postOrderTraversal(Node node) {
if (node == null) {
return;
}
postOrderTraversal(node.leftNode);
postOrderTraversal(node.rightNode);
System.out.print(node.data + " ");
}
public static void main(String[] args) {
CreateTree createTree = new CreateTree();
List<Node> nodeList = createTree.createTree();
IteratorTree iteratorTree = new IteratorTree();
System.out.println("先序遍历");
iteratorTree.preorderTraversal(nodeList.get(0));
System.out.println();
System.out.println("中序遍历");
iteratorTree.inOrderTraversal(nodeList.get(0));
System.out.println();
System.out.println("后序遍历");
iteratorTree.postOrderTraversal(nodeList.get(0));
}
}
最终的输出结果:
和我们期望的结果是一致的
下来是我们的第二个问题,ArrayList和LinkedList的区别
-
ArrayList的实现是基于数组来实现的,LinkedList的基于双向链表来实现。这两个数据结构的逻辑关系是不一样,当然物理存储的方式也会是不一样。
-
对于随机访问,ArrayList优于LinkedList。
-
对于插入和删除操作,LinkedList优于ArrayList
-
LinkedList比ArrayList更占内存,因为LinkedList的节点除了存储数据,还存储了两个引用,一个指向前一个元素,一个指向后一个元素。
上面是我在网上搜到的结果,我自己也很认同,感觉这个东西只要记住了,面试问到了能够答出来就行
最后一个问题,使用LinkedList构建栈
首先我们来构建一个栈,栈的结构我们都知道,先进后出,后入先出;所以我们来构建一个Stack类
package com.test.letcode;
import java.util.LinkedList;
/**
* 栈结构
*/
public class Stack {
LinkedList<Integer> data = new LinkedList<>();
// 入栈
public void push(int val) {
data.push(val);
}
// 出栈
public void pop() {
data.pop();
}
public void print() {
data.forEach(System.out::println);
}
}
然后我们来尝试入栈和出栈,但是其实说白了,LinkedList就像是一个栈结构一样,提供给了我们push和pop的方法
package com.test.letcode;
public class TestStack {
public static void main(String[] args) {
Stack stack = new Stack();
stack.push(1);
stack.push(2);
stack.push(3);
System.out.println("入栈以后的结果");
stack.print();
for (int index = 0; index < 3; index++) {
System.out.println("出栈的结果");
stack.print();
stack.pop();
}
}
}
输出的结果如下:
符合栈的规则