版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_32768743/article/details/81454961
看《算法》的一点记录,看原书最好理解,一般看一遍是理解不了的,哈哈,博客什么的都写得不好,这里抄抄,那里抄抄,很少有精品。什么时候也去看看《算法导论》就好。
使用的数据结构 | 实现 | 优点 | 缺点 |
---|---|---|---|
链表(顺序查找) | SequentialSearchST | 适用于小型问题 | 对于大型符号表很慢 |
有序数组(二分查找) | BinarySearchST | 最优的查找效率和空间需求,能够进行有序性相关的操作 | 插入操作很慢 |
二叉查找树 | BST | 实现简单,能够进行有序性相关的操作 | 没有性能上界的保证,链接需要额外的空间 |
平衡二叉查找树 | RedBlackBST | 最优的查找和插入效率,能够进行有序性相关的操作 | 链接需要额外的空间 |
散列表 | SeparateChainHashST,LinearProbingHashST | 能够快速地查找和插入常见类型的数据 | 需要计算每种类型的数据的散列,无法进行有序性相关的操作,链接和空结点需要额外的空间 |
简单的符号表实现的成本总结
算法(数据结构) | 最坏查找 | 最坏插入 | 平均查找命中 | 平均插入 | 是否支持有序性相关的操作 |
---|---|---|---|---|---|
顺序查询(无序链表) | N | N |
|
N | 否 |
二分查找(有序数组) |
|
N |
|
|
是 |
二叉树查找(二叉查找树) | N | N |
|
|
是 |
2-3树查找(红黑树) |
|
|
|
|
是 |
符号表的内存使用
方法 | N个元素所需的内存(引用类型) |
---|---|
基于拉链法的散列表 | ~48N+32M |
基于线性探测的散列表 | 在~32N和~128N之间 |
各种二叉查找树 | ~56N |
附:
符号表
package cn.net.pikachu;
public interface ST<Key, Value> {
void put(Key key, Value val);
Value get(Key key);
default void delete(Key key) {
put(key, null);
}
default boolean contains(Key key) {
return get(key) != null;
}
default boolean isEmpty() {
return size() == 0;
}
int size();
Iterable<Key> keys();
}
有序符号表
package cn.net.pikachu;
public interface OrderedST<Key extends Comparable<Key>, Value> {
void put(Key key, Value val);
Value get(Key key);
default void delete(Key key) {
put(key, null);
}
default boolean contains(Key key) {
return get(key) != null;
}
default boolean isEmpty() {
return size() == 0;
}
int size();
Key min();
Key max();
Key floor(Key key);
Key ceiling(Key key);
int rank(Key key);
Key select(int k);
default void deleteMin() {
delete(min());
}
default void deleteMax() {
delete(max());
}
default int size(Key lo, Key hi) {
if (hi.compareTo(lo) < 0) {
return 0;
} else if (contains(hi)) {
return rank(hi) - rank(lo) + 1;
} else {
return rank(hi) - rank(lo);
}
}
;
Iterable<Key> key(Key lo, Key hi);
default Iterable<Key> keys() {
return key(min(), max());
}
;
}
无序链表中的顺序查找
package cn.net.pikachu;
public class SequentialSearchST<Key, Value> implements ST<Key, Value> {
private Node first;
private class Node {
Key key;
Value val;
Node next;
public Node(Key key, Value val, Node next) {
this.key = key;
this.val = val;
this.next = next;
}
}
@Override
public void put(Key key, Value val) {
for (Node x = first; x != null; x = x.next) {
if (key.equals(x.key)) {
x.val = val;
}
}
first = new Node(key, val, first);
}
@Override
public Value get(Key key) {
for (Node x = first; x != null; x = x.next) {
if (key.equals(x.key)) {
return x.val;
}
}
return null;
}
@Override
public int size() {
return 0;
}
@Override
public Iterable<Key> keys() {
return null;
}
}
有序数组中的二分查找
package cn.net.pikachu;
import java.util.ArrayDeque;
import java.util.Arrays;
import java.util.Queue;
public class BinarySearchST<Key extends Comparable<Key>, Value> implements OrderedST<Key, Value> {
private Key[] keys;
private Value[] vals;
private int N;
public BinarySearchST(int capacity) {
keys = (Key[]) new Comparable[capacity];
vals = (Value[]) new Object[capacity];
}
@Override
public void put(Key key, Value val) {
int i = rank(key);
if (i < N && keys[i].compareTo(key) == 0) {
vals[i] = val;
return;
}
for (int j = N; j > i; j--) {
keys[j] = keys[j - 1];
vals[j] = vals[j - 1];
}
keys[i] = key;
vals[i] = val;
N++;
}
@Override
public Value get(Key key) {
if (isEmpty()) {
return null;
}
int i = rank(key);
if (i < N && keys[i].compareTo(key) == 0) {
return vals[i];
}
return null;
}
@Override
public int size() {
return N;
}
@Override
public Key min() {
return keys[0];
}
@Override
public Key max() {
return keys[N - 1];
}
@Override
public Key floor(Key key) {
return null;
}
@Override
public Key ceiling(Key key) {
int i = rank(key);
return keys[i];
}
@Override
public int rank(Key key) {
int lo = 0;
int hi = N - 1;
while (lo <= hi) {
int mid = lo + (hi - lo) / 2;
int cmp = key.compareTo(keys[mid]);
if (cmp < 0) {
hi = mid - 1;
} else if (cmp > 0) {
lo = mid + 1;
} else {
return mid;
}
}
return lo;
}
@Override
public Key select(int k) {
return keys[k];
}
@Override
public Iterable<Key> key(Key lo, Key hi) {
Queue<Key> q = new ArrayDeque<>(Arrays.asList(keys).subList(rank(lo), rank(hi)));
if (contains(hi)) {
q.add(hi);
}
return q;
}
}
二叉查找树
package cn.net.pikachu;
import java.util.Queue;
public class BST<Key extends Comparable<Key>, Value> implements OrderedST<Key, Value> {
private Node root;
private class Node {
private Key key;
private Value val;
private Node left, right;
private int N;
public Node(Key key, Value val, int n) {
this.key = key;
this.val = val;
N = n;
}
}
@Override
public void put(Key key, Value val) {
root = put(root, key, val);
}
private Node put(Node x, Key key, Value val) {
if (x == null) {
return new Node(key, val, 1);
}
int cmp = key.compareTo(x.key);
if (cmp < 0) {
x.left = put(x.left, key, val);
} else if (cmp > 0) {
x.right = put(x.right, key, val);
} else {
x.val = val;
}
x.N = size(x.left) + size(x.right) + 1;
return x;
}
@Override
public Value get(Key key) {
return get(root, key);
}
private Value get(Node x, Key key) {
if (x == null) {
return null;
}
int cmp = key.compareTo(x.key);
if (cmp < 0) {
return get(x.left, key);
} else if (cmp > 0) {
return get(x.right, key);
} else {
return x.val;
}
}
@Override
public int size() {
return size(root);
}
private int size(Node x) {
if (x == null) {
return 0;
} else {
return x.N;
}
}
@Override
public Key min() {
return min(root).key;
}
private Node min(Node x) {
if (x.left == null) {
return x;
} else {
return min(x.left);
}
}
@Override
public Key max() {
return max(root).key;
}
private Node max(Node x) {
if (x.right == null) {
return x;
} else {
return max(x.right);
}
}
@Override
public Key floor(Key key) {
Node x = floor(root, key);
if (x == null) {
return null;
}
return x.key;
}
private Node floor(Node x, Key key) {
if (x == null) {
return null;
}
int cmp = key.compareTo(x.key);
if (cmp == 0) {
return x;
} else if (cmp < 0) {
return floor(x.left, key);
}
Node t = floor(x.right, key);
if (t != null) {
return t;
} else {
return x;
}
}
@Override
public Key ceiling(Key key) {
return null;
}
@Override
public int rank(Key key) {
return rank(key, root);
}
private int rank(Key key, Node x) {
if (x == null) {
return 0;
}
int cmp = key.compareTo(x.key);
if (cmp < 0) {
return rank(key, x.left);
} else if (cmp > 0) {
return 1 + size(x.left) + rank(key, x.right);
} else {
return size(x.left);
}
}
@Override
public Key select(int k) {
return select(root, k).key;
}
private Node select(Node x, int k) {
if (x == null) {
return null;
}
int t = size(x.left);
if (t > k) {
return select(x.left, k);
} else if (t < k) {
return select(x.right, k - t - 1);
} else {
return x;
}
}
@Override
public Iterable<Key> key(Key lo, Key hi) {
return null;
}
private void keys(Node x, Queue<Key> queue, Key lo, Key hi) {
if (x == null) {
return;
}
int cmplo = lo.compareTo(x.key);
int cmphi = hi.compareTo(x.key);
if (cmplo < 0) {
keys(x.left, queue, lo, hi);
}
if (cmplo <= 0 && cmphi >= 0) {
queue.add(x.key);
}
if (cmphi > 0) {
keys(x.right, queue, lo, hi);
}
}
@Override
public void deleteMin() {
root = deleteMin(root);
}
private Node deleteMin(Node x) {
if (x.left == null) {
return x.right;
}
x.left = deleteMin(x.left);
x.N = size(x.left) + size(x.right) + 1;
return x;
}
public void delete(Key key) {
}
private Node delete(Node x, Key key) {
if (x == null) {
return null;
}
int cmp = key.compareTo(x.key);
if (cmp < 0) {
x.left = delete(x.left, key);
} else if (cmp > 0) {
x.right = delete(x.right, key);
} else {
if (x.right == null) {
return x.left;
}
if (x.left == null) {
return x.right;
}
Node t = x;
x = min(t.right);
x.right = deleteMin(t.right);
x.left = t.left;
}
x.N = size(x.left) + size(x.right) + 1;
return x;
}
}
红黑二叉查找树
package cn.net.pikachu;
public class RedBlackBST<Key extends Comparable<Key>, Value> implements OrderedST<Key, Value> {
private static final boolean RED = true;
private static final boolean BLACK = false;
private Node root;
private class Node {
public Node left;
public Node right;
public Value val;
public Key key;
int N;
boolean color;
public Node(Key key, Value val, int n, boolean color) {
this.val = val;
this.key = key;
N = n;
this.color = color;
}
}
private boolean isRed(Node x) {
if (x == null) {
return false;
}
return x.color = RED;
}
private Node rotateLeft(Node h) {
Node x = h.right;
h.right = x.left;
x.left = h;
x.color = h.color;
h.color = RED;
x.N = h.N;
h.N = 1 + size(h.left) + size(h.right);
return x;
}
private Node rotateRight(Node h) {
Node x = h.left;
h.left = x.right;
x.right = h;
x.color = h.color;
h.color = RED;
x.N = h.N;
h.N = 1 + size(h.left) + size(h.right);
return x;
}
private void flipColors(Node h) {
h.color = RED;
h.left.color = BLACK;
h.right.color = BLACK;
}
@Override
public void put(Key key, Value val) {
root = put(root, key, val);
root.color = BLACK;
}
private Node put(Node h, Key key, Value val) {
if (h == null) {
return new Node(key, val, 1, RED);
}
int cmp = key.compareTo(h.key);
if (cmp < 0) {
h.left = put(h.left, key, val);
} else if (cmp > 0) {
h.right = put(h.right, key, val);
} else {
h.val = val;
}
if (isRed(h.right) && !isRed(h.left)) {
h = rotateLeft(h);
}
if (isRed(h.left) && isRed(h.left.left)) {
h = rotateRight(h);
}
if (isRed(h.left) && isRed(h.right)) {
flipColors(h);
}
h.N = size(h.left) + size(h.right) + 1;
return h;
}
@Override
public Value get(Key key) {
return null;
}
@Override
public int size() {
return 0;
}
private int size(Node x) {
return 0;
}
@Override
public Key min() {
return null;
}
@Override
public Key max() {
return null;
}
@Override
public Key floor(Key key) {
return null;
}
@Override
public Key ceiling(Key key) {
return null;
}
@Override
public int rank(Key key) {
return 0;
}
@Override
public Key select(int k) {
return null;
}
@Override
public Iterable<Key> key(Key lo, Key hi) {
return null;
}
}
基于线性探测的散列表
package cn.net.pikachu;
public class LinearProbingHashST<Key, Value> implements ST<Key, Value> {
private int N;
private int M = 16;
private Key[] keys;
private Value[] vals;
public LinearProbingHashST() {
keys = (Key[]) new Object[M];
vals = (Value[]) new Object[M];
}
public LinearProbingHashST(int m) {
M = m;
keys = (Key[]) new Object[M];
vals = (Value[]) new Object[M];
}
private int hash(Key key) {
return (key.hashCode() & 0x7fffffff) % M;
}
private void resize() {
}
private void resize(int cap) {
LinearProbingHashST<Key, Value> t;
t = new LinearProbingHashST<Key, Value>(cap);
for (int i = 0; i < M; i++) {
if (keys[i] != null) {
t.put(keys[i], vals[i]);
}
}
keys = t.keys;
vals = t.vals;
M = t.M;
}
@Override
public void put(Key key, Value val) {
if (N >= M / 2) {
resize(2 * M);
}
int i;
for (i = hash(key); keys[i] != null; i = (i + 1) % M) {
if (keys[i].equals(key)) {
vals[i] = val;
return;
}
}
keys[i] = key;
vals[i] = val;
N++;
}
@Override
public Value get(Key key) {
for (int i = hash(key); keys[i] != null; i = (i + 1) % M) {
if (keys[i].equals(key)) {
return vals[i];
}
}
return null;
}
@Override
public int size() {
return 0;
}
@Override
public Iterable<Key> keys() {
return null;
}
@Override
public void delete(Key key) {
if (!contains(key)) {
return;
}
int i = hash(key);
while (!key.equals(keys[i])) {
i = (i + 1) % M;
}
keys[i] = null;
vals[i] = null;
i = (i + 1) % M;
while (keys[i] != null) {
Key keyToRedo = keys[i];
Value valToRedo = vals[i];
keys[i] = null;
vals[i] = null;
N--;
put(keyToRedo, valToRedo);
i = (i + 1) % M;
}
N--;
if (N > 0 && N == M / 8) {
resize(M / 2);
}
}
}
基于拉链法的散列表
package cn.net.pikachu;
public class SeparateChainingHashST<Key, Value> implements ST<Key, Value> {
private int N;
private int M;
private SequentialSearchST<Key, Value>[] st;
public SeparateChainingHashST(int m) {
M = m;
st = (SequentialSearchST<Key, Value>[]) new SequentialSearchST[M];
for (int i = 0; i < M; i++) {
st[i] = new SequentialSearchST();
}
}
private int hash(Key key) {
return (key.hashCode() & 0x7fffffff) % M;
}
@Override
public void put(Key key, Value val) {
st[hash(key)].put(key, val);
}
@Override
public Value get(Key key) {
return st[hash(key)].get(key);
}
@Override
public int size() {
return 0;
}
@Override
public Iterable<Key> keys() {
return null;
}
}