二叉查找树的循环插入以及使用循环和递归的两种先序遍历方式

二叉查找树的循环插入以及使用循环和递归的两种先序遍历方式##

  • 使用一个内部类来当做树的节点
  • 循环插入元素
  • 先序遍历的递归实现
  • 先序遍历的循环实现

成员变量

public class BinTree<T> {
	Node<T> root;

内部类

//树中的节点用内部类表示
		 class Node<E>{
		//一个节点中包含指向左右儿子节点的引用和这个节点包含的数据
		 Node<E> Left;
		 Node<E> Right;
		 Node<E> parent;
		 E data;
		public Node<E> getLeft() {
			return Left;
		}
		public void setLeft(Node<E> left) {
			Left = left;
		}
		public Node<E> getRight() {
			return Right;
		}
		public void setRight(Node<E> right) {
			Right = right;
		}
		public E getData() {
			return data;
		}
		public void setData(E data) {
			this.data = data;
		}
		public Node() {
			super();
			// TODO Auto-generated constructor stub
		}
		public Node(E e,Node<E> parent) {
			this.data= e;
			this.parent = parent;
		}

插入元素

public void add(T e ){
		//先判断这棵树是不是空的
		Node<T> t = root;
		if(t==null) {
			this.root = new Node(e,null);
			return;
		}
		
		int cmp;
		//定义一个父节点
		Node<T> parent;
		//
		do {			
			parent = t;
			Comparable<? super T> k = (Comparable<? super T>) e;
			cmp = k.compareTo(t.getData());
			if(cmp<0) {
				t = t.Left;				
			}else if(cmp>0) {
				t=t.Right;
			}
			else return;
		}while(t!=null);
		//子类节点中包含一个对父类节点的引用,可以通过其来访问父类节点
		Node<T> w = new Node(e, parent);
        if (cmp < 0)
        	//将子节点赋值给父节点的左儿子节点引用,也就是说父节点的左子节点指向新插入的节点
            parent.Left = w;
        else
        	//将子节点赋值给父节点的右儿子节点引用,也就是说父节点的右子节点指向新插入的节点
            parent.Right = w;									
		}

先序遍历的递归实现

递归实现感觉还是比较容易思考的到的,因为看数据结构的视频的时候,老师都是用c语言实现的,不过不会c语言,所以就用java试试看

public void preorder() {
		if(this.root==null) {
			return ;
		}
		preorder(this.root);
		
	}
	public void preorder(Node<T> node) {
		System.out.println(node.data.toString());
		
		
		if(node.Left!=null) {
			preorder(node.Left);			
		}
		if(node.Right!=null) {
			
			preorder(node.Right);
		}
		
		
	}

先序遍历的循环实现

写这个的时候,我是使用了两个集合,一个冲当栈,一个放出栈的元素,其实应该是一个集合或者数组就可以的,但是不想改了,以后有时间再改一下吧。

//使用循环 先序遍历  一个排序二叉树
		//先序遍历:先遍历树的根节点,然后遍历树的左子树,最后遍历树的右子树
	public void loopPreOrder() {
		if(root == null) {
			return;
		}
		//栈
		LinkedList<Node<T>>	 list1 = new LinkedList<>();
		//出栈后的元素放在这个集合里    简称 垃圾堆
		LinkedList<Node<T>>	 list2 = new LinkedList<>();
		Node<T> t = root;
		//定义一个父节点
		Node<T> parent;
		do {			
			parent = t;
			//如果栈集合中不包含这个父节点,就让它进栈,并打印出来
			if(!list1.contains(parent)) {
			list1.add(t);
			System.out.println(parent.getData().toString());
			}	
			//如果这个节点的左子节点不为空同时垃圾堆集合中不包含这个左子节点(为了防止重复进栈)
			// 就把它的左子节点 赋值给t,成为下一个父节点 
			if(t.Left!=null&&(!list2.contains(t.Left))) {
				t = t.Left;
			//同上	
			}else if(t.Right!=null&&(!list2.contains(t.Right))) {
				
				t  = t.Right;
			//如果这个节点没有左子节点和右子节点,就把这个节点放到垃圾堆中
				//同时在栈集合中移除这个节点,同时判断一下这个栈集合中是否为空,如果空
					//就说明 遍历结束,跳出循环
			}else {
				list2.add(list1.getLast());
				list1.removeLast();
				if(!list1.isEmpty()) {
					t = list1.getLast();
				}else {
					return ;
				}
				
			}
						
		}while(list1.size()!=0);
			
		}

插入操作参考了TreeMap集合中的插入的源码,简化了很多,然后循环遍历的时候和插入的操作其实好相像。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值