目录
二叉排序树
左节点的值小于根节点,右节点的值大于根节点,并且每一个子树都是二叉排序树
二叉排序树的插入
值小于根节点,在左子树进行插入,值大于根节点,在右子树进行插入
public static Node insert(Node head, int value) {
if (head == null) {
return new Node(value);
}
if (value < head.value) {//值比当前根的结点小
head.left = insert(head.left, value);
} else if (value > head.value)
head.right = insert(head.right, value);
return head;
}
二叉排序树的查找
值小于根节点,在左子树进行查找,值大于根节点,在右子树进行查找
public static boolean search(Node head, int value) {
if (head == null)
return false;
if (head.value == value)
return true;
if (head.value < value) {
return search(head.right, value);
} else {
return search(head.left, value);
}
}
二叉排序树的删除
public static Node remove(Node head, int value) {
Node parent = head;
Node cur = head;
while (cur != null) {
if (cur.value == value) {//cur是删除结点
if (cur.left == null) {
if (cur == head) {
head = head.right;
return head;
}
if (cur == parent.left) {
parent.left = cur.right;
return head;
}
if (cur == parent.right) {
parent.right = cur.right;
return head;
}
} else if (cur.right == null) {
if (cur == head) {
head = head.left;
return head;
}
if (cur == parent.left) {
parent.left = cur.left;
return head;
}
if (cur == parent.right) {
parent.right = cur.left;
return head;
}
} else {
Node min = cur.right;
if (min.left == null) {//如果左子树为空,最小的结点就是min
cur.value = min.value;
cur.right = min.right;
return head;
}
while (min.left != null) {
parent = min;
min = min.left;
}
cur.value = min.value;
parent.left = null;
return head;
}
}
if (value > cur.value) {
parent = cur;
cur = cur.right;
} else {
parent = cur;
cur = cur.left;
}
}
return null;
}
Set接口
Set接口和List接口同样继承于Collection集合,Set集合的元素无序且不重复
HashSet集合
HashSet集合是Set接口的实现类,内部是一个哈希表
常用方法
1、插入元素
1、根据hashCode()得到对应的hash值
2、根据hash值找到数组的对应存储位置
3、判断对应位置有没有元素:没有元素就插入当前元素;有元素就比较是否和当前对象的value值相等,相等就不插入,不相等就插入
模拟实现
public class MyHashSet<E> {
static class Node<E> {
int hash;
E value;
Node<E> next;
public Node(E value) {
this.value = value;
}
@Override
public String toString() {
return "Node{" +
"value=" + value +
'}';
}
}
private final float load = 0.75f;
private int count = 0;
Node<E>[] table = new Node[10];
public void add(E value) {
//1、生成hash值
int hash =value.hashCode() % table.length;
//获取hash值对应的数组位置
Node<E> cur = table[hash];
//插入结点 jdk1.8使用尾插,我们使用头插
if (cur == null) {
table[hash] = new Node<>(value);
count++;
resize();
return;
}
while (cur != null) {
if (cur.value.equals(value)) {//如果元素之前已经存在,不插入
return;
}
cur = cur.next;
}
//元素可以插入
Node<E> newnode = new Node<>(value);
newnode.next = table[hash];
table[hash] = newnode;
count++;
//计算负载因子,调整数组长度
resize();
}
private void resize(){
if(count*1.0/table.length>load){//需要调整数组长度
Node<E>[] newtable = new Node[table.length*2];
for (int i = 0; i < table.length; i++) {
Node<E> cur = table[i];
while (cur != null) {
//1、生成hash值
int hash = cur.value.hashCode() % newtable.length;
//2、重新插入结点
Node<E> curNext = cur.next;
cur.next = newtable[hash];
newtable[hash] = cur;
cur = curNext;
}
}
table=newtable;
}
}
public void print(){
for (int i = 0; i < table.length; i++) {
Node<E> cur = table[i];
while (cur != null) {
System.out.println(cur);
cur=cur.next;
}
}
}
}
class Person{
int gae;
String name;
public Person(int gae, String name) {
this.gae = gae;
this.name = name;
}
@Override
public String toString() {
return "Person{" +
"gae=" + gae +
", name='" + name + '\'' +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return gae == person.gae && Objects.equals(name, person.name);
}
@Override
public int hashCode() {
return Objects.hash(gae, name);
}
}
public class TextDemo {
public static void main3(String[] args) {
MyHashSet<Person> myHashSet=new MyHashSet<>();
myHashSet.add(new Person(1,"李四"));
myHashSet.add(new Person(9,"李四"));
myHashSet.add(new Person(10,"李四"));
myHashSet.add(new Person(1,"李四"));
myHashSet.add(new Person(10,"李四"));
myHashSet.print();
}
TreeSet集合
HashSet集合内部使用二叉排序树来存储元素,可以保证没有重复元素
public static void main(String[] args) {
Set<Integer>set=new TreeSet<>();
set.add(1);
set.add(3);
set.add(1);
System.out.println(set);
set.remove(1);
System.out.println(set);
}
总结
1、HashSet可以插入null,TreeSet不可以插入null
2、HashSet和TreeSet的区别
HashSet集合内部是一个哈希表,TreeSet集合内部是一个二叉排序树
TreeSet插入查找的时间复杂度O(log2 N)
HashSet插入查找的时间复杂度O(1)
Collections工具类
集合:集合分为单列集合和双列集合
单列集合Collection:List接口存放的元素:有序且可重复,Set接口存放的元素:无需且不可重复
双列集合Map:存储key-value的键值对
Collections工具类提供了一系列对集合的操作方法
反转---reverse()
public static void main(String[] args) {
List<Integer>list=new ArrayList<>() ;
list.add(1);
list.add(3);
System.out.println(list);
Collections.reverse(list);
System.out.println(list);
}
addAll()---将所有元素插入集合
public static void main(String[] args) {
List<Integer>list=new ArrayList<>() ;
Collections.addAll(list,1,3,2,4,5);
System.out.println(list);
}
sort()---对集合的元素进行排序
public static void main(String[] args) {
List<Integer>list=new ArrayList<>() ;
list.add(3);
list.add(1);
System.out.println(list);
Collections.sort(list);
System.out.println(list);
}
swap()---交换集合内两个下标的元素
public static void main(String[] args) {
List<Integer>list=new ArrayList<>() ;
list.add(3);
list.add(1);
System.out.println(list);
Collections.swap(list,0,1);
System.out.println(list);
}
返回最值max(),min()
public static void main(String[] args) {
List<Integer>list=new ArrayList<>() ;
list.add(3);
list.add(1);
System.out.println(list);
System.out.println(Collections.max(list));
System.out.println(Collections.min(list));
}
shuffle()---打乱元素顺序
public static void main(String[] args) {
List<Integer>list=new ArrayList<>() ;
list.add(3);
list.add(1);
list.add(1);
Collections.shuffle(list);
System.out.println(list);
}
replaceAll()---使用新的值替换全部旧的元素值
public static void main(String[] args) {
List<Integer>list=new ArrayList<>() ;
list.add(3);
list.add(1);
list.add(1);
Collections.replaceAll(list,1,9);
System.out.println(list);
}