数据结构——————————————树以及它的遍历方式

最近学习树,就写写自己了解的树的特点,我这篇写的是二叉树


树的定义:二叉树是每个结点最多有两个子树的树结构。通常子树被称作“左子树”(left subtree)和“右子树”(right subtree)。(百度百科的二叉树树的定义)

          左右孩子都在(a)

这就是最简单的树,它每个结点和双向链表 的结点相似,只不过链表的前后指针和它上下结点相互指向。而树的结点它只有从父节点指向子结点,但是子节点不能指向父结点。每一个父结点就像两个链表的开端。每一个结点并不是都有孩子。

                                                     

         只有左孩子的结点 (b)                                                    只有右孩子的结点(c)

这里所说的没有左右孩子是它的左右孩子没有储存数据,相当于是null

如果一颗树只有bc其中一种构成它就相当于一个链表了

java语言写的树的结点:

package Tree;


public class TreeNode<T> {
	T t;//数据
	TreeNode<T> left;//左孩子
	TreeNode<T> right;//右孩子
    public TreeNode(T t){
		this.t=t;
	}
}

一颗树便是由abc三种情况所构成

这便是一颗树

树根:树根为一颗树的最高的父结点,它没有父结点,如上图中是的a

叶子结点:没有孩子结点的结点为叶子结点,如上图中h、i、k、l、m。

树的深度:为最深结点到树根的层数;上图树深度为:4

一颗树的最多结点数:2^m-1,m为这个树的深度

一个树的最大叶子树:2^(m-1),m为树的深度

关于二叉树的遍历,二叉树树的遍历有四种分别是

a.先序遍历

b.中序遍历

c.后序遍历

d.按层遍历

先序遍历:

从树根开始遍历,先输出根结点,在输出它的左孩子,其次是右孩子。

上边树前序遍历为:abdhiekcflgm

使用java语言先序遍历:

public void preorder(TreeNode<T> n) {
	System.out.println(n.t);
	if(n.left!=null) {
	preorder(n.left);
	}
	if(n.right!=null) {
	preorder(n.right);
	}
}

中序遍历:

从有左孩子开始,先输左孩子,在输出它的父结点,其次是右孩子

上边树中序遍历为:hdibkeaflcgm

使用java语言中序遍历:

public void inorder(TreeNode<T> n) {
	if(n.left!=null) {
	inorder(n.left);
	}
	System.out.println(n.t);
	if(n.right!=null) {
	inorder(n.right);
	}
}

后序遍历:

从左孩子开始遍历,先输出左孩子,在输出它的右孩子,其次是父节点

上边树前序遍历为:hidkeblfmgca

java实现后序遍历:

public void postorder(TreeNode<T> n) {
	if(n.left!=null) {
	postorder(n.left);
	}
	if(n.right!=null) {
	postorder(n.right);
	}
	System.out.println(n.t);
}

 

前序、中序和后序三种遍历方式,记忆起来可能混淆,所以有一个比较简单的记法

右肯定在左的右边,然后是哪种遍历就把中加在哪里

比如前序:中左右    中序:左中右       后序:左右中

按层遍历:

可以使用递归的方式,每递归一次输出当前层的所有数据

上面树的遍历为:abcdefghiklm

这里就需要两个队列分别是l1和l2

1.首先将根结点存入l1中

2.把l1中数据输出,把l1中所有数据移入l2中。

3.l2为当前层的检点,将l2中每个结点的左右孩子移入l1中,且把所有的数据移除

4.重复2-3直到,经过3步骤l2中没有数据说明已经遍历完成

java代码实现

ArrayList<TreeNode<T>> l1;//队列1
ArrayList<TreeNode<T>> l2;//队列2

public void layer(TreeNode<T> n) {
	//当第一调用时,我们把传入的n存入l1
	if(l1.size()<1) {
		l1.add(n);
	}
	//将l1中遍历当前层输出其中的数据
	//将该层的数据取出存入l2中
	while(l1.size()>0) {
		System.out.print(l1.get(0).t+"--");
		l2.add(l1.remove(0));
	}
	System.out.println();
	//将l2中每个数据的孩子结点存入l1中
	while(l2.size()>0) {
		if(l2.get(0).left!=null) {
			l1.add(l2.get(0).left);
		}
		if(l2.get(0).right!=null) {
			l1.add(l2.get(0).right);
		}
		l2.remove(0);
	}
	//当l1中无数据时,说明这颗树已经遍历完成
	if(l1.size()<1) {
		return ;
	}
	layer(n);
}

四种遍历方式的整合代码:

package Tree;

import java.util.ArrayList;

public class Tree<T>{
	ArrayList<TreeNode<T>> l1;//队列1
	ArrayList<TreeNode<T>> l2;//队列2
	
	public Tree() {
		l1=new ArrayList<>();
		l2=new ArrayList<>();
	}
//先序遍历
public void preorder(TreeNode<T> n) {
	System.out.println(n.t);
	if(n.left!=null) {
	preorder(n.left);
	}
	if(n.right!=null) {
	preorder(n.right);
	}
}
//中序遍历
public void inorder(TreeNode<T> n) {
	if(n.left!=null) {
	inorder(n.left);
	}
	System.out.println(n.t);
	if(n.right!=null) {
	inorder(n.right);
	}
}
//后序遍历
public void postorder(TreeNode<T> n) {
	if(n.left!=null) {
	postorder(n.left);
	}
	if(n.right!=null) {
	postorder(n.right);
	}
	System.out.println(n.t);
}
//按层遍历
public void layer(TreeNode<T> n) {
	//当第一调用时,我们把传入的n存入l1
	if(l1.size()<1) {
		l1.add(n);
	}
	//将l1中遍历当前层输出其中的数据
	//将该层的数据取出存入l2中
	while(l1.size()>0) {
		System.out.print(l1.get(0).t+"--");
		l2.add(l1.remove(0));
	}
	System.out.println();
	//将l2中每个数据的孩子结点存入l1中
	while(l2.size()>0) {
		if(l2.get(0).left!=null) {
			l1.add(l2.get(0).left);
		}
		if(l2.get(0).right!=null) {
			l1.add(l2.get(0).right);
		}
		l2.remove(0);
	}
	//当l1中无数据时,说明这颗树已经遍历完成
	if(l1.size()<1) {
		return ;
	}
	layer(n);
}
}

如果有不对的地方大家相互请教

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值