1.数组存储方式分析
优点:通过下表方式访问元素,速度快。对于有序数组没还可以使用二分查找提高检索速度。
缺点:如果要检索某一个具体值,效率比较低下
2.链式存储方式分析
优点:在一定程度上对数组存储方式进行优化(比如插入一个节点,只需要将插入节点,链接到链表当中可删除的效率也很好)。
缺点:在进行检索时,效率仍然比较低,比如(检索某个数值,需要从头结点开始遍历)
3.树存储方式分析
能提高数据存储,读取的效率,比如利用二叉排序树,既可以保证数据的检索速度。同时也可以保证数据的插入,删除,修改的速度。
1.树有很多种,每个节点最多只能有两个子节点的一种形式称为二叉树
2.二叉树的子节点分为左节点和右节点
3.如果二叉树的所有叶子节点都在最后一层并且总结点数 = 2^n-1,(n为层数),则我们称为满二叉数。
4.如果二叉树的所有叶子节点都在最后一层或者倒数第二层,而且最后一层的叶子节点在左边连续,倒数第二层的叶子节点在右边连续,我们称为完全二叉树。
1、节点类
public class TreeNode {
private TreeNode leftTreeNode;
private TreeNode rightTreeNode;
private Integer value;
public Integer getValue() {
return value;
}
public void setValue(Integer value) {
this.value = value;
}
public TreeNode(Integer value){
this.value = value;
}
public TreeNode getLeftTreeNode() {
return leftTreeNode;
}
public void setLeftTreeNode(TreeNode leftTreeNode) {
this.leftTreeNode = leftTreeNode;
}
public TreeNode getRightTreeNode() {
return rightTreeNode;
}
public void setRightTreeNode(TreeNode rightTreeNode) {
this.rightTreeNode = rightTreeNode;
}
@Override
public String toString() {
return "TreeNode{" +
"leftTreeNode=" + leftTreeNode +
", rightTreeNode=" + rightTreeNode +
", value=" + value +
'}';
}
}
2、二叉树管理类
import java.util.LinkedList;
public class BinaryTree {
// 新建代表整棵树的节点
TreeNode root;
//非递归构建有序二叉树
public void insert(Integer value){
// 新建一个节点
TreeNode newNode = new TreeNode(value);
if(root == null){
root = newNode;
}else{
TreeNode current = root;
TreeNode parentNode;
while(true){
parentNode = current;
if(newNode.getValue() > current.getValue()){
current = current.getRightTreeNode();
if(current == null){
parentNode.setRightTreeNode(newNode);
return;
}
}else {
current = current.getLeftTreeNode();
if(current == null){
parentNode.setLeftTreeNode(newNode);
return;
}
}
}
}
}
//递归构建有序二叉树
public TreeNode insert(TreeNode node,Integer value){
TreeNode newNode = new TreeNode(value);
if(root == null){
return root = newNode;
}
if(newNode.getValue() > node.getValue()){
if(node.getRightTreeNode() == null){
node.setRightTreeNode(newNode);
return root;
}
return insert(node.getRightTreeNode(),value);
}else{
if(node.getLeftTreeNode() == null){
node.setLeftTreeNode(newNode);
return root;
}
return insert(node.getLeftTreeNode(),value);
}
}
//递归先序遍历
public void preOrder(TreeNode node){
if(node == null){
return;
}
System.out.println(" "+node.getValue());
preOrder(node.getLeftTreeNode());
preOrder(node.getRightTreeNode());
}
//递归中序遍历
public void midOrder(TreeNode node){
if(node == null){
return;
}
midOrder(node.getLeftTreeNode());
System.out.println(" "+node.getValue());
midOrder(node.getRightTreeNode());
}
//递归后序遍历
public void lastOrder(TreeNode node){
if(node == null){
return;
}
lastOrder(node.getLeftTreeNode());
lastOrder(node.getRightTreeNode());
System.out.println(" "+node.getValue());
}
//找到要删除的节点
public TreeNode search(TreeNode node,int value){
//递归出口
if(node == null){
return null;
}
if(node.getValue() == value){
return node;
}else if(value < node.getValue()){
if(node.getLeftTreeNode() == null){
return null;
}
return search(node.getLeftTreeNode(),value);
}else {
if(node.getRightTreeNode() == null){
return null;
}
return search(node.getRightTreeNode(),value);
}
}
//查找父节点
public TreeNode searchParent(TreeNode node,int value){
if(node == null){
return null;
}
if(node.getLeftTreeNode() != null && node.getLeftTreeNode().getValue() == value ||
(node.getRightTreeNode() !=null && node.getRightTreeNode().getValue() == value)
){
return node;
}else{
if(node.getLeftTreeNode() != null && value < node.getValue()){
return searchParent(node.getLeftTreeNode(),value);
}else if(node.getRightTreeNode() != null && value > node.getValue()){
return searchParent(node.getRightTreeNode(),value);
}else{
return null;
}
}
}
//查找右子树中的最小值
public int delRightTreeMin(TreeNode node){
TreeNode currentNode = node;
while(currentNode.getLeftTreeNode() != null){
currentNode = currentNode.getLeftTreeNode();
}
//删除
delNode(node,currentNode.getValue());
return currentNode.getValue();
}
//删除
public void delNode(TreeNode node,int value){
// 判断这棵树是否为空
if(node == null){
return;
}
// 找到要删除的节点
TreeNode targetNode = search(node,value);
//判断我们找的的这个节点是否为空
if(targetNode == null){
return;
}
//找到target节点的父节点
TreeNode parent = searchParent(node,value);
if(targetNode.getLeftTreeNode() == null && targetNode.getRightTreeNode() == null){ //删除叶子节点
//判断targeNode节点是parent节点的左子树还是右子树
if(parent.getLeftTreeNode() !=null && parent.getLeftTreeNode().getValue() == value ){
parent.setLeftTreeNode(null);
}else if(parent.getRightTreeNode() !=null && parent.getRightTreeNode().getValue() == value ){
parent.setRightTreeNode(null);
}
}else if(targetNode.getLeftTreeNode() != null && targetNode.getRightTreeNode() != null){ //有两个子树的节点
int MinValue = delRightTreeMin(targetNode.getRightTreeNode());
targetNode.setValue(MinValue);
}else{ //只有一个子树的情况
if(targetNode.getLeftTreeNode() != null){ //判断我们要删除的节点是否有左子节点
if(parent.getLeftTreeNode().getValue() == value){ //判断我们要删除的节点是父节点的左子节点
parent.setLeftTreeNode(targetNode.getLeftTreeNode());
}else {
parent.setRightTreeNode(targetNode.getLeftTreeNode());
}
}else { //判断我们要删除的节点是否有右子节点
if(parent.getLeftTreeNode().getValue() == value){ //判断我们要删除的节点是父节点的左子节点
parent.setLeftTreeNode(targetNode.getRightTreeNode());
}else {
parent.setRightTreeNode(targetNode.getRightTreeNode());
}
}
}
}
//层次遍历
public void levelOrder(TreeNode root){
if(root == null){
return;
}
LinkedList<TreeNode> queue = new LinkedList<>();
TreeNode current = null;
queue.offer(root);
while (!queue.isEmpty()){
current = queue.poll();
System.out.println(current.getValue());
if(current.getLeftTreeNode() != null){
queue.offer(current.getLeftTreeNode());
}
if(current.getRightTreeNode() != null){
queue.offer(current.getRightTreeNode());
}
}
}
}
3、测试类
public class Test {
public static void main(String[] args) {
TreeNode treeNode = new TreeNode(20);
BinaryTree binaryTree = new BinaryTree();
binaryTree.insert(12);
binaryTree.insert(2);
binaryTree.insert(1);
binaryTree.insert(10);
binaryTree.insert(16);
binaryTree.insert(22);
binaryTree.insert(34);
binaryTree.insert(23);
binaryTree.insert(21);
binaryTree.insert(0);
binaryTree.insert(5);
binaryTree.preOrder(binaryTree.root);
binaryTree.delNode(binaryTree.root,16);
System.out.println("---------------------");
binaryTree.levelOrder(binaryTree.root);
}
}