想要完成二叉树,就必须要先建一颗二叉树,那么该如何创建呢?有很多种方法,其一是利用广义表来创建,其二是利用当遇见空节点时将其赋值为某一元素如“*”,其三是利用二叉树的储存结构直接在主函数手动创建一个二叉树。今天我们就用第一种方法演示。
第一种方法就是利用广义表,广义表储存就需要用到堆栈和压栈,还需要用一个标记flag(当其为true时处理左子树,当为false时处理右子树)。当遇见“(”时将标记flag=true,然后再堆栈(即将根节点放到栈顶);当遇见“,”时,说明这个时候要处理的是右子树,将标记flag=flase;当遇见“)”的时候,说明这个根节点的左右子树都已经创建好让这个根节点出栈就行了;最后就是处理字母,当遇见字母的时候,根据flag的真假来判断其是左子树还是右子树。重复这个过程,直至到达广义表的最右端。
public void CreatTree2(String a){
int len=a.length();
Node<Character> p=null;
char ch;
int i=0;
boolean flag = true;
Stack<Node> st=new Stack<Node>();
while(i<len) {
ch=a.charAt(i);
if(ch=='(') {
flag=true;
st.push(p);
}else if(ch==',') {
flag=false;
}else if(ch==')') {
st.pop();
}else {
p=new Node<Character>(ch);
if(root==null)
root=p;
else {
if(!st.empty()) {
if(flag==true)
st.peek().left=p;
else
st.peek().right=p;
}
}
}
i++;
}
}
接下来时遍历,遍历可以用递归,也可以用堆栈压栈。递归就用中序来演示。递归的过程会将每个节点都遍历三次,中序遍历就是只在每个节点第二次出现的时候输出,期代码为
private void Z_printTree2(Node<Character> t) {
if(t!=null) {
Z_printTree2(t.left);
System.out.print(t.date+" ");
Z_printTree2(t.right);
}
}
再说另一种方法,也比较好理解,就是如果节点的右节点不为空,则将右节点压栈,如果左节点不为空就对左节点压栈(先右后左,因为栈是后进先出),操作完一轮之后出栈顶元素。反复这个过程,直至栈为空。
private void X_printTree1(Node<Character> t) {
if(t!=null) {
Stack<Node> st=new Stack<Node>();
st.push(t);
while(!st.empty()) {
t=st.pop();
System.out.print(t.date+" ");
if(t.right!=null)
st.push(t.right);
if(t.left!=null)
st.push(t.left);
}
}
System.out.println();
}
查找:查找也是利用递归,当找到这个节点的时候,直接将这个节点返回就行,左右节点递归这个过程,如果说没有找到,直接返回一个空节点,然后再在主函数中判断是否为空,就能够判断出是否找到。
private Node<Character> SearchNode(Node<Character> t,char k) {
Node<Character> s;
if(t==null)
return null;
else {
if(t.date==k)
return t;
else {
s=this.SearchNode(t.left,k);
if(s!=null)
return s;
else
return this.SearchNode(t.right,k);
}
}
}
根节点的个数。其方法也一样,利用递归,就是每递归一次就加一,最后加一个根节点的个数就行了
private int Number(Node<Character> t) {
if(t==null)
return 0;
return Number(t.left)+Number(t.right)+1;
}
二叉树的高度,就是对左树和右树递归,然后比较左树和右树那一棵树更高,让高的那一颗加一即可。(每次对根节点加一,就相当于一直重复这个过程,递归有点抽象,还是要多理解)
private int Height(Node<Character> t) {
if(t==null)
return 0;
int p1=Height(t.left);
int p2=Height(t.right);
return Math.max(p1, p2)+1;
}
最后就是整个代码。
public class Test01 {
public static void main(String[] args) {
Scanner srr=new Scanner(System.in);
OperateTree tree=new OperateTree();
String str="A(B(D,E),C(K,F(G,)))";
tree.CreatTree2(str);
tree.toX_printTree1();
tree.toZ_printTree2();
System.out.println();
//该二叉树的高度为:
System.out.println("二叉树的高度为:"+tree.toHeight());
//该二叉树有多少个节点
System.out.println("二叉树节点的个数为:"+tree.toNumber());
//对二叉树上面的字母查找
System.out.print("请输入你想要查找的字母:");
char k=srr.next().charAt(0);
if(tree.toSearchNode(k)!=null)
System.out.println("查找成功");
else
System.out.println("查找失败");
}
}
class OperateTree{
Node<Character> root;
OperateTree(){
root=null;
}
Scanner sr=new Scanner(System.in);
public void toCreatTree1() {
System.out.println("请创建一个二叉树");//中序遍历创建一颗二叉树,当二叉树的节点为空,就用‘*’代替
this.CreatTree1(root);
}
private void CreatTree1(Node<Character> t) {
char ch;
ch=sr.next().charAt(0);
if(ch=='*')
t=null;
else {
t=new Node<Character>(ch);
CreatTree1(t.left);
CreatTree1(t.right);
}
}
public void CreatTree2(String a){
int len=a.length();
Node<Character> p=null;
char ch;
int i=0;
boolean flag = true;
Stack<Node> st=new Stack<Node>();
while(i<len) {
ch=a.charAt(i);
if(ch=='(') {
flag=true;
st.push(p);
}else if(ch==',') {
flag=false;
}else if(ch==')') {
st.pop();
}else {
p=new Node<Character>(ch);
if(root==null)
root=p;
else {
if(!st.empty()) {
if(flag==true)
st.peek().left=p;
else
st.peek().right=p;
}
}
}
i++;
}
}
public void toX_printTree1() {
System.out.print("先序输出为:");
this.X_printTree1(root);
}
private void X_printTree1(Node<Character> t) {
if(t!=null) {
Stack<Node> st=new Stack<Node>();
st.push(t);
while(!st.empty()) {
t=st.pop();
System.out.print(t.date+" ");
if(t.right!=null)
st.push(t.right);
if(t.left!=null)
st.push(t.left);
}
}
System.out.println();
}
public void toZ_printTree2() {
System.out.print("中序输出为:");
this.Z_printTree2(root);
}
private void Z_printTree2(Node<Character> t) {
if(t!=null) {
Z_printTree2(t.left);
System.out.print(t.date+" ");
Z_printTree2(t.right);
}
}
public Node<Character> toSearchNode(char k){
return this.SearchNode(root, k);
}
private Node<Character> SearchNode(Node<Character> t,char k) {
Node<Character> s;
if(t==null)
return null;
else {
if(t.date==k)
return t;
else {
s=this.SearchNode(t.left,k);
if(s!=null)
return s;
else
return this.SearchNode(t.right,k);
}
}
}
public int toHeight() {
return this.Height(root);
}
private int Height(Node<Character> t) {
if(t==null)
return 0;
int p1=Height(t.left);
int p2=Height(t.right);
return Math.max(p1, p2)+1;
}
public int toNumber() {
return this.Number(root);
}
private int Number(Node<Character> t) {
if(t==null)
return 0;
return Number(t.left)+Number(t.right)+1;
}
}
class Node<N>{
N date;
Node left;
Node right;
public Node(N date) {
this.date=date;
left=null;
right=null;
}
public Node() {
}
}
如何利用二叉树排序?
如果说二叉树你已经懂了的话,那么二叉树排序对你来说就很容易了,就是在创建的时候,以某个数为根节点,将大于这个根节点的数放到二叉树的右边,将小于这个节点的数放到二叉树的左边,一直重复这个过程,直至建好一颗你想要的二叉树,然后再中序输出就是从小到大的顺序(因为左边的数永远比右边的数小)还有就是对重复数的处理,你可以给一个提示,也可以直接不管。堆排序的好处就在于其时间复杂度很低;
public class TreeNode {
public static void main(String[] args) {
// TODO Auto-generated method stub
int a[]= {1,5,2,8,23,4,1,2,5};
methord st=new methord();
for(int i=0;i<a.length;i++) {
st.addNode(a[i]);
}
System.out.println("堆排序之后为:");
st.Z_print(st.root);
}
}
class methord{
Node root;
public void addNode(int date){
Node newNode=new Node(date);
if(root==null) {
root=newNode;
return;
}
else {
Node temp=root;
while(temp!=null) {
if(temp.date>date) {
if(temp.left==null) {
temp.left=newNode;
return;
}
else
temp=temp.left;
}else if(temp.date<date) {
if(temp.right==null) {
temp.right=newNode;
return;
}else
temp=temp.right;
}else {
System.out.println("已帮你删除重复数字:"+date);
return ;
}
}
}
}
public void Z_print(Node n) {
if(n==null)
return;
Z_print(n.left);
System.out.print(n.date+" ");
Z_print(n.right);
}
}
class Node{
int date;
Node left;
Node right;
public Node(int date){
this.left=null;
this.right=null;
this.date=date;
}
}
下一章 队列。
谢谢观看!