文章目录
1.集合(Set)
集合:存储不重复元素的容器
有序集合中的元素具有顺序性,基于搜索树实现
无序集合中的元素没有顺序性,基于哈希表实现
顺序性,是指按照元素的大小进行排序,并非指插入的顺序
有序性,是指元素的进场顺序和出场顺序一致
应用场合:
客户统计
词汇量统计
public interface Set<E> {
void add(E e); //向集合中添加元素e(不能添加重复元素)
void remove(E e); //删除集合中指定元素e
boolean contains(E e); //判断是否包含指定元素e
int getSize(); //获取集合中元素的个数
boolean isEmpty(); //判断集合是否为空
}
BSTSet基于二分搜索树实现的集合类定义
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;
import p01.动态数组.Stack;
import p02.动态链表.LinkedStack;
/*
树:元素与元素之间存在一对多的关系 层次关系
根节点 叶子结点 孩子结点 父亲结点
二叉树:就是一种特殊的树结构 元素节点最多有两个孩子节点
二叉树怎么存?动态数组 动态链表
如果用动态数组存一个深度为h的二叉树 最多需要 2^h-1
每一层最多几个节点 2^(h-1)
如果此时的二叉树不是一个平衡二叉树 那么用动态数组存会有很多空间浪费
平衡:
满二叉树:叶子节点的深度差为0 且最后一层全是叶子结点
完全二叉树:是按照每一层从左到右填充节点 叶子节点的深度差<=1
满二叉树一定是完全二叉树
完全二叉树不一定是满二叉树
二分搜索树:就是一颗二叉树 只不过有一些条件限定
目前这个二分搜索树是非平衡!
二叉搜索树 二叉排序树 二叉顺序树
对于二叉树中的每一个结点
其左子树中所有的结点都小于该节点
其右子树中所有的结点都大于该节点
相等怎么处理?不对相等做处理!不能存储重复元素
目前为止 关于O(logn) 二分查找 插入排序 二分搜索树
*/
public class BinarySearchTree<E extends Comparable<E>> { // BST
private class Node {
public E e; // 节点数据域
public Node left, right;
public Node(E e) {
this.e = e;
left = null;
right = null;
}
}
private Node root; // 二分搜索树的根节点
private int size;
public BinarySearchTree() {
root = null;
size = 0;
}
// 获取树中元素的个数
public int size() {
return size;
}
// 判断树是否为空
public boolean isEmpty() {
return size() == 0;
}
// 将元素e添加到树中
public void add(E e) {
// 迭代实现
/*
* if(size()==0){ root=new Node(e); size++; } Node p=root; while(true){
* if(e.compareTo(p.e)==0){ return; }else if(e.compareTo(p.e)>0){
* if(p.right!=null){ p=p.right; }else{ p.right=new Node(e); size++;
* return; } }else{ if(p.left!=null){ p=p.left; }else{ p.left=new
* Node(e); size++; return; } } }
*/
root = add(root, e);
}
// 以node为当前树的根节点,添加元素e并返回该树的根
private Node add(Node node, E e) {
if (node == null) {
size++;
return new Node(e);
}
if (e.compareTo(node.e) > 0) {
node.right = add(node.right, e);
} else if (e.compareTo(node.e) < 0) {
node.left = add(node.left, e);
}
return node;
}
// 查找元素e是否存在于树中
public boolean contains(E e) {
// 迭代实现
/*
* if(size()==0){ return false; } Node p=root; while(p!=null){
* if(e.compareTo(p.e)>0){ p=p.right; }else if(e.compareTo(p.e)<0){
* p=p.left; }else{ return true; } } return false;
*/
return contains(root, e);
}
// 查找以node为根节点的树是否包含元素e
private boolean contains(Node node, E e) {
if (node == null) {
return false;
}
if (e.compareTo(node.e) > 0) {
return contains(node.right, e);
} else if (e.compareTo(node.e) < 0) {
return contains(node.left, e);
} else {
return true;
}
}
// 中序遍历 preOrder前序 postOrder后序
public void inOrder() {
ArrayList<E> list = new ArrayList<E>();
inOrder(root, list);
System.out.println(list);
}
private void inOrder(Node node, ArrayList<E> list) {
if (node == null) {
return;
}
inOrder(node.left, list);
list.add(node.e);
inOrder(node.right, list);
}
// 层序遍历 广度优先遍历
public void levelOrder() {
ArrayList<E> list = new ArrayList<E>();
// 用辅助队列实现层序遍历
Queue<Node> queue = new LinkedList<Node>();
queue.add(root);
while (!queue.isEmpty()) {
Node cur = queue.poll();
list.add(cur.e);
if (cur.left != null) {
queue.add(cur.left);
}
if (cur.right != null) {
queue.add(cur.right);
}
}
System.out.println(list);
}
@Override
public String toString() {
/*StringBuilder sb=new StringBuilder();
generateBSTString(root,0,sb);*/
LinkedList<E> list=new LinkedList<>();
BSTIterator it=new BSTIterator(root);
while(it.hasNext()){
list.addLast(it.next());
}
StringBuilder sb=new StringBuilder();
for(int i=0;i<list.size();i++){
sb.append(list.get(i)+"\n");
}
return sb.toString();
}
private void generateBSTString(Node node, int level,
StringBuilder sb) {
if(node==null){
sb.append(generateDepthString(level)+"null\n");
return;
}
generateBSTString(node.left, level+1, sb);
sb.append(generateDepthString(level)+node.e+"\n");
generateBSTString(node.right, level+1, sb);
}
private String generateDepthString(int level) {
StringBuilder sb=new StringBuilder();
for(int i=0;i<level;i++){
sb.append("--");
}
return sb.toString();
}
// 获取最小值
public E minmum(){
if(size()==0){
throw new IllegalArgumentException("Tree is empty!");
}
return minmun(root).e;
}
// 以node为根节点 查找该树中的最小值
private Node minmun(Node node){
if(node.left==null){
return node;
}
return minmun(node.left);
}
// 获取最大值
public E maxmun(){
if(size()==0){
throw new IllegalArgumentException("Tree is empty!");
}
return maxmum(root).e;
}
private Node maxmum(Node node) {
if(node.right==null){
return node;
}
return maxmum(node.right);
}
// 删除最小值
public E removeMin(){
E e=minmum();
root=removeMin(root);
return e;
}
// 以node为根节点的二分搜索树,在删除最小值之后并返回新树的根
private Node removeMin(Node node) {
if(node.left==null){
Node rightNode=node.right;
node.right=null;
size--;
return rightNode;
}
node.left=removeMin(node.left);
return node;
}
// 删除最大值
public E removeMax(){
E e=maxmun();
root=removeMax(root);
return e;
}
private Node removeMax(Node node){
if(node.right==null){
Node leftNode=node.left;
node.left=null;
size--;
return leftNode;
}
node.right=removeMax(node.right);
return node;
}
public void remove(E e){
root=remove(root,e);
}
// 以node为根 删除指定元素e之后 返回新树的根
private Node remove(Node node,E e){
if(node==null){
return null;
}
if(e.compareTo(node.e)>0){
node.right=remove(node.right,e);
return node;
}else if(e.compareTo(node.e)<0){
node.left=remove(node.left,e);
return node;
}else{
if(node.left==null){
Node rightNode=node.right;
node.right=null;
size--;
return rightNode;
}
if(node.right==null){
Node leftNode=node.left;
node.left=null;
size--;
return leftNode;
}
Node successor=minmun(node.right);
successor.right=removeMin(node.right);
successor.left=node.left;
node.left=node.right=null;
return successor;
}
}
class BSTIterator {
Stack<Node> stack=new LinkedStack<>();
public BSTIterator(Node root) {
Node cur=root;
while(cur!=null){
stack.push(cur);
cur=cur.left;
}
}
public E next() {
Node n=stack.pop();
Node cur=n.right;
while(cur!=null){
stack.push(cur);
cur=cur.left;
}
return n.e;
}
public boolean hasNext() {
return !stack.isEmpty();
}
}
}
public class BSTSet<E extends Comparable<E>> implements Set<E> {
private BinarySearchTree<E> bst;
public BSTSet() {
bst=new BinarySearchTree<>();
}
@Override
public void add(E e) {//O(logn)->O(n)
bst.add(e);
}
@Override
public void remove(E e) {//O(logn)
bst.remove(e);
}
@Override
public boolean contains(E e) {//O(logn)
return bst.contains(e);
}
//O(nlogn)
@Override
public int getSize() {
return bst.size();
}
@Override
public boolean isEmpty() {
return bst.isEmpty();
}
@Override
public String toString() {
return bst.toString();
}
}
LinkedListSet基于链表实现的集合类定义
LinkedList代码在以前写的LinkedList的数据结构中
import p02.动态链表.LinkedList;
//基于链表实现的集合
public class LinkedSet<E> implements Set<E>{
private LinkedList<E> list;
public LinkedSet() {
list=new LinkedList<>();
}
@Override
public void add(E e) { //O(n)
if(!list.contains(e)){
list.addLast(e);//O(1)
}
}
@Override
public void remove(E e) {//O(n)
list.removeElement(e);
}
@Override
public boolean contains(E e) {//O(n)
return list.contains(e);
}
@Override
public int getSize() {
return list.getSize();
}
@Override
public boolean isEmpty() {
return list.isEmpty();
}
}
二分搜索树最坏情况
映射
映射就是存储(键,值)数据对的数据结构(Key,Value)。根据键(Key),寻找
值(Value)
有序映射中的键具有顺序性,基于搜索树实现
无序映射中的键没有顺序性,基于哈希表实现
map接口定义
public interface Map<K,V>{
public void add(K key,V value);
public V remove(K key);
public boolean contains(K key);
public V get(K key);
public void set(K key,V value);
public int getSize();
public boolean isEmpty();
public Set keys(); //返回映射中键的集合
public List values(); //返回映射中值的线性表
}
linkedListMap
package p05.集合与映射;
import p01.动态数组.List;
import p02.动态链表.LinkedList;
//基于动态链表实现的映射
public class LinkedMap<K,V> implements Map<K,V>{
private class Node{
public K key;
public V value;
public Node next;
public Node(K key,V value){
this.key=key;
this.value=value;
next=null;
}
public Node(){
this(null,null);
}
@Override
public String toString() {
return key.toString()+":"+value.toString();
}
}
private Node head;
private int size;
public LinkedMap() {
head=new Node();
size=0;
}
//为了操作方便 写一个辅助函数
private Node getNode(K key){
//迭代
/* Node p=head.next;
while(p!=null){
if(p.key.equals(key)){
return p;
}
p=p.next;
}
return null;*/
return getNode(head.next,key);
}
private Node getNode(Node node, K key) {
if(node==null){
return null;
}
if(node.key.equals(key)){
return node;
}else{
return getNode(node.next,key);
}
}
@Override
public void add(K key, V value) {
Node n=getNode(key);
if(n==null){
n=new Node(key,value);
n.next=head.next;
head.next=n;
size++;
}else{
n.value=value;
}
}
@Override
public V remove(K key) {
Node pre=head;
while(pre.next!=null){
if(pre.next.key.equals(key)){
break;
}
pre=pre.next;
}
if(pre.next!=null){
Node n=pre.next;
pre.next=n.next;
n.next=null;
size--;
return n.value;
}
return null;
}
@Override
public boolean contains(K key) {
return getNode(key)!=null;
}
@Override
public V get(K key) {
Node n=getNode(key);
return n==null?null:n.value;
}
@Override
public void set(K key, V value) {
Node n=getNode(key);
if(n==null){
throw new IllegalArgumentException("元素不存在!");
}
n.value=value;
}
@Override
public int getSize() {
return size;
}
@Override
public boolean isEmpty() {
return size==0;
}
@Override
public Set keys() {
Set<K> set=new LinkedSet<K>();
Node cur=head.next;
while(cur!=null){
set.add(cur.key);
}
return set;
}
@Override
public List values() {
List<V> list=new LinkedList<V>();
Node cur=head.next;
while(cur!=null){
list.addLast(cur.value);
}
return list;
}
}
BSTMap基于二分搜索树实现的映射类定义
package p05.集合与映射;
import p01.动态数组.List;
public class BSTMap<K extends Comparable<K>,V> implements Map<K, V> {
private class Node{
public K key;
public V value;
public Node left,right;
public Node(K key,V value){
this.key=key;
this.value=value;
left=null;
right=null;
}
public Node(){
this(null,null);
}
@Override
public String toString() {
return key.toString()+":"+value.toString();
}
}
private Node root;
private int size;
public BSTMap() {
root=null;
size=0;
}
@Override
public void add(K key, V value) {
root=add(root,key,value);
}
// 以node为根节点,将键值对k-v添加在树中 并返回新树的根
private Node add(Node node,K key,V value){
if(node==null){
size++;
return new Node(key,value);
}
if(key.compareTo(node.key)<0){
node.left=add(node.left,key,value);
}else if(key.compareTo(node.key)>0){
node.right=add(node.right,key,value);
}else{
node.value=value;
}
return node;
}
@Override
public V remove(K key) {
Node n=getNode(root,key);
if(n==null){
return null;
}
root=remove(root,key);
return n.value;
}
private Node remove(Node node,K key){
if(node==null){
return null;
}
if(key.compareTo(node.key)<0){
node.left=remove(node.left, key);
return node;
}else if(key.compareTo(node.key)>0){
node.right=remove(node.right, key);
return node;
}else{//相等
if(node.left==null){
Node rightNode=node.right;
node.right=null;
size--;
return rightNode;
}
if(node.right==null){
Node leftNode=node.left;
node.left=null;
size--;
return leftNode;
}
Node successor=minmum(node.right);
successor.right=removeMin(node.right);
successor.left=node.left;
node.left=node.right=null;
return successor;
}
}
private Node minmum(Node node){
if(node.left==null){
return node;
}else{
return minmum(node.left);
}
}
private Node removeMin(Node node){
if(node.left==null){
Node rightNode=node.right;
size--;
node.right=null;
return rightNode;
}
node.left=removeMin(node.left);
return node;
}
@Override
public boolean contains(K key) {
Node n=getNode(root,key);
return n==null?false:true;
}
@Override
public V get(K key) {
Node n=getNode(root,key);
return n==null?null:n.value;
}
@Override
public void set(K key, V value) {
Node n=getNode(root,key);
if(n==null){
throw new IllegalArgumentException("元素不存在!");
}
n.value=value;
}
@Override
public int getSize() {
return size;
}
@Override
public boolean isEmpty() {
return size==0;
}
@Override
public Set keys() {
Set<K> set=new BSTSet<>();
inOrder(root,set);
return set;
}
private void inOrder(Node node, Set<K> set) {
if(node==null){
return;
}
inOrder(node.left, set);
set.add(node.key);
inOrder(node.right, set);
}
@Override
public List values() {
return null;
}
private Node getNode(Node node,K key){
if(node==null){
return null;
}
if(key.compareTo(node.key)<0){
return getNode(node.left,key);
}else if(key.compareTo(node.key)>0){
return getNode(node.right,key);
}else{
return node;
}
}
}