▶ 书中第三章部分程序,加上自己补充的代码,红黑树

● 红黑树,大部分方法与注释与二叉树相同

 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的更多相关文章

  1. 《算法》第三章部分程序 part 6

    ▶ 书中第三章部分程序,加上自己补充的代码,包含双向索引表.文建索引.稀疏向量类型 ● 双向索引表 package package01; import edu.princeton.cs.algs4.S ...

  2. 《算法》第三章部分程序 part 5

    ▶ 书中第三章部分程序,加上自己补充的代码,包含公共符号表.集合类型 ● 公共符号表,用于普通查找表的基本类 package package01; import java.util.NoSuchEle ...

  3. 《算法》第三章部分程序 part 4

    ▶ 书中第三章部分程序,加上自己补充的代码,包括散列表.线性探查表 ● 散列表 package package01; import edu.princeton.cs.algs4.Queue; impo ...

  4. 《算法》第三章部分程序 part 2

    ▶ 书中第三章部分程序,加上自己补充的代码,平衡二叉搜索树 ● 平衡二叉搜索树 package package01; import java.util.NoSuchElementException; ...

  5. 《算法》第三章部分程序 part 1

    ▶ 书中第三章部分程序,加上自己补充的代码,包括单词频率统计,(单链表)顺序查找表,二分查找表 ● 单词频率统计 package package01; import edu.princeton.cs. ...

  6. 《算法》第二章部分程序 part 3

    ▶ 书中第二章部分程序,加上自己补充的代码,包括各种优化的快排 package package01; import edu.princeton.cs.algs4.In; import edu.prin ...

  7. 《算法》第一章部分程序 part 1

    ▶ 书中第一章部分程序,加上自己补充的代码,包括若干种二分搜索,寻找图上连通分量数的两种算法 ● 代码,二分搜索 package package01; import java.util.Arrays; ...

  8. 《算法》第二章部分程序 part 5

    ▶ 书中第二章部分程序,加上自己补充的代码,包括利用优先队列进行多路归并和堆排序 ● 利用优先队列进行多路归并 package package01; import edu.princeton.cs.a ...

  9. 《算法》第二章部分程序 part 4

    ▶ 书中第二章部分程序,加上自己补充的代码,包括优先队列和索引优先队列 ● 优先队列 package package01; import java.util.Comparator; import ja ...

随机推荐

  1. excel技巧--一键求和

    类似于上图的表格,我们要得到右侧和下侧栏的汇总结果,通常可以用sum公式加下拉方式,但是还有一种方法更快速,那就是使用 ALT + “+=”组合键就能一下子得到所有汇总结果.(+=键,就是一个键,该键 ...

  2. Python高效编程技巧

    如何在列表,字典,集合中根据条件筛选数据 1.过滤掉列表[-1,-2,-3,4,5,6]中的负数和0 方法1,for循环 data = [-1, -2, -3, 4, 5, 6] res = [] f ...

  3. Action<T> Delegate

    来源:https://docs.microsoft.com/zh-cn/dotnet/api/system.action-1?view=netframework-4.7.2 Action<T&g ...

  4. sql server 拼接字段

    方式一: --select @p_AllPARTOFCHECK = (select CAST(t.PARTOFCHECK as varchar)+'|' from QUEUEDETAIL t wher ...

  5. C#实现根据日期计算星期

    /// <summary> /// 根据日期返回 星期(返回结果为英文) /// </summary> /// <param name="date"& ...

  6. ipconfig/all详解

    Ipconfig/all(win+R-->cmd-->ipconfig/all)最常用的就是显示自己主机的ip了,可以让我们了解自己的计算机是否成功的租用到一个IP地址.但是ipconfi ...

  7. C/C++基础----拷贝控制

    拷贝控制操作,有5个特殊成员函数copy ctor,copy =opt,move ctor,move =opt,dtor 有哪些地方会用到 拷贝初始化 除了=定义变量时 参数传递和函数返回时 花括号列 ...

  8. 峰Redis学习(5)Redis 数据结构(Set的操作)

    第五节:Redis 数据结构之Set 类型 存储Set,这里的Set是无序的:  和List类型不同的是,Set集合中不允许出现重复的元素  Set可包含的最大元素数量是4294967295   存储 ...

  9. vue之v-on

    我们可以用 v-on 指令绑定一个事件监听器,通过它调用我们 Vue 实例中定义的方法: <!DOCTYPE html> <html lang="en"> ...

  10. 客户端负载均衡Feign之一:申明式服务调用Feign入门示例

    Spring Cloud提供了Ribbon和Feign作为客户端的负载均衡. 前面使用了Ribbon做客户端负载均衡,使用Hystrix做容错保护,这两者被作为基础工具类框架被广泛地应用在各个微服务的 ...