您的位置:首页 > 职场人生

求职系列1--树构造、遍历

2016-08-11 16:56 162 查看
最近面试被问到树相关的问题,哎,好久没看了,忽然间还不太容易写出来,这次就总结下树相关的操作。

1、树的构造(java)

树构造分为两部分:
一部分是树种节点,即Node节点,一般包括其Key、leftChild、rightChild,还可以自己构造一些方法,比如打印本节点的值。
第二部分即树,主要包括树的生成、查询节点、删除节点、更新节点、遍历节点,(本次主要针对树的生成,以及树的遍历来讲述基本操作)。

第一部分Node节点构造,类结构如下:
</pre><pre name="code" class="java">public class Node {
private int key;  //节点主键
private int value;  //节点值

private Node left;  //左孩子节点
private Node right;  //右孩子节点

public Node(int key,int value) {
this.key = key;
this.value = value;
}

public int getKey() {
return key;
}
public void setKey(int key) {
this.key = key;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
public Node getLeft() {
return left;
}
public void setLeft(Node left) {
this.left = left;
}
public Node getRight() {
return right;
}
public void setRight(Node right) {
this.right = right;
}

public void display(){  //打印本节点的值
System.out.println(key+":"+value);
}
}
第二部分:树相关结构,主要有root即根节点,以及树的构造方法。
public class Tree {

private Node root;  //树的根节点

public void insert(int key,int value){
Node node = new Node(key,value);
if(root==null)
{
root = node;  //如果树为空,新节点作为root节点
}
else{
Node current = root;  //如果树不为空,root节点赋为当前节点
while(true){  //一直循环,直到找到最后节点位置
Node parent = current;  //parent为访问节点的父节点,current为访问节点(最后插入位置)
if(current.getKey()<key){
current = current.getRight();
if(current == null)
{
parent.setRight(node);
return;
}
}
else{
current = current.getLeft();
if(current == null)
{
parent.setLeft(node);
return;
}
}
}

}

}

public Node find(int key){
if(root.getKey() == key)
return root;
Node current = root;

while(current!=null){
if(current.getKey()==key)
{
return current;

}
else{
if(current.getKey()<key)
current = current.getRight();
else
current = current.getLeft();
}
}
return null;
}
}

2、树的三种遍历

2.1.1 树的前序遍历--递归实现

public void preOrderRecrusion(Node root){
Node p = root;
if(p==null)
return;
else{
p.display();  //打印本节点的值
preOrderRecrusion(p.getLeft());  //遍历左节点
preOrderRecrusion(p.getRight());  //遍历右节点
}
}

2.1.2 树的前序遍历--非递归实现

基本思想:
1、将树根入栈,循环中每次先弹出栈顶元素即根并访问;
2、如果存在右子树则先将右子树入栈,如果存在左子树再将左子树入栈;
3、一直循环至栈空。
public void preNonRecrusion(Node root){
Node current = root;
Stack<Node> stack = new Stack<Node>();  //申请栈,保存访问节点
if(current == null)
return;
stack.push(current);
while(!stack.isEmpty())  //将root节点弹出并访问,如果有右子树则将右节点入栈,左子树同理
{
current = stack.pop();
current.display();
if(current.getRight() != null)
stack.push(current.getRight());
if(current.getLeft() != null)
stack.push(current.getLeft());
}
}

2.2.1 树的中序遍历--递归实现

public void midRecrusion(Node root){
Node current = root;

if(root == null)
return;
else{
midRecrusion(current.getLeft());
current.display();
midRecrusion(current.getRight());
}
}

2.2.2 树的中序遍历--非递归实现

基本思想:
1、从根节点开始,一直向左下找,直到节点为空,即到达左下节点的左节点(空节点),遍历的每个节点都入栈,最后一个不入;
2、当前current指向为最左节点的左孩子(为空),如果左孩子为空,则将栈中左节点弹出并访问,将其current指向弹出节点的右孩子,继续第一步,循环执行,直至栈为空或current为空。
public void midNonRecrusion(Node root){
Node current = root;
Stack<Node> stack = new Stack<Node>();
if(current == null) return;

while(current!=null || !stack.isEmpty())
{
while(current!=null)  //沿着左分支一直往下找,将每个节点分别入栈
{
stack.push(current);
current = current.getLeft();
}
if(current == null){  //如果到达底端,则将栈中节点弹出,把current指向弹出节点的右节点,重复以上步骤
Node tmp = stack.pop();
tmp.display();
current = tmp.getRight();
}
}
}


2.3.1 树的后续遍历--递归实现

public void postRecrusion(Node root){
Node current = root;
if(current == null)
return;
else{
postRecrusion(current.getLeft());
postRecrusion(current.getRight());
current.display();
}
}

2.3.2 树的后续遍历 -- 非递归实现

基本思想:
1、将root入栈,栈不为空,则执行循环,循环体为以下;
2、如果 栈顶节点的左孩子、右孩子都为空或者前一次弹出节点为这次节点的左孩子或者右孩子,则将栈顶元素弹出,并访问;
3、如果栈顶的右孩子存在,则将右孩子入栈;然后,如果左孩子存在,再将左孩子入栈。

public void postNonRecrusion(Node root){
Node pre; //上一次访问的节点,用于判断当前节点的孩子节点是否访问过
Node current = root;
if(current == null) return;
Stack<Node> stack = new Stack<Node>();
stack.push(current);

while(!stack.isEmpty()){
current = stack.peek();
if( (current.getLeft()==null && current.getRight()==null)
|| ( pre!=null && (pre==current.getLeft() || pre==current.getRight()) )  )
{
pre = stack.pop();
pre.display();
}else{
if(current.getRight() != null)
stack.push(current.getRight());
if(current.getLeft() != null)
stack.push(current.getLeft());
}

}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: