#数据结构—二叉搜索树
1.什么是树:
一种非线性的数据结构
一个结点只有一个父节点,零个或多个子节点;除了父节点以外每个结点只有一个父节点,并且兄弟结点不相:
结点的度:每个结点所拥有子树的数目;
兄弟结点:有相同父节点的结点;
树的度:最大度结点,的度叫做树的度;
树的深度:根到叶子节点的所连的边的数目,
数的高度:树的深度反过来;
树的层数:树的深度+1;
2.二叉树:
除了叶子节点以外,每个结点最多有两个子树;
二叉搜索树: 每个结点的左子树都比该节点小,每个结点的右子树都比该节点大;
首先二叉搜索树的结点插入:
思路:以当前节点为根节点为节点;
public void add(E e) {
root=add(root,e);
}
private Node add(Node root,E e){
if(root==null){
size++;
return new Node(e);
}
if((e.compareTo(root.e))<0){
root.left=add(root.left,e);
}
if((e.compareTo(root.e))>0){
root.right=add(root.right,e);
}
return root;
}
查找当前数是否有指定的结点
public boolean contains(E e) {
return contains(root,e);
}
private boolean contains(Node root,E e){
if(root==null){
return false;
}
if(root.e.equals(e)){
return true;
}else if((e.compareTo(root.e))<0){
return contains(root.left,e);
}else {
return contains(root.right,e);
}
}
找到最小的结点
public E removeMin() {
if (root==null)
return null;
root=removeMin(root);
return root.e;
}
private Node removeMin(Node root){
if(root.left==null){
if (root.right!=null){
Node temp=root.right;
root.right=null;
size--;
return temp;
}
}
root.right=removeMax(root.right);
return root;
}
public E removeMax() {
if(root==null){
return null;
}
root=removeMax(root);
return root.e;
}
private Node removeMax(Node root){
if(root.right==null){
if (root.left!=null){
Node temp=root.left;
root.left=null;
size--;
return temp;
}
}
root.left=removeMax(root.left);
return root;
}
删除最小结点
public E removeMin() {
if(root==null){
return null;
}
return removeMin(root.left).e;
}
//返回最小结点
private Node removeMin(Node root){
//如果当前节点的左子树为空,说明找到了要删除的结点;
if(root.left==null){
//保存当前节点的右子树
Node temp=root.right;
//将当前节点的右数置为空
root.right=null;
size--;
//返回当前节点
return temp;
}
//将返回的结点连在子树上
root.left=removeMin(root.left);
//返回结点
return root;
}
删除最大结点 和删除最小节点的逻辑一样
public E removeMax() {
if(root==null){
return null;
}
return removeMax(root).e;
}
private Node removeMax(Node root){
//如果当前节点的右子树为空,说明找到了要删除的结点;
if(root.right==null){
//保存当前节点的左子树
Node temp=root.right;
//将当前节点的左子树为空
root.right=null;
size--;
return temp;
}
//连上最新的子树;
root.right=removeMax(root.right);
return root;
}
删除指定结点:
public void remove(E e) {
root=remove(root,e);
}
private Node remove(Node root,E e){
if (root==null){
return null;
}
if(root.e.equals(e)){
if(root.left==null){
Node right=root.right;
root.right=null;
size--;
return right;
}
if(root.right==null){
Node left=root.left;
root.left=null;
size--;
return left;
}
if(root.left!=null&&root.right!=null){
Node s=findMin(root.right);
s.right=removeMin(root.right);
s.left=root.left;
size--;
return s;
}
}else if((e.compareTo(root.e))<0){
root=remove(root.left,e);
return root;
}else {
root=remove(root.right,e);
return root;
}
return root;
}
前驱结点,比当前结点小的子树的最大结点;
后继结点,比当前节点大的子树的最大结点;
树的前序遍历
public void preOrder() {
preOrder(root);
}
private void preOrder(Node root){
if(root==null){
return;
}
//第一次访问根节点就输出根节点先输出根节点
System.out.println(root.e);
//向左树递归
preOrder(root.left);
//向右树递归
preOrder(root.right);
}
中序遍历
public void inOrder() {
inOrder(root);
}
private void inOrder(Node root){
if(root==null){
return ;
}
inOrder(root.left);
//第二次访问根节点的时候输出
System.out.println(root.e);
inOrder(root.right);
}
后序遍历
@Override
public void postOrder() {
postOrder(root);
}
private void postOrder(Node root){
if(root==null){
return;
}
postOrder(root.left);
postOrder(root.right);
//第三次访问结点的时候输出
System.out.println(root.e);
}
层序遍历:所有广度优先遍历使用队列来进行迭代输出
public void levelOrder() {
if(root==null){
return;
}
//将当前节点入队
LinkedList<Node> queue=new LinkedList<>();
queue.add(root);
//当结点不为空,说明不断有结点入队
while(!queue.isEmpty()){
//将队头结点出队
Node temp=queue.poll();
//输出当前节点
System.out.println(temp.e);
//如果左子树不为空,入队
if(temp.left!=null){
queue.add(root.left);
}
//如果右子树不为空,入队
if(temp.right!=null){
queue.add(root.right);
}
}
}