一:二叉树相关操作
1:构造一个二叉树
2:二叉树前序遍历(递归)
3:二叉树中序遍历(递归)
4:二叉树后续遍历(递归)
5:二叉树前序遍历(非递归)
6:二叉树中序遍历(非递归)
7:二叉树后序遍历(非递归)
二:代码实现
2.1:节点结构
/**
* 节点类
*/
private static class BinaryNode{
private int value;
private BinaryNode leftNode;
private BinaryNode rightNode;
public BinaryNode(int value) {
this(value, null, null);
}
public BinaryNode(int value, BinaryNode leftNode, BinaryNode rightNode) {
this.value = value;
this.leftNode = leftNode;
this.rightNode = rightNode;
}
}
2.2:构造一个二叉树
/**
* 构造二叉树
* @param datas 二叉树中各节点的值
* @param nodeList 二叉树中的各节点
* 可以讲的点:
* 1:先构造节点信息(把数据加到节点当中),节点信息保存到数组中
* 2:为父节点添加相应的子节点
* 2.1:节点个数和父节点的关系 2倍关系
* 2.2:最后一个父节点需要特殊处理,奇数的话,有右孩子,偶数的话没有右孩子
*
*/
public void createBinaryTree(int[] datas, List<BinaryNode> nodeList){
//为各节点添加数据域
BinaryNode binaryNode = null;
for(int i = 0; i < datas.length; i++){
binaryNode = new BinaryNode(datas[i]);
nodeList.add(binaryNode);
}
/**
* 说明:
* 1、为各个父节点添加相应的子节点,按照层序的方式添加子节点
* 2、将二叉树按照完全二叉树编号,根节点的编号为1,若某节点i有左孩子,则其左孩子的编号为2i
* 若某节点有右孩子,则其右孩子的编号为(2i + 1)
* 3、二叉树中若有n个节点,那么父节点的个数为(n/2)
* 4、二叉树中若节点的个数为奇数,那么最后一个父节点有右子节点
* 若节点的个数为偶数,那么最后一个父节点只有左子节点,没有右子节点
* 5、list中节点的下标从0开始,因此编号为i的节点存储到下标为(i - 1)的位置
*/
//nodeList.size() / 2 - 1,减1的原因是,最后一个父节点可能没有右子节点,所以需要单独处理
for(int i = 0; i < nodeList.size() / 2 - 1; i++){
//加1的原因是,list从0开始编号
nodeList.get(i).leftNode = nodeList.get(i * 2 +1);
nodeList.get(i).rightNode = nodeList.get(i * 2 + 1 + 1);
}
//单独处理最后一个父节点
int lastNode = nodeList.size() / 2 - 1;
nodeList.get(lastNode).leftNode = nodeList.get(lastNode * 2 + 1);
//二叉树中节点的总个数为奇数,此时最后一个父节点有右子节点
if(nodeList.size() % 2 != 0){
nodeList.get(lastNode).rightNode = nodeList.get(lastNode * 2 + 1 + 1);
}
}
2.3:前序遍历二叉树(递归)
/**
* 前序递归遍历二叉树
* 根左右
*/
public void preTraverse(BinaryNode rootNode){
//递归遍历结束条件
if(rootNode == null){
return;
}else{
//访问根节点rootNode的数据域
System.out.print(rootNode.value + ", ");
//前序递归调用rootNode的左子树
preTraverse(rootNode.leftNode);
//前序递归调用rootNode的右子树
preTraverse(rootNode.rightNode);
}
}
2.4:中序遍历(递归)
/**
* 中序递归遍历二叉树
* 左根右
*/
public void inTraverse(BinaryNode rootNode){
if(rootNode == null){
return;
}else{
inTraverse(rootNode.leftNode);
System.out.print(rootNode.value + ", ");
inTraverse(rootNode.rightNode);
}
}
2.5:后序遍历(递归)
/**
* 后序递归调用二叉树
* 左右跟
*/
public void postTraverse(BinaryNode rootNode){
if(rootNode == null){
return;
}else{
postTraverse(rootNode.leftNode);
postTraverse(rootNode.rightNode);
System.out.print(rootNode.value + ", ");
}
}
2.6:层序遍历(从上到下)
/**
* 层序遍历节点
* 思路
* 1:用一个数组当成一个队列
* 2:两个下标front控制出队,和rear控制入队
*/
private void levelTraverse(BinaryNode rootNode, int nodeSize) {
// 使用顺序队列
BinaryNode[] nodes = new BinaryNode[nodeSize];
int front = -1, rear = -1;
// 二叉树为空,直接结束
if (rootNode == null) {
return;
}
// 根节点入队列
nodes[++rear] = rootNode;
BinaryNode tempNode = null;
// 当队列非空时
while (front != rear) {
// 出队
tempNode = nodes[++front];
System.out.print(tempNode.value + ", ");
// 将当前节点的左节点入队列
if (tempNode.leftNode != null) {
nodes[++rear] = tempNode.leftNode;
}
// 将当前节点的右节点入队列
if (tempNode.rightNode != null) {
nodes[++rear] = tempNode.rightNode;
}
}
}
2.7:前序遍历(非递归)
/**
* 前序非递归遍历二叉树
* 1:根左右
* 步骤:
* 1:我们用栈来存储二叉树信息
* 2:根节点入栈,输出根节点到值,将节点左孩子循环入栈,输出,
* 3:栈顶元素为最左节点,出栈
*/
public void preTraverseByLoop(BinaryNode rootNode){
Stack<BinaryNode> nodeStack = new Stack<BinaryNode>();
//若根节点和栈均为空,则整个二叉树遍历结束
while(rootNode != null || !nodeStack.isEmpty()){
while(rootNode != null){
System.out.print(rootNode.value + ", ");
//将根节点入栈,以便通过它找到这个树的右子树
nodeStack.push(rootNode);
//准备遍历根节点的左子树
rootNode = rootNode.leftNode;
}
//此时根节点为空,但是栈非空,将根节点弹出,并遍历根节点的左子树
if(!nodeStack.isEmpty()){
rootNode = nodeStack.pop();
rootNode = rootNode.rightNode;
}
}
}
2.8:中序非递归方式实现
/**
* 中序非递归遍历二叉树
* 左根有
* 步骤:
* 1:我们用一个栈来解决,左子树一直入栈完毕
* 2:输出栈顶元素 ,最后访问右字数
*
*/
public void inTraverseByLoop(BinaryNode rootNode){
Stack<BinaryNode> nodeStack = new Stack<BinaryNode>();
while(rootNode != null || !nodeStack.isEmpty()){
while(rootNode != null){
nodeStack.push(rootNode);
rootNode = rootNode.leftNode;
}
if(!nodeStack.isEmpty()){
//遍历过程中,不能立即访问,只有当它的左子树遍历完毕,才从栈中弹出并访问
rootNode = nodeStack.pop();
System.out.print(rootNode.value + ", ");
rootNode = rootNode.rightNode;
}
}
}
2.9: 后序遍历非实现
/**
* 后序非递归遍历二叉树
*/
public void postTraverseByLoop(BinaryNode rootNode){
Stack<BinaryNode> nodeStack = new Stack<BinaryNode>();
BinaryNode pre = rootNode;
while(rootNode != null || !nodeStack.isEmpty()){
while(rootNode != null){
nodeStack.push(rootNode);
rootNode = rootNode.leftNode;
}
if(!nodeStack.isEmpty()){
BinaryNode tempNode = nodeStack.peek().rightNode;
if(tempNode == null || tempNode == pre){
rootNode = nodeStack.pop();
System.out.print(rootNode.value + ", ");
pre = rootNode;
rootNode = null;
}else{
rootNode = tempNode;
}
}
}
}
三: 源代码下载