Java实现二叉树的遍历、添加、删除
2018-01-23 15:08
513 查看
定义
二叉树在图论中是这样定义的:二叉树是一个连通的无环图,并且每一个顶点的度不大于3。有根二叉树还要满足根结点的度不大于2。有了根结点之后,每个顶点定义了唯一的父结点,和最多2个子结点。然而,没有足够的信息来区分左结点和右结点。如果不考虑连通性,允许图中有多个连通分量,这样的结构叫做森林。为什么需要使用二叉树
二叉树,本质上,是对链表和数组的一个折中。比如,我有一个任务,需要输入 10万个数据(32位整数),然后有两个操作:
1.添加(删除)一个整数。
2.询问第x大的数据。
比如,我给你 1, 8, 13, 10(等等一堆数据)…….
然后我询问第3大的数据,然后我插入 18
然后我询问第4大的数据我再插入 9
我再询问第2大的数据不停的重复1,2重复10万次。。应该如何实现。
你会发现,用有序链表,不行,查找(包括1需要找到对应位置,以及2查找)成本大O(N),但具体这个插入操作成本小O(1)。用有序数组,查找(2的查找)成本小O(1)。但1的插入操作成本很大O(N)。
所以,我们折中使用排序二叉树(二叉树仅仅作为排序二叉树的基础),查找(包括1需要找到对应位置,以及2查找)成本挺小O(logN)。具体这个插入操作成本也挺小O(logN)。具体的应用就是由排序二叉树(由于普通排序二叉树可能会有不平衡的情况)引申出来的红黑树(linux中ext3文件系统管理),avl树“windows对进程地址空间的管理”。
引用于知乎:二叉树可以解决什么问题
二叉查找树
定义
二叉查找树(Binary Search Tree),又被称为二叉搜索树。设x为二叉查找树中的一个结点,x节点包含关键字key,节点x的key值记为key[x]。如果y是x的左子树中的一个结点,则key[y] <= key[x];如果y是x的右子树的一个结点,则key[y] >= key[x]。性质
若任意节点的左子树不空,则左子树上所有结点的值均小于它的根结点的值;任意节点的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
任意节点的左、右子树也分别为二叉查找树。
没有键值相等的节点(no duplicate nodes)。
Java实现
Node节点类可以添加多个data值或对象,只要有能进行比较区分的值即可。比如说我用二叉查找树存储person,那么节点中就有一个person的索引,和一个person对象,这里为了方便添加就直接使用了int。
public class Node { public int data; public Node rightChild; public Node leftChild; public Node(int value) { data = value; rightChild = null; leftChild = null; } }
二叉查找树的插入
在插入的时候会比较节点的大小,小的节点放在左边,大的节点放在右边。其中root变量属于二叉树类的属性变量。
public void insertNode(int value) { Node newNode = new Node(value); Node curr = root; if (root == null) { root = newNode; } else { while (true) { if (curr.data > value) { if (curr.leftChild == null) { curr.leftChild = newNode; return; } else curr = curr.leftChild; } else { if (curr.rightChild == null) { curr.rightChild = newNode; return; } else curr = curr.rightChild; } } } }
查找某个节点
public Node getNode(int value) { if (root == null) { return null; } else { Node current = root; while (current.data != value) { if (current.data > value) { current = current.leftChild; } else { current = current.rightChild; } if (current == null) return null; } return current; } }
二叉树的遍历(递归版本)
二叉树的遍历百度百科讲的很清楚了,如果有不清楚的可以去看看:二叉树的遍历
下面我们来看Java程序的实现。
/** * 前序遍历 递归 * @param node */ public void frontOrder_Recursion(Node node) { if (node != null) { // 输出中间节点 System.out.print(node.data + " "); // 前序遍历左子树 frontOrder_Recursion(node.leftChild); // 前 4000 序遍历右子树 frontOrder_Recursion(node.rightChild); } } /** * 中序遍历 递归 * * @param node */ public void midOrder_Recursion(Node node) { if (node != null) { // 中序遍历左子树 midOrder_Recursion(node.leftChild); // 输出中间节点 System.out.print(node.data + " "); // 中序遍历右子树 midOrder_Recursion(node.rightChild); } } /** * 后序遍历 递归 * * @param node */ public void rareOrder_Recursion(Node node) { if (node != null) { // 后序遍历左子树 rareOrder_Recursion(node.leftChild); // 后序遍历右子树 rareOrder_Recursion(node.rightChild); // 输出中间节点 System.out.print(node.data + " "); } }
二叉树的遍历(非递归)
/** * 前序遍历 非递归 * * @param node */ public void frontOrder_NonRecursion(Node node) { Stack<Node> nodeStark = new Stack<Node>(); Node curr = node; if (curr != null) { nodeStark.push(curr); while (!nodeStark.isEmpty()) { curr = nodeStark.pop(); System.out.print(curr.data + " "); if (curr.rightChild != null) nodeStark.push(curr.rightChild); if (curr.leftChild != null) { nodeStark.push(curr.leftChild); } } } } /** * 中序遍历 非递归 * * @param node */ public void midOrder_NonRecursion(Node node) { Stack<Node> nodeStark = new Stack<Node>(); Node curr = node; while (curr != null) { while (curr != null) { if (curr.rightChild != null) nodeStark.push(curr.rightChild); nodeStark.push(curr); curr = curr.leftChild; } curr = nodeStark.pop(); while (!nodeStark.isEmpty() && curr.rightChild == null) { System.out.print(curr.data + " "); curr = nodeStark.pop(); } System.out.print(curr.data + " "); if (curr.rightChild != null) { curr = nodeStark.pop(); } else { return; } } } /** * 中序遍历2 非递归 * * @param node */ public static void midOrder_NonRecursion2(Node t) { Stack<Node> s = new Stack<Node>(); while (t != null || !s.empty()) { while (t != null) { s.push(t); t = t.leftChild; } if (!s.empty()) { t = s.pop(); System.out.print(t.data + " "); t = t.rightChild; } } } /** * 后续遍历 非递归 单栈 * * @param p */ public void rareOrder_NonRecursion_SingleStack(Node p) { Stack<Node> stack = new Stack<Node>(); Node node = p; while (p != null) { // 左子树入栈 for (; p.leftChild != null; p = p.leftChild) { stack.push(p); } // 当前结点无右子树或右子树已经输出 while (p != null && (p.rightChild == null || p.rightChild == node)) { System.out.print(p.data + " "); // 纪录上一个已输出结点 node = p; if (stack.empty()) return; p = stack.pop(); } // 处理右子树 stack.push(p); p = p.rightChild; } } /** * 后续遍历 非递归 双栈 * * @return */ public void rareOrder_NonRecursion_DoubleStack(Node node) { Stack<Integer> flags = new Stack<Integer>(); Stack<Node> nodeStark = new Stack<Node>(); Integer i = new Integer(1); while (node != null || !nodeStark.isEmpty()) { while (node != null) { nodeStark.push(node); flags.push(0); node = node.leftChild; } while (!nodeStark.isEmpty() && flags.peek().equals(i)) { System.out.print(nodeStark.pop().data + " "); flags.pop(); } if (!nodeStark.isEmpty()) { node = nodeStark.peek(); flags.pop(); flags.push(1); node = node.rightChild; } } }
层序遍历(非递归)
/** * 层序遍历 * 非递归 * @param node */ public void levelorder_NonRecursion(Node node) { LinkedList<Node> linkedList = new LinkedList<Node>(); Node curr = root; if(root == null) return; else linkedList.offer(node); while(!linkedList.isEmpty()){ curr = linkedList.remove(); System.out.print(curr.data + " "); if(curr.leftChild != null){ linkedList.offer(curr.leftChild); } if(curr.rightChild != null){ linkedList.offer(curr.rightChild); } } }
删除节点
/** * 删除节点 * @param value * @return */ public boolean deleteNode(int value){ //引用当前节点,从根节点开始 Node curr = root; //应用当前节点的父节点 Node parentNode = root; //是否为左节点 boolean isLeftChild = true; //进行比较,查找是否存在要删除的节点 while(curr.data != value){ parentNode = curr; if(curr.data > value){ curr = curr.leftChild; isLeftChild = true; }else { curr = curr.rightChild; isLeftChild = false; } //如果查找不到 if(curr == null) { return false; } } //刪除叶子节点 if(curr.leftChild == null && curr.rightChild == null){ if(curr == root) { root = null; } else if(isLeftChild) { parentNode.leftChild = null; } else { parentNode.rightChild = null; } }else if(curr.leftChild == null){//删除节点的左节点为空 if(curr == root){ root = root.rightChild; }else if(isLeftChild) { parentNode.leftChild = curr.rightChild; }else { parentNode.rightChild = curr.rightChild; } }else if (curr.rightChild == null) {//删除节点的右节点为空 if(curr == root){ root = root.leftChild; }else if(isLeftChild) { parentNode.leftChild = curr.leftChild; }else { parentNode.rightChild = curr.leftChild; } }else {//如果要删除的节点有左右两个子节点 Node successor = getSuccessor(curr); if(curr == root){ root = successor; }else if(isLeftChild){ parentNode.leftChild = successor; }else { parentNode.rightChild = successor; } successor.leftChild = curr.leftChild; } return true; } /** * 获取要删除节点的中序后继节点 * @param delNode * @return */ public Node getSuccessor(Node delNode) { Node successor = delNode; Node successorParent = delNode; Node curr = delNode.rightChild; while(curr != null){ successorParent = successor; successor = curr; curr = curr.leftChild; } if(successor != delNode.rightChild){ successorParent.leftChild = successor.rightChild; successor.rightChild = delNode.rightChild; } return successor; }
相关文章推荐
- 二叉树:实现java操作二叉排序树(生成、插入、遍历、删除)
- javascript实现二叉树的创建,遍历,添加,查找最大值最小值和指定值的寻找及删除功能——递归的多次运用
- 二叉树(插入,删除,遍历等)java实现
- 数据结构二叉树的java实现,包括二叉树的创建、搜索、删除和遍历
- java实现二叉树及遍历、删除
- [算法]Java 实现 简单MyNode类型 无序链表 递归 添加 删除 遍历
- Java实现二叉树的创建、删除、遍历
- 二叉树的建立删除及三种遍历实现
- 并发遍历二叉树 Java 实现
- Java实现数组的添加、删除、查找(基础型)
- java 控制表项删除、编辑、添加(实现接口)
- java实现二叉树的先序、中序、后序遍历
- Java实现二叉树的多种遍历
- 实现二叉树的层序遍历,说说Java中的队列结构(实现一个Java的队列)
- java实现的二叉树(前序、中序、后序)递归和非递归遍历,包含层序遍历
- ArrayList利用迭代器Iterator遍历方法实现数据(新闻)的删除、添加、显示功能例子
- 二叉树的遍历(Java实现)
- java实现B树(二叉树)插入,删除
- JAVA实现二叉树及递归遍历二叉树
- 根据前序遍历和中序遍历重建二叉树的Java实现