为什么需要树这种数据结构
1)数组存储(顺序存续):
优点:通过下标访问元素,速度快。对于有序的数组,使用二分查找还能提高检索速度
缺点:插入值时会整体移动,效率低
补充:arrayList的底层操作机制源码分析
1)arrayList中维护了一个object类型的数组elementData
2)当创建对象时,如果使用的是无参构造器,则初始elementData的容量为0(jdk7为10)
3)当使用的是指定容量Capacity的构造器,则初始elementData容量为capacity
4)当添加元素时:先判读是否需要扩容,如果需要扩容,则调用grow方法,否则直接添加元素到合适的位置
5)如果使用的是无参构造器,如果第一次添加,需要扩容的话,则扩容elementData为10,如果需要再次扩容的话 则elementData为1.5陪。
6)如果使用的是指定容量capacity的构造器,如果需要扩容,则直接扩容elementData的1.5倍
2)链式存储:
优点:在一定程度上对数组存储方式有优化(比如:插入一个数值节点,只需要将插入的节点,链接到链表中即可,删除效率也很好)
缺点:在进行检索时,效率仍然较低
3)树存储:
提高了数据存储、读取的效率,比如利用二叉树,既可以保证数据的检索速度 同时也保证了数据的插入删除修改的速度
分析二叉树的前序、中序、后续的遍历思路
定义
前序遍历:先输出父节点、再遍历左子树和右子树
中序遍历:先遍历左子树、再输出父节点、再遍历右子树
后续遍历:先遍历左子树、再遍历右子树、最后输出父节点
思路:
1.创建一个二叉树
2.前序遍历
2.1 先输出当前节点(初始的时候的root节点)
2.2如果左子节点不为空,则递归继续前序遍历
2.3如果右子节点不为空,则递归继续前序遍历
3.中序遍历
3.1如果当前节点的左节点不为空,则递归中序遍历
3.2输出当前节点
3.3如果当前节点的右子节点不为空,则递归中序遍历
4.后续遍历
4.1如果当前节点的左子节点不为空,则递归后续遍历
4.2如果当前节点的右子节点不为空,则递归后续遍历
4.3输出当前节点
接下来看一下二叉树的前中后序遍历
首先写一个英雄节点类
class HeroNode{
private Integer id;
private String name;
private HeroNode left;
private HeroNode right;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public HeroNode getLeft() {
return left;
}
public void setLeft(HeroNode left) {
this.left = left;
}
public HeroNode getRight() {
return right;
}
public void setRight(HeroNode right) {
this.right = right;
}
public HeroNode(Integer id, String name) {
this.id = id;
this.name = name;
}
@Override
public String toString() {
return "HeroNode{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
/*遍历前序遍历的方法*/
public void preOrder(){
System.out.println(this);//先输出父节点
if (this.left!=null){//假如左子树不为空则递归前序遍历方法
this.left.preOrder();
}
if(this.right!=null){//然后判断右子树是否为空 ,不为空则递归前序遍历
this.right.preOrder();
}
}
/*遍历中序遍历的方法*/
public void midOrder(){
//递归向左子树遍历
if (this.left!=null){
this.left.midOrder();
}
System.out.println(this);//输出父节点
if (this.right!=null){
this.right.midOrder();
}
}
/*后续遍历的方法*/
public void sufOrder(){
if (this.left!=null){
this.left.sufOrder();
}
if (this.right!=null){
this.right.sufOrder();
}
System.out.println(this);//输出父节点
}
}
然后创建一个二叉树类
/*定义一个二叉树*/
class BinaryTr{
private HeroNode root;/*定义一个根节点*/
public void setRoot(HeroNode root) {
this.root = root;
}
//前序遍历
public void preOrder(){
if (this.root!=null){
this.root.preOrder();
}
else {
System.out.println("binary is null");
}
}
/*中序遍历*/
public void midOrder(){
if (this.root!=null){
this.root.midOrder();
}
else
{
System.out.println("null");
}
}
/*后续遍历*/
public void sufOrder(){
if (this.root!=null){
this.root.sufOrder();
}else{
System.out.println("null");
}
}
}
最后测试
public class BinaryTree {
public static void main(String[] args) {
/*创建一个二叉树*/
BinaryTr binaryTr=new BinaryTr();
/*创建需要的节点*/
HeroNode root=new HeroNode(1,"sj");
HeroNode node2=new HeroNode(2,"wy");
HeroNode node3=new HeroNode(3,"ly");
HeroNode node4=new HeroNode(4,"lin");
/*手动创建二叉树*/
root.setLeft(node2);
root.setRight(node3);
node3.setRight(node4);
binaryTr.setRoot(root);
/*测试*/
System.out.println("前序遍历");
binaryTr.preOrder();
System.out.println("中序遍历");
binaryTr.midOrder();
System.out.println("后续遍历");
binaryTr.sufOrder();
}
这是结果图