数据结构二叉树

一下是java语言编写的关于数据结构中二叉树的一些常见操作:

 

首先需要定义二叉树的节点类Node,代码如下:

 

/**

 * 二叉树的节点类

 * @author xxqi1229

 *

 */

public class Node {

private Node leftChild;//左孩子

private Node rightChild;//有孩子

private int data;//该节点的值,此处用int类型的值为例

boolean canVisit = false ;//此变量的值在后序非递归遍历的时候需要用到,表示节点是否可以直接访问

 

public Node(){}

 

public Node(int data){

leftChild = rightChild = null ;

this.data = data ;

}

 

 

public Node getLeftChild() {

return leftChild;

}

 

 

public void setLeftChild(Node leftChild) {

this.leftChild = leftChild;

}

 

 

public Node getRightChild() {

return rightChild;

}

 

 

public void setRightChild(Node rightChild) {

this.rightChild = rightChild;

}

 

 

public int getData() {

return data;

}

 

 

public void setData(int data) {

this.data = data;

}

 

public String toString(){

return "" + this.data ;

}

 

 

public boolean isCanVisit() {

return canVisit;

}

 

 

public void setCanVisit(boolean canVisit) {

this.canVisit = canVisit;

}

}

 

有了这个节点类之后,就是二叉树的一些具体操作了,这些操作都封装在Tree类中,Tree的代码如下:

 

package edu.qc.tree;

 

 

import java.util.Stack;

 

 

/**

 * 二叉树

 * @author Administrator

 *

 */

public class Tree {

private Node root ;//根结点

private int count  ;//节点个数

private boolean find = false ;//在查找特定节点的时候需要使用该成员变量

 

public Tree(){//无参构造函数

this.root = null ;

this.count = 0 ;

}

 

public Tree(int[] data){

count = 0 ;

root = this.createTree(root, data, 1) ;

}

 

/**

* 二叉树的创建

* @param node :创建的节点

* @param data : 节点的值

* @param index : 数组的下标

* @return

*/

public Node createTree(Node node , int[] data , int index){

if(index > data.length){//数组下标越界

return null ;

}

if(null == node){//如果节点不存在则创建新节点,并设置节点的值。

node = new Node(data[index-1]) ;

}else{

node.setData(data[index-1]) ;

}

count++ ;//记录节点的数目

//递归的创建该节点的左孩子

Node leftNode = createTree(node.getLeftChild() , data , 2*index) ;

//递归的创建该节点的右孩子

Node rightNode = createTree(node.getRightChild() , data , 2*index+1) ;

//设置当前节点的左孩子和有孩子

node.setLeftChild(leftNode) ;

node.setRightChild(rightNode) ;

return node ;//返回当前创建的节点

}

 

/**

* 后序遍历递归算法

* @param node

*/

public void postList(Node node){

if(node != null){

postList(node.getLeftChild()) ;//遍历左孩子

postList(node.getRightChild()) ;//遍历有孩子

System.out.print(node.getData() + ",");//输出当前节点的s值

}

}

 

/**

* 后序遍历非递归算法

* @param node

*/

public void postList2(Node node){

Stack<Node> stack = new Stack<Node>() ;

while(node != null || !stack.isEmpty()){//节点不为空或者栈部位空时进入循环

if(node != null){//将根节点的所有左孩子入栈

stack.push(node) ;

node = node.getLeftChild() ;

}else{

//如果栈顶节点可以访问,canVisit默认为false,不能访问,只有在有孩子也遍历了之后才可以访问父亲节点

if(stack.lastElement().isCanVisit()){

System.out.print(stack.pop().getData() + ",");//出栈,输出结果

}else{//如果栈顶节点不能访问,则遍历节点的有孩子,并设置节点可以访问

node = stack.lastElement().getRightChild() ;//遍历有孩子

stack.lastElement().setCanVisit(true) ;//将父节点设置为可以访问

}

}

}

}

 

/**

* 查找值data1和data2的第一个祖先节点,返回第一个祖先节点.此处定义了两个栈作为辅助,需要遍历两次二叉树。程序可以大量优化。

* @param root : 从root开始查找

* @param data1 : 值为data1的节点

* @param data2 : 值为data2的节点

* @return

*/

public Node findNode(Node root , int data1 , int data2) {

Stack<Node> s1 = new Stack<Node>() ;//存放data1的祖先节点

Stack<Node> s2 = new Stack<Node>() ;//存放data2的祖先节点

 

findParents(s1 , root , data1) ;//将data1的所有祖先节点存放在s1中

this.find = false ;

findParents(s2 , root , data2) ;//将data2的所有祖先节点存放在s2中

 

Node parent = null ;

while(s1.size()>0 && s2.size()>0 ){//查找第一个祖先节点

if(s1.get(0).getData() == s2.get(0).getData()){

parent = s1.remove(0) ;

s2.remove(0) ;

}else{

break ;

}

}

 

return parent ;//返回第一个祖先节点

}

 

/**

* 从root开始查找值为data1的所有祖先节点,并将祖先节点存放在s中

* @param s : 存放祖先节点的栈

* @param root : 开始寻找的及诶单

* @param data : 寻找节点的值

* @return : 是否找到值为data1的节点

*/

public boolean findParents(Stack<Node> s , Node root , int data){

if(root != null && !find){

s.push(root) ;//根节点入栈

if(data == root.getData()){

find = true ;//找到了节点

}else{

if(root.getLeftChild() != null){

findParents(s , root.getLeftChild() , data) ;//如果左边找到了

}

 

if(root.getRightChild() != null){

findParents(s, root.getRightChild() , data) ;

}

 

if(!find){//如果当前节点的左孩子和有孩子中都没有找到要查找的节点,则当前节点出栈。

s.pop() ;

}

}

}

return find;

}

 

/**

* 中序遍历递归算法

* @param node

*/

public void midList(Node node){

if(node != null){

midList(node.getLeftChild()) ;

System.out.print(node.getData() + ",");

midList(node.getRightChild()) ;

}

}

 

/**

* 中序遍历非递归算法

* @param node

*/

public void midList2(Node node){

Stack<Node> stack = new Stack<Node>() ;

while(node != null || !stack.isEmpty()){

if(node != null){

stack.push(node) ;

node = node.getLeftChild() ;

}else{

node = stack.pop() ;

System.out.print(node.getData() + ",");

node = node.getRightChild() ;

}

}

}

 

/**

* 先序遍历递归算法

* @param node

*/

public void preList(Node node){

if(node != null){

System.out.print(node.getData() + ",");

preList(node.getLeftChild()) ;

preList(node.getRightChild()) ;

}

}

 

/**

* 线序遍历的非递归实现

* @param node

*/

public void preList2(Node p){

Stack<Node> stack = new Stack<Node>() ;

while(p != null || !stack.isEmpty()){

if(p != null){

System.out.print(p.getData() + ",") ;//输出节点的值

stack.push(p) ;       //把根节点入栈

p = p.getLeftChild() ;//寻找左孩子

}else{

p = stack.pop().getRightChild() ;

}

}

}

 

 

public Node getRoot() {

return root;

}

 

 

public void setRoot(Node root) {

this.root = root;

}

 

 

public int getCount() {

return count;

}

 

 

public void setCount(int count) {

this.count = count;

}

}

