java数据结构-----二叉树和利用二叉树排序

想要完成二叉树,就必须要先建一颗二叉树,那么该如何创建呢?有很多种方法,其一是利用广义表来创建,其二是利用当遇见空节点时将其赋值为某一元素如“*”,其三是利用二叉树的储存结构直接在主函数手动创建一个二叉树。今天我们就用第一种方法演示。

第一种方法就是利用广义表,广义表储存就需要用到堆栈和压栈,还需要用一个标记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;
	}
}

下一章 队列。

谢谢观看!

  • 8
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小魏苦练算法

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值