《算法》第三章部分程序 part 3
▶ 书中第三章部分程序,加上自己补充的代码,红黑树
● 红黑树,大部分方法与注释与二叉树相同
package package01; import java.util.NoSuchElementException;
import edu.princeton.cs.algs4.Queue;
import edu.princeton.cs.algs4.StdIn;
import edu.princeton.cs.algs4.StdOut; public class class01<Key extends Comparable<Key>, Value>
{
private static final boolean RED = true;
private static final boolean BLACK = false; private class Node
{
private Key key;
private Value val;
private Node left, right;
private boolean color; // 指向该节点的连接的颜色
private int size; public Node(Key key, Value val, boolean color, int size)
{
this.key = key;
this.val = val;
this.color = color;
this.size = size;
}
} private Node root; public class01() {} private boolean isRed(Node x)
{
if (x == null)
return false;
return x.color == RED;
} public int size()
{
return size(root);
} private int size(Node x)
{
if (x == null)
return 0;
return x.size;
} public boolean isEmpty()
{
return size() == 0; //return root == null;
} public Value get(Key key) // 查找
{
if (key == null)
throw new IllegalArgumentException("\n<get> key == null.\n");
return getKernel(root, key);
} private Value getKernel(Node x, Key key)// 查找内核,使用了非递归实现
{
for (int cmp = key.compareTo(x.key); x != null; cmp = key.compareTo(x.key))
{
if (cmp < 0)
x = x.left;
else if (cmp > 0)
x = x.right;
else
return x.val;
}
return null;
} public boolean contains(Key key) // 判断 key 是否在树中
{
if (key == null)
throw new IllegalArgumentException("\n<contains> key == null.\n");
return get(key) != null;
} public void put(Key key, Value val) // 插入
{
if (key == null)
throw new IllegalArgumentException("\n<put> key == null.\n");
if (val == null)
delete(key);
else
{
root = putKernel(root, key, val);
root.color = BLACK;
}
// assert check();
} private Node putKernel(Node x, Key key, Value val)
{
if (x == null)
return new Node(key, val, RED, 1);
int cmp = key.compareTo(x.key);
if (cmp < 0)
x.left = putKernel(x.left, key, val);
else if (cmp > 0)
x.right = putKernel(x.right, key, val);
else
x.val = val;
if (isRed(x.right) && !isRed(x.left))
x = rotateLeft(x);
if (isRed(x.left) && isRed(x.left.left))
x = rotateRight(x);
if (isRed(x.left) && isRed(x.right))
flipColors(x);
x.size = 1 + size(x.left) + size(x.right);
return x;
} public void deleteMin()
{
if (isEmpty())
throw new NoSuchElementException("\n<deleteMin> underflow.\n");
if (!isRed(root.left) && !isRed(root.right))
root.color = RED;
root = deleteMinKernel(root);
if (!isEmpty())
root.color = BLACK;
// assert check();
} private Node deleteMinKernel(Node x)
{
if (x.left == null)
return null;
if (!isRed(x.left) && !isRed(x.left.left))
x = moveRedLeft(x);
x.left = deleteMinKernel(x.left);
return balance(x);
} public void deleteMax()
{
if (isEmpty())
throw new NoSuchElementException("\n<deleteMax> underflow.\n");
if (!isRed(root.left) && !isRed(root.right))
root.color = RED;
root = deleteMaxKernel(root);
if (!isEmpty())
root.color = BLACK;
// assert check();
} private Node deleteMaxKernel(Node x)
{
if (isRed(x.left))
x = rotateRight(x);
if (x.right == null)
return null;
if (!isRed(x.right) && !isRed(x.right.left))
x = moveRedRight(x);
x.right = deleteMaxKernel(x.right);
return balance(x);
} public void delete(Key key)
{
if (key == null)
throw new IllegalArgumentException("\n<delete> key == null.\n");
if (!contains(key))
return;
if (!isRed(root.left) && !isRed(root.right))
root.color = RED;
root = deleteKernel(root, key);
if (!isEmpty())
root.color = BLACK;
// assert check();
} private Node deleteKernel(Node x, Key key)
{
if (key.compareTo(x.key) < 0)
{
if (!isRed(x.left) && !isRed(x.left.left))
x = moveRedLeft(x);
x.left = deleteKernel(x.left, key);
}
else
{
if (isRed(x.left))
x = rotateRight(x);
if (key.compareTo(x.key) == 0 && (x.right == null))
return null;
if (!isRed(x.right) && !isRed(x.right.left))
x = moveRedRight(x);
if (key.compareTo(x.key) == 0)
{
Node t = minKernel(x.right);
x.key = t.key;
x.val = t.val;
// x.val = get(x.right, min(x.right).key);
// x.key = min(x.right).key;
x.right = deleteMinKernel(x.right);
}
else x.right = deleteKernel(x.right, key);
}
return balance(x);
} private Node rotateRight(Node x) // 右旋转
{
Node t = x.left;
x.left = t.right;
t.right = x;
t.color = t.right.color;
t.right.color = RED;
t.size = x.size;
x.size = 1 + size(x.left) + size(x.right);
return t;
} private Node rotateLeft(Node x) // 左旋转
{
Node t = x.right;
x.right = t.left;
t.left = x;
t.color = t.left.color;
t.left.color = RED;
t.size = x.size;
x.size = 1 + size(x.left) + size(x.right);
return t;
} private void flipColors(Node x) // 改变节点及其子节点的颜色
{
// assert (x != null) && (x.left != null) && (x.right != null);
// assert (!isRed(x) && isRed(x.left) && isRed(x.right)) || (isRed(x) && !isRed(x.left) && !isRed(x.right));
x.color = !x.color;
x.left.color = !x.left.color;
x.right.color = !x.right.color;
} private Node moveRedLeft(Node x) // x 红而 x.left 和 x.left.left 都是黑的,调整使得两个黑链接之一变红
{
// assert (x != null);
// assert isRed(x) && !isRed(x.left) && !isRed(x.left.left);
flipColors(x);
if (isRed(x.right.left))
{
x.right = rotateRight(x.right);
x = rotateLeft(x);
flipColors(x);
}
return x;
} private Node moveRedRight(Node x) // x 红而 x.right 和 x.right.left 都是黑的,调整使得两黑链接之一变红
{
// assert (x != null);
// assert isRed(x) && !isRed(x.right) && !isRed(x.right.left);
flipColors(x);
if (isRed(x.left.left))
{
x = rotateRight(x);
flipColors(x);
}
return x;
} private Node balance(Node x) // 右链接红色、连续两层左链接红色以及左右链接都是红色的状况,分别调整
{
// assert (x != null);
if (isRed(x.right))
x = rotateLeft(x);
if (isRed(x.left) && isRed(x.left.left))
x = rotateRight(x);
if (isRed(x.left) && isRed(x.right))
flipColors(x);
x.size = 1 + size(x.left) + size(x.right);
return x;
} public Key min()
{
if (isEmpty())
throw new NoSuchElementException("\n<delete> empty.\n");
return minKernel(root).key;
} private Node minKernel(Node x)
{
if (x.left == null)
return x;
return minKernel(x.left);
} public Key max()
{
if (isEmpty())
throw new NoSuchElementException("\n<max> empty.\n");
return maxKernel(root).key;
} private Node maxKernel(Node x)
{
if (x.right == null)
return x;
return maxKernel(x.right);
} public Key floor(Key key)
{
if (key == null)
throw new IllegalArgumentException("\n<floor> key == null.\n");
if (isEmpty())
throw new NoSuchElementException("\n<floor> empty.\n");
Node x = floorKernel(root, key);
return (x == null) ? null : x.key;
} private Node floorKernel(Node x, Key key)
{
if (x == null)
return null;
int cmp = key.compareTo(x.key);
if (cmp == 0)
return x;
if (cmp < 0)
return floorKernel(x.left, key);
Node t = floorKernel(x.right, key);
return (t == null) ? x : t;
} public Key ceiling(Key key)
{
if (key == null)
throw new IllegalArgumentException("\n<ceiling> key == null.\n");
if (isEmpty())
throw new NoSuchElementException("\n<ceiling> empty.\n");
Node x = ceilingKernel(root, key);
return (x == null) ? null : x.key;
} private Node ceilingKernel(Node x, Key key)
{
if (x == null)
return null;
int cmp = key.compareTo(x.key);
if (cmp == 0)
return x;
if (cmp > 0)
return ceilingKernel(x.right, key);
Node t = ceilingKernel(x.left, key);
return (t == null) ? x : t;
} public Key select(int k)
{
if (k < 0 || k >= size())
throw new IllegalArgumentException("\n<select> k < 0 || k >= size().\n");
return selectKernel(root, k).key;
} private Node selectKernel(Node x, int k)
{
if (x == null)
return null;
int t = size(x.left);
if (k <t)
return selectKernel(x.left, k);
if (k > t)
return selectKernel(x.right, k - t - 1);
return x;
} public int rank(Key key)
{
if (key == null)
throw new IllegalArgumentException("\n<rank> key == null.\n");
return rankKernel(key, root);
} private int rankKernel(Key key, Node x)
{
if (x == null)
return 0;
int cmp = key.compareTo(x.key);
if (cmp < 0)
return rankKernel(key, x.left);
if (cmp > 0)
return 1 + size(x.left) + rankKernel(key, x.right);
return size(x.left);
} public Iterable<Key> keys()
{
if (isEmpty())
return new Queue<Key>();
Key lo = min(), hi = max();
if (lo == null)
throw new IllegalArgumentException("\n<iterable> lo == null.\n");
if (hi == null)
throw new IllegalArgumentException("\n<iterable> hi == null.\n");
Queue<Key> queue = new Queue<Key>();
// if (isEmpty() || lo.compareTo(hi) > 0) return queue;
keysKernel(root, queue, lo, hi);
return queue;
} private void keysKernel(Node x, Queue<Key> queue, Key lo, Key hi)
{
if (x == null)
return;
int cmplo = lo.compareTo(x.key), cmphi = hi.compareTo(x.key);
if (cmplo < 0)
keysKernel(x.left, queue, lo, hi);
if (cmplo <= 0 && cmphi >= 0)
queue.enqueue(x.key);
if (cmphi > 0)
keysKernel(x.right, queue, lo, hi);
} public Iterable<Key> levelOrder()
{
Queue<Key> keys = new Queue<Key>();
Queue<Node> queue = new Queue<Node>();
for (queue.enqueue(root); !queue.isEmpty();)
{
Node x = queue.dequeue();
if (x == null)
continue;
keys.enqueue(x.key);
queue.enqueue(x.left);
queue.enqueue(x.right);
}
return keys;
} public int size(Key lo, Key hi)
{
if (lo == null)
throw new IllegalArgumentException("\n<size> lo == null.\n");
if (hi == null)
throw new IllegalArgumentException("\n<size> hi == null.\n");
if (lo.compareTo(hi) > 0)
return 0;
if (contains(hi))
return rank(hi) - rank(lo) + 1;
return rank(hi) - rank(lo);
} public int height()
{
return heightKernel(root);
} private int heightKernel(Node x)
{
if (x == null)
return -1;
return 1 + Math.max(heightKernel(x.left), heightKernel(x.right));
} private boolean check()
{
if (!isBST())
StdOut.println("\n<check> Not in symmetric order.\n");
if (!isSizeConsistent())
StdOut.println("\n<check> Subtree counts not consistent.\n");
if (!isRankConsistent())
StdOut.println("\n<check> Ranks not consistent.\n");
if (!is23())
StdOut.println("\n<check> Not a 2 - 3 tree.\n");
if (!isBalanced())
StdOut.println("\n<check> Not balanced.\n");
return isBST() && isSizeConsistent() && isRankConsistent() && is23() && isBalanced();
} private boolean isBST()
{
return isBSTKernel(root, null, null);
} private boolean isBSTKernel(Node x, Key min, Key max)
{
if (x == null)
return true;
if (min != null && x.key.compareTo(min) <= 0)
return false;
if (max != null && x.key.compareTo(max) >= 0)
return false;
return isBSTKernel(x.left, min, x.key) && isBSTKernel(x.right, x.key, max);
} private boolean isSizeConsistent()
{
return isSizeConsistentKernel(root);
} private boolean isSizeConsistentKernel(Node x)
{
if (x == null)
return true;
if (x.size != 1 + size(x.left) + size(x.right))
return false;
return isSizeConsistentKernel(x.left) && isSizeConsistentKernel(x.right);
} private boolean isRankConsistent()
{
for (int i = 0; i < size(); i++)
{
if (i != rank(select(i)))
return false;
}
for (Key key : keys())
{
if (key.compareTo(select(rank(key))) != 0)
return false;
}
return true;
} private boolean is23()
{
return is23Kernel(root);
} private boolean is23Kernel(Node x)
{
if (x == null)
return true;
if (isRed(x.right))
return false;
if (x != root && isRed(x) && isRed(x.left))
return false;
return is23Kernel(x.left) && is23Kernel(x.right);
} private boolean isBalanced()
{
int black = 0; // 从 root 到 min 节点的路径长
for(Node x = root;x != null; x = x.left)
{
if (!isRed(x))
black++;
}
return isBalancedKernel(root, black);
} private boolean isBalancedKernel(Node x, int black)
{
if (x == null)
return black == 0;
if (!isRed(x))
black--;
return isBalancedKernel(x.left, black) && isBalancedKernel(x.right, black);
} public static void main(String[] args)
{
class01<String, Integer> st = new class01<String, Integer>();
for (int i = 0; !StdIn.isEmpty(); i++)
{
String key = StdIn.readString();
st.put(key, i);
} for (String s : st.levelOrder())
StdOut.println(s + " " + st.get(s)); StdOut.println();
for (String s : st.keys())
StdOut.println(s + " " + st.get(s));
}
}//
《算法》第三章部分程序 part 3的更多相关文章
- 《算法》第三章部分程序 part 6
▶ 书中第三章部分程序,加上自己补充的代码,包含双向索引表.文建索引.稀疏向量类型 ● 双向索引表 package package01; import edu.princeton.cs.algs4.S ...
- 《算法》第三章部分程序 part 5
▶ 书中第三章部分程序,加上自己补充的代码,包含公共符号表.集合类型 ● 公共符号表,用于普通查找表的基本类 package package01; import java.util.NoSuchEle ...
- 《算法》第三章部分程序 part 4
▶ 书中第三章部分程序,加上自己补充的代码,包括散列表.线性探查表 ● 散列表 package package01; import edu.princeton.cs.algs4.Queue; impo ...
- 《算法》第三章部分程序 part 2
▶ 书中第三章部分程序,加上自己补充的代码,平衡二叉搜索树 ● 平衡二叉搜索树 package package01; import java.util.NoSuchElementException; ...
- 《算法》第三章部分程序 part 1
▶ 书中第三章部分程序,加上自己补充的代码,包括单词频率统计,(单链表)顺序查找表,二分查找表 ● 单词频率统计 package package01; import edu.princeton.cs. ...
- 《算法》第二章部分程序 part 3
▶ 书中第二章部分程序,加上自己补充的代码,包括各种优化的快排 package package01; import edu.princeton.cs.algs4.In; import edu.prin ...
- 《算法》第一章部分程序 part 1
▶ 书中第一章部分程序,加上自己补充的代码,包括若干种二分搜索,寻找图上连通分量数的两种算法 ● 代码,二分搜索 package package01; import java.util.Arrays; ...
- 《算法》第二章部分程序 part 5
▶ 书中第二章部分程序,加上自己补充的代码,包括利用优先队列进行多路归并和堆排序 ● 利用优先队列进行多路归并 package package01; import edu.princeton.cs.a ...
- 《算法》第二章部分程序 part 4
▶ 书中第二章部分程序,加上自己补充的代码,包括优先队列和索引优先队列 ● 优先队列 package package01; import java.util.Comparator; import ja ...
随机推荐
- debian下erlang新版本安装
debian下的erlang版本太老 安装kerl,并且在profile内添加到PATH curl -o ~/dev/erlang/kerl https://raw.githubusercontent ...
- C++11--正则表达式<regex>
/* 正则表达式:一个指定的模式用来对文本中的字符串提供精确且灵活的匹配 */ #include <regex> using namespace std; int main() { str ...
- Java连接S3并上传Redis
package com.shinho.bigdatalake.redis; import com.amazonaws.regions.Region; import com.amazonaws.regi ...
- Android keystore相关
一.生成keystorekeytool -genkey -alias test.keystore -keyalg RSA -validity -keystore test.keystore 二.查看 ...
- PAT 乙级 1046 划拳(15) C++版
1046. 划拳(15) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 CHEN, Yue 划拳是古老中国酒文化的一个有趣的组成部分 ...
- python 数组 变成 字典的方法
1.现在有两个列表,list1 = ['key1','key2','key3']和list2 = ['1','2','3'],把他们转为这样的字典:{'key1':'1','key2':'2','ke ...
- 不同安卓手机的 安卓版本不同,xpath元素也不同
模拟器是 夜神模拟器 版本是 4.4.2 LG手机 版本是 8.0.0
- Consul之:key/value存储
key/value作用 动态修改配置文件 支持服务协同 建立leader选举 提供服务发现 集成健康检查 除了提供服务发现和综合健康检查,Consul还提供了一个易于使用的键/值存储.这可以用来保存动 ...
- 云中树莓派(2):将传感器数据上传到 AWS IoT 并利用Kibana进行展示
云中树莓派(1):环境准备 云中树莓派(2):将传感器数据上传到AWS IoT 并利用Kibana进行展示 1. 传感器安装及配置 1.1 DHT22 安装 DHT22 是一款温度与湿度传感器,它有3 ...
- 【ZZ】号称“开发者神器”的GitHub,到底该怎么用?
号称“开发者神器”的GitHub,到底该怎么用? https://mp.weixin.qq.com/s/zpKOBMKWckY05Mv_B28RgQ A developer’s introductio ...