㈠ java二叉树遍历问题
二叉树具有以下重要性质:
性质1 二叉树第i层上的结点数目最多为2i-1(i≥1)。
证明:用数学归纳法证明:
归纳基础:i=1时,有2i-1=20=1。因为第1层上只有一个根结点,所以命题成立。
归纳假设:假设对所有的j(1≤j<i)命题成立,即第j层上至多有2j-1个结点,证明j=i时命题亦成立。
归纳步骤:根据归纳假设,第i-1层上至多有2i-2个结点。由于二叉树的每个结点至多有两个孩子,故第i层上的结点数至多是第i-1层上的最大结点数的2倍。即j=i时,该层上至多有2×2i-2=2i-1个结点,故命题成立。
性质2 深度为k的二叉树至多有2k-1个结点(k≥1)。
证明:在具有相同深度的二叉树中,仅当每一层都含有最大结点数时,其树中结点数最多。因此利用性质1可得,深度为k的二叉树的结点数至多为:
20+21+…+2k-1=2k-1
故命题正确。
性质3 在任意-棵二叉树中,若终端结点的个数为n0,度为2的结点数为n2,则no=n2+1。
证明:因为二叉树中所有结点的度数均不大于2,所以结点总数(记为n)应等于0度结点数、1度结点(记为n1)和2度结点数之和:
n=no+n1+n2 (式子1)
另一方面,1度结点有一个孩子,2度结点有两个孩子,故二叉树中孩子结点总数是:
nl+2n2
树中只有根结点不是任何结点的孩子,故二叉树中的结点总数又可表示为:
n=n1+2n2+1 (式子2)
由式子1和式子2得到:
no=n2+1
满二叉树和完全二叉树是二叉树的两种特殊情形。
1、满二叉树(FullBinaryTree)
一棵深度为k且有2k-1个结点的二又树称为满二叉树。
满二叉树的特点:
(1) 每一层上的结点数都达到最大值。即对给定的高度,它是具有最多结点数的二叉树。
(2) 满二叉树中不存在度数为1的结点,每个分支结点均有两棵高度相同的子树,且树叶都在最下一层上。
图(a)是一个深度为4的满二叉树。
2、完全二叉树(Complete BinaryTree)
若一棵二叉树至多只有最下面的两层上结点的度数可以小于2,并且最下一层上的结点都集中在该层最左边的若干位置上,则此二叉树称为完全二叉树。
特点:
(1) 满二叉树是完全二叉树,完全二叉树不一定是满二叉树。
(2) 在满二叉树的最下一层上,从最右边开始连续删去若干结点后得到的二叉树仍然是一棵完全二叉树。
(3) 在完全二叉树中,若某个结点没有左孩子,则它一定没有右孩子,即该结点必是叶结点。
如图(c)中,结点F没有左孩子而有右孩子L,故它不是一棵完全二叉树。
图(b)是一棵完全二叉树。
性质4 具有n个结点的完全二叉树的深度为
证明:设所求完全二叉树的深度为k。由完全二叉树定义可得:
深度为k得完全二叉树的前k-1层是深度为k-1的满二叉树,一共有2k-1-1个结点。
由于完全二叉树深度为k,故第k层上还有若干个结点,因此该完全二叉树的结点个数:
n>2k-1-1。
另一方面,由性质2可得:
n≤2k-1,
即:2k-1-l<n≤2k-1
由此可推出:2k-1≤n<2k,取对数后有:
k-1≤lgn<k
又因k-1和k是相邻的两个整数,故有
,
由此即得:
注意:
的证明
㈡ 求一个java遍历比较完整树的方法
//用中序遍历一个二叉树
class BinaryTree
{
class Node
{
private int data; //保存数据内容
private Node left; //左子树
private Node right;//右子树
public Node(int data){
this.data = data;
}
public void addNode(Node newNode){ //addNode方法用来添加数据
if(newNode.data <= this.data){
if(this.left == null){ //左子树为空
this.left = newNode;
}else{
this.left.addNode(newNode);//继续向下判断
}
}
if(newNode.data > this.data){
if(this.right == null){ //右子树为空
this.right = newNode;
}else{
this.right.addNode(newNode);//继续向下判断
}
}
} //addNode方法结束
public void printNode(){ //采用中序遍历(左-根-右)
if(this.left != null){
this.left.printNode();
}
System.out.println(this.data); //找到根内容
if(this.right != null){
this.right.printNode();
}
}
} //Node类结束
private Node root; //根节点
public void add(int data){
Node newNode = new Node(data);
if(this.root == null){
this.root = newNode;
}else{
this.root.addNode(newNode);
}
}
public void print(){
this.root.printNode();
}
}
public class Demo
{
public static void main(String args[]){
BinaryTree bt = new BinaryTree();
bt.add(3);
bt.add(4);
bt.add(0);
bt.add(1);
bt.print();
}
}
㈢ 二叉树的java实现与几种遍历
二叉树的定义
二叉树(binary tree)是结点的有限集合,这个集合或者空,或者由一个根及两个互不相交的称为这个根的左子树或右子树构成.
从定义可以看出,二叉树包括:1.空树 2.只有一个根节点 3.只有左子树 4.只有右子树 5.左右子树都存在 有且仅有这5种表现形式
二叉树的遍历分为三种:前序遍历 中序遍历 后序遍历
前序遍历:按照“根左右”,先遍历根节点,再遍历左子树 ,再遍历右子树
中序遍历:按照“左根右“,先遍历左子树,再遍历根节点,最后遍历右子树
后续遍历:按照“左右根”,先遍历左子树,再遍历右子树,最后遍历根节点
其中前,后,中指的是每次遍历时候的根节点被遍历的顺序
具体实现看下图:
㈣ 急急急!!!要求用java实现二叉树中序遍历序列 具体要求如下
第一棵树只有一个 1 节点,为什么输出序列有两个 1?
第二棵树只有一个 3 节点,为什么输出序列有两个 3?
题目中的输出序列是否不正确?
㈤ 二叉树中序遍历问题
你建二叉树的时候没有把左右孩子地址返回给父节点,遍历时找不到左右孩子,当然就崩溃了。而且你的程序在不停地对一个野指针进行操作,这样是很危险的。
create函数改成:
BiTreeCreate()
{
intx;
BiTreebt;
scanf("%d",&x);
if(x==0)bt=NULL;
else
{
bt=(BiTree)malloc(sizeof(BiTNode));
bt->data=x;
bt->LChild=Create();
bt->RChild=Create();
}
returnbt;
}
main函数改成:
intmain()
{
BiTreebt;
bt=Create();
InOrder(bt);
getch();
return0;
}
就可以了。
㈥ java如何遍历二叉树
/**
* 二叉树测试二叉树顺序存储在treeLine中,递归前序创建二叉树。另外还有能
* 够前序、中序、后序、按层遍历二叉树的方法以及一个返回遍历结果asString的
* 方法。
*/
public class BitTree {
public static Node2 root;
public static String asString;
//事先存入的数组,符号#表示二叉树结束。
public static final char[] treeLine = {'a','b','c','d','e','f','g',' ',' ','j',' ',' ','i','#'};
//用于标志二叉树节点在数组中的存储位置,以便在创建二叉树时能够找到节点对应的数据。
static int index;
//构造函数
public BitTree() {
System.out.print("测试二叉树的顺序表示为:");
System.out.println(treeLine);
this.index = 0;
root = this.setup(root);
}
//创建二叉树的递归程序
private Node2 setup(Node2 current) {
if (index >= treeLine.length) return current;
if (treeLine[index] == '#') return current;
if (treeLine[index] == ' ') return current;
current = new Node2(treeLine[index]);
index = index * 2 + 1;
current.left = setup(current.left);
index ++;
current.right = setup(current.right);
index = index / 2 - 1;
return current;
}
//二叉树是否为空。
public boolean isEmpty() {
if (root == null) return true;
return false;
}
//返回遍历二叉树所得到的字符串。
public String toString(int type) {
if (type == 0) {
asString = "前序遍历:\t";
this.front(root);
}
if (type == 1) {
asString = "中序遍历:\t";
this.middle(root);
}
if (type == 2) {
asString = "后序遍历:\t";
this.rear(root);
}
if (type == 3) {
asString = "按层遍历:\t";
this.level(root);
}
return asString;
}
//前序遍历二叉树的循环算法,每到一个结点先输出,再压栈,然后访问它的左子树,
//出栈,访问其右子树,然后该次循环结束。
private void front(Node2 current) {
StackL stack = new StackL((Object)current);
do {
if (current == null) {
current = (Node2)stack.pop();
current = current.right;
} else {
asString += current.ch;
current = current.left;
}
if (!(current == null)) stack.push((Object)current);
} while (!(stack.isEmpty()));
}
//中序遍历二叉树
private void middle(Node2 current) {
if (current == null) return;
middle(current.left);
asString += current.ch;
middle(current.right);
}
//后序遍历二叉树的递归算法
private void rear(Node2 current) {
if (current == null) return;
rear(current.left);
rear(current.right);
asString += current.ch;
}
}
/**
* 二叉树所使用的节点类。包括一个值域两个链域
*/
public class Node2 {
char ch;
Node2 left;
Node2 right;
//构造函数
public Node2(char c) {
this.ch = c;
this.left = null;
this.right = null;
}
//设置节点的值
public void setChar(char c) {
this.ch = c;
}
//返回节点的值
public char getChar() {
return ch;
}
//设置节点的左孩子
public void setLeft(Node2 left) {
this.left = left;
}
//设置节点的右孩子
public void setRight (Node2 right) {
this.right = right;
}
//如果是叶节点返回true
public boolean isLeaf() {
if ((this.left == null) && (this.right == null)) return true;
return false;
}
}
一个作业题,里面有你要的东西。
主函数自己写吧。当然其它地方也有要改的。
㈦ java二叉树中序遍历 的递归算法没有看懂。。search(data.getLeft());之后不就回到最左边的一个
最左边的节点是没有左子树和右子树的。
if(data.getLeft()!=null){ // 这里getLetf()为null
search(data.getLeft());
}
System.out.print(data.getObj()+","); //只有这句是执行的!
if(data.getRight()!=null){ // 这里getRight()为null
search(data.getRight());
}
然后就会退到上一个节点的遍历函数了。
㈧ 在java中,遍历是干嘛用的有什么意义
你说的比较笼统,遍历的话,可以遍历数组,遍历list,遍历链表,遍历图,树等等,遍历的意义就在于检查集合中的元素并做处理。至于什么顺序,那要根据需求喽。
例子,比较简单的是,遍历一个整型数组,找出里面最大的数。
㈨ java二叉树的顺序表实现
做了很多年的程序员,觉得什么树的设计并不是非常实用。二叉树有顺序存储,当一个insert大量同时顺序自增插入的时候,树就会失去平衡。树的一方为了不让塌陷,会增大树的高度。性能会非常不好。以上是题外话。分析需求在写代码。
import java.util.List;
import java.util.LinkedList;
public class Bintrees {
private int[] array = {1, 2, 3, 4, 5, 6, 7, 8, 9};
private static List<Node> nodeList = null;
private static class Node {
Node leftChild;
Node rightChild;
int data;
Node(int newData) {
leftChild = null;
rightChild = null;
data = newData;
}
}
// 创建二叉树
public void createBintree() {
nodeList = new LinkedList<Node>();
// 将数组的值转换为node
for (int nodeIndex = 0; nodeIndex < array.length; nodeIndex++) {
nodeList.add(new Node(array[nodeIndex]));
}
// 对除最后一个父节点按照父节点和孩子节点的数字关系建立二叉树
for (int parentIndex = 0; parentIndex < array.length / 2 - 1; parentIndex++) {
nodeList.get(parentIndex).leftChild = nodeList.get(parentIndex * 2 + 1);
nodeList.get(parentIndex).rightChild = nodeList.get(parentIndex * 2 + 2);
}
// 最后一个父节点
int lastParentIndex = array.length / 2 - 1;
// 左孩子
nodeList.get(lastParentIndex).leftChild = nodeList.get(lastParentIndex * 2 + 1);
// 如果为奇数,建立右孩子
if (array.length % 2 == 1) {
nodeList.get(lastParentIndex).rightChild = nodeList.get(lastParentIndex * 2 + 2);
}
}
// 前序遍历
public static void preOrderTraverse(Node node) {
if (node == null) {
return;
}
System.out.print(node.data + " ");
preOrderTraverse(node.leftChild);
preOrderTraverse(node.rightChild);
}
// 中序遍历
public static void inOrderTraverse(Node node) {
if (node == null) {
return;
}
inOrderTraverse(node.leftChild);
System.out.print(node.data + " ");
inOrderTraverse(node.rightChild);
}
// 后序遍历
public static void postOrderTraverse(Node node) {
if (node == null) {
return;
}
postOrderTraverse(node.leftChild);
postOrderTraverse(node.rightChild);
System.out.print(node.data + " ");
}
public static void main(String[] args) {
Bintrees binTree = new Bintrees();
binTree.createBintree();
Node root = nodeList.get(0);
System.out.println("前序遍历:");
preOrderTraverse(root);
System.out.println();
System.out.println("中序遍历:");
inOrderTraverse(root);
System.out.println();
System.out.println("后序遍历:");
postOrderTraverse(root);
}
}
㈩ 什么是树的遍历java
树遍历方法:有先序遍历、中序遍历、后序遍历以及广度优先遍历四种遍历树的方法
Demo:
publicclassThreeLinkBinTree<E>{
publicstaticclassTreeNode{
Objectdata;
TreeNodeleft;
TreeNoderight;
TreeNodeparent;
publicTreeNode(){
}
publicTreeNode(Objectdata){
this.data=data;
}
publicTreeNode(Objectdata,TreeNodeleft,TreeNoderight,TreeNodeparent){
this.data=data;
this.left=left;
this.right=right;
this.parent=parent;
}
}
privateTreeNoderoot;
//以默认的构造器创建二叉树
publicThreeLinkBinTree(){
this.root=newTreeNode();
}
//以指定根元素创建二叉树
publicThreeLinkBinTree(Edata){
this.root=newTreeNode(data);
}
/**
*为指定节点添加子节点
*
*@paramparent需要添加子节点的父节点的索引
*@paramdata新子节点的数据
*@paramisLeft是否为左节点
*@return新增的节点
*/
publicTreeNodeaddNode(TreeNodeparent,Edata,booleanisLeft){
if(parent==null){
thrownewRuntimeException(parent+"节点为null,无法添加子节点");
}
if(isLeft&&parent.left!=null){
thrownewRuntimeException(parent+"节点已有左子节点,无法添加左子节点");
}
if(!isLeft&&parent.right!=null){
thrownewRuntimeException(parent+"节点已有右子节点,无法添加右子节点");
}
TreeNodenewNode=newTreeNode(data);
if(isLeft){
//让父节点的left引用指向新节点
parent.left=newNode;
}else{
//让父节点的left引用指向新节点
parent.right=newNode;
}
//让新节点的parent引用到parent节点
newNode.parent=parent;
returnnewNode;
}
//判断二叉树是否为空
publicbooleanempty(){
//根据元素判断二叉树是否为空
returnroot.data==null;
}
//返回根节点
publicTreeNoderoot(){
if(empty()){
thrownewRuntimeException("树为空,无法访问根节点");
}
returnroot;
}
//返回指定节点(非根节点)的父节点
publicEparent(TreeNodenode){
if(node==null){
thrownewRuntimeException("节点为null,无法访问其父节点");
}
return(E)node.parent.data;
}
//返回指定节点(非叶子)的左子节点,当左子节点不存在时返回null
publicEleftChild(TreeNodeparent){
if(parent==null){
thrownewRuntimeException(parent+"节点为null,无法添加子节点");
}
returnparent.left==null?null:(E)parent.left.data;
}
//返回指定节点(非叶子)的右子节点,当右子节点不存在时返回null
publicErightChild(TreeNodeparent){
if(parent==null){
thrownewRuntimeException(parent+"节点为null,无法添加子节点");
}
returnparent.right==null?null:(E)parent.right.data;
}
//返回该二叉树的深度
publicintdeep(){
//获取该树的深度
returndeep(root);
}
//这是一个递归方法:每一棵子树的深度为其所有子树的最大深度+1
privateintdeep(TreeNodenode){
if(node==null){
return0;
}
//没有子树
if(node.left==null&&node.right==null){
return1;
}else{
intleftDeep=deep(node.left);
intrightDeep=deep(node.right);
//记录其所有左、右子树中较大的深度
intmax=leftDeep>rightDeep?leftDeep:rightDeep;
//返回其左右子树中较大的深度+1
returnmax+1;
}
}
//实现先序遍历
//1、访问根节点
//2、递归遍历左子树
//3、递归遍历右子树
publicList<TreeNode>preIterator(){
returnpreIterator(root);
}
privateList<TreeNode>preIterator(TreeNodenode){
List<TreeNode>list=newArrayList<TreeNode>();
//处理根节点
list.add(node);
//递归处理左子树
if(node.left!=null){
list.addAll(preIterator(node.left));
}
//递归处理右子树
if(node.right!=null){
list.addAll(preIterator(node.right));
}
returnlist;
}
//实现中序遍历
//1、递归遍历左子树
//2、访问根节点
//3、递归遍历右子树
publicList<TreeNode>inIterator(){
returninIterator(root);
}
privateList<TreeNode>inIterator(TreeNodenode){
List<TreeNode>list=newArrayList<TreeNode>();
//递归处理左子树
if(node.left!=null){
list.addAll(inIterator(node.left));
}
//处理根节点
list.add(node);
//递归处理右子树
if(node.right!=null){
list.addAll(inIterator(node.right));
}
returnlist;
}
//实现后序遍历
//1、递归遍历左子树
//2、递归遍历右子树
//3、访问根节点
publicList<TreeNode>postIterator(){
returnpostIterator(root);
}
privateList<TreeNode>postIterator(TreeNodenode){
List<TreeNode>list=newArrayList<TreeNode>();
//递归处理左子树
if(node.left!=null){
list.addAll(postIterator(node.left));
}
//递归处理右子树
if(node.right!=null){
list.addAll(postIterator(node.right));
}
//处理根节点
list.add(node);
returnlist;
}
//实现广度优先遍历
//广度优先遍历又称为按层遍历,整个遍历算法先遍历二叉树的第一层(根节点),再遍历根节点的两个子节点(第二层),以此类推
publicList<TreeNode>breadthFirst(){
Queue<TreeNode>queue=newArrayDeque<TreeNode>();
List<TreeNode>list=newArrayList<TreeNode>();
if(root!=null){
//将根元素加入“队列”
queue.offer(root);
}
while(!queue.isEmpty()){
//将该队列的“队尾”的元素添加到List中
list.add(queue.peek());
TreeNodep=queue.poll();
//如果左子节点不为null,将它加入“队列”
if(p.left!=null){
queue.offer(p.left);
}
//如果右子节点不为null,将它加入“队列”
if(p.right!=null){
queue.offer(p.right);
}
}
returnlist;
}
}