前面我们介绍数组的数据结构,我们知道对于有序数组,查找很快,并介绍可以通过二分法查找,但是想要在有序数组中插入一个数据项,就必须先找到插入数据项的位置,然后将所有插入位置后面的数据项全部向后移动一位,来给新数据腾出空间,平均来讲要移动N/2次,这是很费时的。同理,删除数据也是。
然后我们介绍了另外一种数据结构——链表,链表的插入和删除很快,我们只需要改变一些引用值就行了,但是查找数据却很慢了,因为不管我们查找什么数据,都需要从链表的第一个数据项开始,遍历到找到所需数据项为止,这个查找也是平均需要比较N/2次。
那么我们就希望一种数据结构能同时具备数组查找快的优点以及链表插入和删除快的优点,于是 树 诞生了。
深度为路径长度
A(D(I(N,M(Q,P)),H),C(G,F(J)),B(E(L(O),K)))
//二叉排序树
//我们就希望一种数据结构能同时具备数组查找快的优点以及链表插入和删除快的优点,于是 树 诞生了。
//https://www.cnblogs.com/ysocean/p/8032642.html
//如果我们给二叉树加一个额外的条件,就可以得到一种被称作二叉搜索树(binary search tree)的特殊二叉树。
//二叉搜索树要求:若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为二叉排序树。
//待插入的节点也需要从根节点开始进行比较,小于根节点则与根节点左子树比较,反之则与右子树比较,直到左子树为空或右子树为空,则插入到相应为空的位置
//,在比较的过程中要注意保存父节点的信息 及 待插入的位置是父节点的左子树还是右子树,才能插入到正确的位置。
删除节点
删除节点是二叉搜索树中最复杂的操作,删除的节点有三种情况,前两种比较简单,但是第三种却很复杂。
1、该节点是叶节点(没有子节点)
2、该节点有一个子节点
3、该节点有两个子节点
package LineStructure;
//二叉排序树
//我们就希望一种数据结构能同时具备数组查找快的优点以及链表插入和删除快的优点,于是 树 诞生了。
//https://www.cnblogs.com/ysocean/p/8032642.html
//如果我们给二叉树加一个额外的条件,就可以得到一种被称作二叉搜索树(binary search tree)的特殊二叉树。
//二叉搜索树要求:若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为二叉排序树。
public class LinkedTree<T> extends Object {
Node root;
private class Node {
private int data;
private Node leftChild;
private Node rightChild;
public Node(int data) {
this.data = data;
}
public int getData() {
return data;
}
}
public LinkedTree() {
}
//
public LinkedTree(Node root) {
this.root = root;
}
// get root
public Node getRoot() {
return this.root;
}
// set root
public void setRoot(Node root) {
this.root = root;
}
//待插入的节点也需要从根节点开始进行比较,小于根节点则与根节点左子树比较,反之则与右子树比较,直到左子树为空或右子树为空,则插入到相应为空的位置
//,在比较的过程中要注意保存父节点的信息 及 待插入的位置是父节点的左子树还是右子树,才能插入到正确的位置。
public Boolean insert(int data) {
String error = null;
Node node = new Node(data);
if (root == null) {
root = node;
root.leftChild = null;
root.rightChild = null;
} else {
//start to Search
Node current = root;
//保存一个 parent 用来插入时指定插入点的parent以及叶子节点
Node parent = null;
//searchTree
while (true) {
parent = current; //指定插入点的parent
if(data < current.data) {
current = current.leftChild; //searchLeftTree
if(current == null) {
parent.leftChild = node;//指定插入点的位置
return true;
}
}else {
current = current.rightChild;
if(current == null) {
parent.rightChild = node;//指定插入点的位置
return true;
}
}
}
}
return false;
}
public Boolean delete() {
return null;
}
//查找树 注意并不是遍历 因为是二叉搜索树 所以查找时并不会遍历所有节点
//查找节点的时间取决于这个节点所在的层数,每一层最多有2n-1个节点,总共N层共有2n-1个节点,那么时间复杂度为O(logn),底数为2。
public Node find(int data) {
Node temp = root;
while(temp != null) {
if(temp.data == data) {
return temp;
}else if(data < temp.data) {
temp = temp.leftChild;
}else if(data > temp.data) {
temp = temp.rightChild;
}
}
return null;
}
public void middleOrder(Node current) {
if(current != null) {
middleOrder(current.leftChild);
System.out.println(current.data);
middleOrder(current.rightChild);
}
}
public void preOrder(Node current) {
if(current != null) {
System.out.println(current.data);
preOrder(current.leftChild);
preOrder(current.rightChild);
}
}
public void postOrder(Node current) {
if(current != null) {
postOrder(current.leftChild);
postOrder(current.rightChild);
System.out.println(current.data);
}
}
//查找最大值节点 直接找右子树
public Node findMax() {
Node current = root;
Node maxNode = null;
while(current != null) {
current = current.rightChild;
maxNode = current;
}
return maxNode;
}
//查找最小值 直接找左子树
public Node findMin() {
Node current = root;
//之前的写法 错误 current可能为空
/*while(current != null) {
current = current.leftChild;
}
return current;*/
Node MinNode = null;
while(current != null) {
current = current.leftChild;
MinNode = current;
}
return MinNode;
}
//删除节点
}