这里主要实现了二叉树的先序、中序、后序遍历的递归算法和非递归算法。对二叉树的深度和层次遍历没有实现,希望看了此文章的朋友们可以自己实现!

p� rP�� @� an>
/**
* 查找值data1和data2的第一个祖先节点,返回第一个祖先节点.此处定义了两个栈作为辅助,需要遍历两次二叉树。程序可以大量优化。
* @param root : 从root开始查找
* @param data1 : 值为data1的节点
* @param data2 : 值为data2的节点
* @return
*/
public Node findNode(Node root , int data1 , int data2) {
Stack<Node> s1 = new Stack<Node>() ;//存放data1的祖先节点
Stack<Node> s2 = new Stack<Node>() ;//存放data2的祖先节点

findParents(s1 , root , data1) ;//将data1的所有祖先节点存放在s1中
this.find = false ;
findParents(s2 , root , data2) ;//将data2的所有祖先节点存放在s2中

Node parent = null ;
while(s1.size()>0 && s2.size()>0 ){//查找第一个祖先节点
if(s1.get(0).getData() == s2.get(0).getData()){
parent = s1.remove(0) ;
s2.remove(0) ;
}else{
break ;
}
}

return parent ;//返回第一个祖先节点 
}

/**
* 从root开始查找值为data1的所有祖先节点,并将祖先节点存放在s中
* @param s : 存放祖先节点的栈
* @param root : 开始寻找的及诶单
* @param data : 寻找节点的值
* @return : 是否找到值为data1的节点
*/
public boolean findParents(Stack<Node> s , Node root , int data){
if(root != null && !find){
s.push(root) ;//根节点入栈
if(data == root.getData()){
find = true ;//找到了节点
}else{
if(root.getLeftChild() != null){
findParents(s , root.getLeftChild() , data) ;//如果左边找到了
}

if(root.getRightChild() != null){
findParents(s, root.getRightChild() , data) ;
}

if(!find){//如果当前节点的左孩子和有孩子中都没有找到要查找的节点,则当前节点出栈。
s.pop() ;
}
}
}
return find;
}

/**
* 中序遍历递归算法
* @param node
*/
public void midList(Node node){
if(node != null){
midList(node.getLeftChild()) ;
System.out.print(node.getData() + ",");
midList(node.getRightChild()) ;
}
}

/**
* 中序遍历非递归算法
* @param node
*/
public void midList2(Node node){
Stack<Node> stack = new Stack<Node>() ;
while(node != null || !stack.isEmpty()){
if(node != null){
stack.push(node) ;
node = node.getLeftChild() ;
}else{
node = stack.pop() ;
System.out.print(node.getData() + ",");
node = node.getRightChild() ;
}
}
}

/**
* 先序遍历递归算法
* @param node
*/
public void preList(Node node){
if(node != null){
System.out.print(node.getData() + ",");
preList(node.getLeftChild()) ;
preList(node.getRightChild()) ;
}
}

/**
* 线序遍历的非递归实现
* @param node
*/
public void preList2(Node p){
Stack<Node> stack = new Stack<Node>() ;
while(p != null || !stack.isEmpty()){
if(p != null){
System.out.print(p.getData() + ",") ;//输出节点的值
stack.push(p) ;       //把根节点入栈
p = p.getLeftChild() ;//寻找左孩子
}else{
p = stack.pop().getRightChild() ;
}
}
}


public Node getRoot() {
return root;
}


public void setRoot(Node root) {
this.root = root;
}


public int getCount() {
return count;
}


public void setCount(int count) {
this.count = count;
}
}


 

这里主要实现了二叉树的先序、中序、后序遍历的递归算法和非递归算法。对二叉树的深度和层次遍历没有实现,希望看了此文章的朋友们可以自己实现!


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值