因为学得太烂以至于忘掉了老师上课讲的具体步骤。。。/(ㄒoㄒ)/~~
然后作业又要求写,只好自己写了
最后发现除了层序遍历,其它几个都是用栈实现的
还有:
今天才知道,原来
就算你新建了一个树类并赋值为原来的树,他喵的还是按传址处理原来的树类
于是就导致主方法写得很奇葩
好像整个过程就写得很奇葩好伐。。。┑( ̄Д  ̄)┍
package BianLi;
public class Quee {
Node head,tail;
Node pointer;
Object value;
int size;
public Quee(){
head=new Node();
tail=head;
size=0;
}
public void InQuee(Node node)
{
tail.LinkNext(node);
tail=node;
size++;
}
public Node OutQuee()
{
if(size>0)
{
if(size==1)
{
Node n=head.next();
head.LinkNext(null);
size--;
return n;
}
else
{
Node n=head.next();
head.LinkNext(n.next());
//head.next().LinkNext(null); 不知道错在哪里,辣眼睛
size--;
return n;
}
}
else
{
System.out.println("队列是空的");
return null;
}
}
public boolean IsEmpty()
{
if(size==0) return true;
else return false;
}
}
class Node
{
Node next;
Object value;
boolean ifprint;
public Node(){}
public Node (Object value)
{
this.value=value;
ifprint=false;
}
public Node next()
{
return this.next;
}
public void LinkNext(Node node)
{
this.next=node;
}
public Object getValue()
{
return this.value;
}
Node left,right,father;
//左子结点
public void LinkLeftLeaf(Node left)
{
this.left=left;
}
public Node getLeftLeaf()
{
return this.left;
}
//右子结点
public void LinkRightLeaf(Node right)
{
this.right=right;
}
public Node getRightLeaf()
{
return this.right;
}
//父节点
public void LinkFather(Node father)
{
this.father=father;
}
public Node getFather()
{
return this.father;
}
}
package BianLi;
public class Stack {
Node top;
Node bottom;
Node pointer;
int size=0;
public Stack()
{
top=new Node();
bottom=top;
pointer=top;
size=0;
}
public void InStack(Node node)
{
top.LinkNext(node);
top=node;
size++;
}
public Node OutStack()
{
if(size>0)
{
Node n=top;
pointer=bottom;
while(pointer.next()!=top)
pointer=pointer.next();
pointer.LinkNext(null);
top=pointer;
size--;
return n;
}
else
{
System.out.println("栈是空的");
return null;
}
}
}
package BianLi;
public class TreeClass {
Node root;//根结点
Object value;
public TreeClass(Node root)
{
this.root=new Node();
this.root=root;
}
//添加左子结点
public void AddLeftLeaf(Node left)
{
root.LinkLeftLeaf(left);
left.LinkFather(root);
}
//添加右子节点
public void AddRightLeaf(Node right)
{
root.LinkRightLeaf(right);
right.LinkFather(root);
}
//判断父节点是否有子节点
public boolean HaveChild(Node root)
{
boolean have=true;
if((root.getLeftLeaf()==null)&&(root.getRightLeaf()==null)) have=false;
return have;
}
//层序遍历:利用队列,从根节点开始入队
public void LevelOrder()
{
Quee q =new Quee();
q.InQuee(root);
System.out.println("层序遍历是:");
while(q.size>0)
{
root=q.head.next();
if(HaveChild(root))//添加父节点的所有孩子
{
if(root.getLeftLeaf()!=null)
{
q.InQuee(root.getLeftLeaf());
}
if(root.getRightLeaf()!=null)
{
q.InQuee(root.getRightLeaf());
}
}
System.out.print(q.OutQuee().getValue());
}
}
/*后序遍历:用栈储存
如果有左子树,一直找到没有左子树为止
否则找右子树
如果发现已经找到底(没有左子树和右子树)那么开始出栈,根节点退回上一节点
*/
public void PostOrder()
{
Stack s=new Stack();
s.InStack(root);
System.out.println("后序遍历是:");
while(s.size>0)
{
if(root.getLeftLeaf()!=null)
while(root.getLeftLeaf()!=null)
{
s.InStack(root.getLeftLeaf());
Node n=root.getLeftLeaf();
root.LinkLeftLeaf(null);//为了防止出栈退回节点时发生死循环,找到子节点后从树上删掉父节点与子节点的连接
root=n;
}
else if(root.getRightLeaf()!=null)
{
s.InStack(root.getRightLeaf());
Node n=root.getRightLeaf();
root.LinkRightLeaf(null);
root=n;
}
else
{
System.out.print(s.OutStack().getValue());
root=s.top;
}
}
}
/*
前序遍历:和后序遍历有区别的是,在输出的时候因为先输出的是根节点的值但根节点又不能出栈,所以要设置一个
参照判断根节点有没有被输出过
然后再依次让左右子节点依次入栈并成为新的根节点
*/
public void PreOrder()
{
Stack s=new Stack();
s.InStack(root);
System.out.println("前序遍历是:");
while(s.size>0)
{
if(root.ifprint==false)
{
System.out.print(root.getValue());
root.ifprint=true;
}
if(root.getLeftLeaf()!=null)
{
s.InStack(root.getLeftLeaf());
Node n=root.getLeftLeaf();
root.LinkLeftLeaf(null);
root=n;
}
else if(root.getRightLeaf()!=null)
{
s.InStack(root.getRightLeaf());
Node n=root.getRightLeaf();
root.LinkRightLeaf(null);
root=n;
}
else
{
s.OutStack();
root=s.top;
}
}
}
/*
* 中序遍历:中序遍历与先前的稍有差异
* 虽然也是一路找到左子结点到底为止,但是应该注意;
* 当左子节点没有了的时候应该先输出根节点然后再操作右结点
* 同样的,每次操作后,下一个被遍历的子节点称为新的根节点
* 当然,当到底的时候应该从栈里弹出
*/
public void InOrder()
{
Stack s=new Stack();
s.InStack(root);
System.out.println("中序遍历是:");
while(s.size>0)
{
if(root.getLeftLeaf()!=null)
while(root.getLeftLeaf()!=null)
{
s.InStack(root.getLeftLeaf());
Node n=root.getLeftLeaf();
root.LinkLeftLeaf(null);
root=n;
}
else if(root.getRightLeaf()!=null)
{
System.out.print(root.getValue());
root.ifprint=true;
s.InStack(root.getRightLeaf());
Node n=root.getRightLeaf();
root.LinkRightLeaf(null);
root=n;
}
else
{
if(root.ifprint==false)
{
System.out.print(s.OutStack().getValue());
root.ifprint=true;
}
else
{
s.OutStack();
}
root=s.top;
}
}
}
}
package BianLi;
public class MainMethod {
public static void main(String[] args)
{
//建立好二叉树
Node leaf1=new Node('+');
Node leaf2=new Node('A');
Node leaf3=new Node('/');
Node leaf4=new Node('*');
Node leaf5=new Node('D');
Node leaf6=new Node('B');
Node leaf7=new Node('C');
TreeClass tree=new TreeClass(leaf1);
tree.AddLeftLeaf(leaf2);
tree.AddRightLeaf(leaf3);
tree.root=leaf3;
tree.AddLeftLeaf(leaf4);
tree.AddRightLeaf(leaf5);
tree.root=leaf4;
tree.AddLeftLeaf(leaf6);
tree.AddRightLeaf(leaf7);
tree.root=leaf1;
tree.LevelOrder();
System.out.println();
tree.root=leaf1;
TreeClass treepost=new TreeClass(leaf1);
treepost=tree;
treepost.PostOrder();
System.out.println();
TreeClass treepre=new TreeClass(leaf1);
treepre.AddLeftLeaf(leaf2);
treepre.AddRightLeaf(leaf3);
treepre.root=leaf3;
treepre.AddLeftLeaf(leaf4);
treepre.AddRightLeaf(leaf5);
treepre.root=leaf4;
treepre.AddLeftLeaf(leaf6);
treepre.AddRightLeaf(leaf7);
treepre.root=leaf1;
treepre.PreOrder();
System.out.println();
leaf1.ifprint=false;
leaf2.ifprint=false;
leaf3.ifprint=false;
leaf4.ifprint=false;
leaf5.ifprint=false;
leaf6.ifprint=false;
leaf7.ifprint=false;
TreeClass treein=new TreeClass(leaf1);
treein.AddLeftLeaf(leaf2);
treein.AddRightLeaf(leaf3);
treein.root=leaf3;
treein.AddLeftLeaf(leaf4);
treein.AddRightLeaf(leaf5);
treein.root=leaf4;
treein.AddLeftLeaf(leaf6);
treein.AddRightLeaf(leaf7);
treein.root=leaf1;
treein.InOrder();
}
}
运行结果:
层序遍历是:
+A/*DBC
后序遍历是:
ABC*D/+
前序遍历是:
+A/*BCD
中序遍历是:
A+B*C/D
突然发现是按照老师上课讲的写的,只不过写成了鬼畜版(QAQ)
中根遍历非递归算法
1. 建立栈结构,建立一个节点作为当前节点
2. 如果当前节点非空或者栈非空,重复执行3-5步
3. 重复执行这样操作:如果当前节点非空,便将其压入栈中,并让当前节点访问当前节点的左子节点,直到当前节点再无左节点
4. 如果栈非空,则访问栈顶节点并出栈
5. 当前节点变为出栈节点的右子节点。
先根遍历非递归算法
1. 建立栈结构,建立当前节点
2. 如果当前节点非空或者栈非空,重复执行3-5步
3. 重复执行这样操作:如果但前节点非空,访问当前节点,并将其压入栈中,并让当前节点访问当前节点的左子节点,直到当前节点再无左节点
4. 如果栈非空,则栈顶出栈
5. 当前节点变为出栈节点的右子节点。
后根遍历非递归算法
1.建立栈结构,建立当前节点,建立当前节点的前一次访问节点
2.根节点压栈
3.如果栈非空,重复4-6步
4.当前节点为栈顶节点
5.如果当前节点没有子节点或子节点在上一步已经被访问过
•则
访问当前节点,栈顶出栈,并记录前一次访问节点为当前节点。
6.否则
•如果当前节点有右子节点,则
右子节点压栈
•如果但前节点有左子节点,则
左子节点压栈