目录
搜索二叉树的概念
二叉树左边的值小与根节点,右边的值大于根节点。
左树<根节点<右树
这样也大大提升了我们代码搜索的效率
这时通过中序遍历得到一个有序的数组。
二叉树搜索模拟实现
搜索二叉树查找
public boolean search(int val){
TreeNode cur=this.root;
while(cur!=null){
if(val>cur.val){
cur=cur.right;
}else if(val<cur.val){
cur=cur.left;
}else{
return true;
}
}
return false;
}
搜索二叉树插入
public boolean insert(int val){
if(this.root==null){
//root为空情况下
this.root=new TreeNode(val);
return true;
}
TreeNode cur=this.root;
//定义一个值来接收前一个父亲节点值
TreeNode parent=null;
while(cur!=null){
parent=cur;
if(cur.val>val){
parent=cur;
cur=cur.left;
} else if (cur.val< val) {
parent=cur;
cur=cur.right;
}else{
//不需两个相同元素存在
return false;
}
}
TreeNode node=new TreeNode(val);
if(parent.val>val){
//插入左边
parent.left=node;
}else{
parent.right=node;
}
return true;
}
搜索二叉树删除
public void removeThisNode(TreeNode cur,TreeNode parent){
if(cur.left==null){
//如果cur根节点为要删除的节点,直接将root指向cur.right
if(cur==this.root){
this.root=cur.right;
} else if (cur==parent.left) {
parent.left=cur.right;
}else{
parent.right=cur.right;
}
} else if (cur.right==null) {
if(cur==root){
this.root=cur.left;
} else if (cur==parent.left) {
parent.left=cur.left;
}else{
parent.right=cur.left;
}
}else{
TreeNode targetParent=cur;
TreeNode target=cur.right;
while(target.left!=null){
targetParent=target;
target=target.left;
}
//cur的值被target覆盖掉
cur.val=target.val;
//这里target的指向修改
if(targetParent.left==target){
targetParent.left=target.right;
}else{
targetParent.right=target.right;
}
}
}
HashMap 和HashSet的定义
hashCode(开散链法)
二叉搜索树是通过对半切的方式进行比较,类似于我们的二分法查找,但是它的如果是两边的树是平衡时,时间复杂度是O(logN),如果是一棵单分枝树时间复杂度来到O(N)都要进行遍历。
而哈希可以不经过比较,一次性从想要查找的范围内获取到该元素。
如果想要实现,通过哈希函数使元素的存储位置与它的关键码之间能够建立一一映射的关系,通过公式:hash=key(查找的下标)%capacity(容量)如下图所示:
哈希冲突
模拟实现哈希桶(尾叉法)
public class HashBucket {
//内部类
static class Node{
public int key;
public int val;
public Node next;
//内部类构造方法
public Node(int key, int val) {
this.key = key;
this.val = val;
}
}
//申请一个数组
public Node[] array;
int size;//长度
public static final float loadFactor=0.75f;//负载因子的默认值
public HashBucket(){
//构造方法
this.array=new Node[10];
}
//放入元素
public void put(int key,int val){
int index=key%array.length;
Node node=new Node(key,val);
Node preV=null;
//为空
if(this.array[index]==null){
this.array[index]=node;
}else{
//不为空
Node cur=this.array[index];
while(cur!=null){
if(cur.key==key){
cur.val=val;
return;
}
preV=cur;
cur=cur.next;
}
assert preV!=null;
preV.next=node;
}
size++;
if(judgThisLoadFactorFull())
//扩容
grow();
}
//判断是否大于负载因子
public boolean judgThisLoadFactorFull(){
return size*1.0f/array.length>loadFactor;
}
//扩容
private void grow() {
Node[] newArray=new Node[2*array.length];//两倍的扩容
for(int i=0;i<array.length;i++){
Node cur=this.array[i];
Node preV=null;
while(cur!=null){
int index= cur.key%newArray.length;
if(newArray[index]==null){
newArray[index]=cur;
cur=cur.next;
this.array[i]=cur;
newArray[index].next=null;
}else{
Node newCur=newArray[index];
while(newCur!=null){
preV=newCur;
newCur=newCur.next;
}
assert preV!=null;
preV.next=cur;
cur=cur.next;
this.array[i]=cur;
preV.next.next=null;
}
}
}
this.array=newArray;
}
//通过key搜索到值
public int getValByThisKey(int key){
int index=key%this.array.length;
Node cur=this.array[index];
while (cur!=null){
if(cur.key==key){
return cur.val;
}
cur=cur.next;
}
return -1;
}
当我们创建了一个泛型的类型后,生成了hashCode方法,我们生成两个参数相同的对象时,如果将student1放入到hashmap中,当我们想要查找hashmap1中的值时,使用student2也可以查到student1中的值,这里的哈希函数通过计算关键码,因为两者的关键码相同,得到关键码的数值。
Student student1=new Student("12313");
Student student2=new Student("12313");
System.out.println(student1.hashCode());
System.out.println(student2.hashCode());
HashMap<Student,Integer> hashMap=new HashMap<>();
hashMap.put(student1,2);
System.out.println(hashMap.get(student2));
而我们如何自己模拟实现一个自定义类型的哈希桶呢?
接下来我们实现以下
模拟创建泛型哈希桶
这里泛类型哈希桶实现与上述哈希桶实现类似,但是这里注意get方法中的比较关键码是通过equals来判断。
public class HashBucket<K,V>{
static class Node<K,V>{
public K key;
public V val;
public Node<K,V> next;
public Node(K key, V val) {
this.key = key;
this.val = val;
}
}
public Node<K,V>[] array;
public int usedSize;
public static final float DefaultFactor=0.75f;
public HashBucket(){
this.array=(Node<K, V>[]) new Node[10];
}
//放入值
public void put(K key,V val){
int hash=key.hashCode();
int index=hash%array.length;
Node<K,V> cur=array[index];
Node<K,V> node=new Node<>(key,val);
Node<K,V> preV=null;
if(cur==null){
this.array[index]=node;
}else{
while(cur!=null){
if(cur.key==key){
cur.val=val;
}
preV=cur;
cur=cur.next;
}
preV.next=node;
}
usedSize++;
}
//获取值
public V get(K key){
int hash= key.hashCode();
int index=hash % array.length;
Node<K,V> cur=this.array[index];
while(cur!=null){
//这里比较不是==
if(cur.key.equals(key)){
return cur.val;
}
cur=cur.next;
}
return null;
}
}