1、二叉查找树
package search;import javax.swing.*;/*** @author zwlstart* @create 2020-12-26 20:55*/public class BinerySearchTree {//返回树的全部节点数量private int size(Node x){if (x == null){return 0;}else{return x.n;}}//查找一个节点public Node get(Node x,int v){if (x == null){return null;}int i = x.val - v;if (i == 0){return x;}else if (i > 0){return get(x.left,v);}else{return get(x.right,v);}}//插入一个节点public Node put(Node x,int v){if (x == null){return new Node(v,1);}int i = x.val - v;if (i == 0){x.val = v;}else if (i > 0){x.left = put(x.left,v);}else{x.right = put(x.right,v);}x.n = size(x.left) + size(x.right) + 1;return x;}//查找第i个节点public int search(Node root,int i){if (root == null || i > size(root) || i < 0){return -1;}int size = size(root.left);if (size > i){return search(root.left,i);}else if(size < i){return search(root.right,i - size - 1);}else {return root.val;}}/*** 给定一个数,然后二叉树中节点值小于此数的节点数目* @param v* @return*/public int rank(Node x,int v){if (x == null){return -1;}int i = x.val - v;if (i == 0){return size(x.left);}else if (i > 0){return rank(x.left,v);}else{return size(x.left) + 1 + rank(x.right,v);}}/*** 删除树中的最小值* @param root* @return*/public Node deleteMin(Node root){if (root.left == null){return root.right;}root.left = deleteMin(root.left);root.n = size(root.left) + size(root.right) + 1;return root;}/*** 删除指定的值,分为三种情况,当该节点只有一个子节点时,直接删除即可,让该节点的指针* 指向唯一的子节点* 如果该节点有两个孩子,则不能直接删除,需要找到该节点的直接后继或直接前继节点然后再删除* 可分为四步:* 1、找到后续节点* 2、该节点指向后续节点* 3、删除后续节点* 4、后续的节点的左右孩子指向原节点的左右孩子节点* @param root* @param v* @return*/public Node delete(Node root, int v){if (root == null){return null;}int i = root.val - v;if (i > 0){root.left = delete(root.left,v);}else if (i < 0){root.right = delete(root.right,v);}else{if (root.left == null){return root.right;}if (root.right == null){return root.left;}Node temp = root;root = searchMin(root.right);//这一步必须在前,否则删除的会有问题,//如果先执行 root.left = temp.left; 这步,则会将原本temp.left挂载到root.left上,//此时root还是temp.right子树上的最小节点,再执行root.right = deleteMin(temp.right);//删除的就不是temp了root.right = deleteMin(temp.right);root.left = temp.left;}root.n = size(root.right) + size(root.left) + 1;return root;}private Node searchMin(Node node) {while (node.left != null){node = node.left;}return node;}public BinerySearchTree() {}}
2、avl树的实现
package search;import javax.swing.*;/*** @author zwlstart* @create 2020-12-28 10:45*/public class AVL {/*** 返回以该节点为根的树高度*/public int height(AvlNode x){if (x == null){return 0;}return x.height;}/*** 插入一个节点*/public AvlNode put(AvlNode x,int value){if (x == null){return new AvlNode(value,1);}int i = x.val - value;if (i > 0){x.left = put(x.left,value);}else if (i < 0){x.right = put(x.right,value);}else {x.val = value;}if (height(x.left) - height(x.right) > 1){if (height(x.left.left) > height(x.left.right)){x = rotatlRight(x);}else{x.left = rotatlLeft(x.left);x = rotatlRight(x);}}else if (height(x.left) - height(x.right) < -1) {if (height(x.right.right) < height(x.right.left)){x = rotatlLeft(x);}else{x.right = rotatlRight(x.right);x = rotatlLeft(x);}}x.height = Integer.max(height(x.left),height(x.right)) + 1;return x;}/*** 左旋*/private AvlNode rotatlLeft(AvlNode x) {AvlNode temp = x.right;x.right = temp.left;temp.left = x;x.height = Integer.max(height(x.left),height(x.right)) + 1;temp.height = Integer.max(x.height,height(temp.right)) + 1;return temp;}/*** 右旋*/private AvlNode rotatlRight(AvlNode x) {AvlNode temp = x.left;x.left = temp.right;temp.right = x;x.height = Integer.max(height(x.left),height(x.right)) + 1;temp.height = Integer.max(height(temp.left),x.height) + 1;return temp;}public AvlNode delete(AvlNode root,int k){if (root == null){return null;}int i = root.val - k;if (i > 0){root.left = delete(root.left,k);}else if (i < 0){root.right = delete(root.right,k);}else{if (root.left == null && root.right == null){return null;}if (root.left != null && root.right == null){return root.left;}if (root.left == null && root.right != null){return root.right;}if (root.left != null && root.right != null){AvlNode t = searchMin(root.right);root.val = t.val;root.right = delete(root.right,t.val);}}if (height(root.left) - height(root.right) > 1){if (height(root.left.left) > height(root.left.right)){root = rotatlRight(root);}else{root.left = rotatlLeft(root.left);root = rotatlRight(root);}}else if (height(root.left) - height(root.right) < -1) {if (height(root.right.right) < height(root.right.left)){root = rotatlLeft(root);}else{root.right = rotatlRight(root.right);root = rotatlLeft(root);}}root.height = Integer.max(height(root.left),height(root.right)) + 1;return root;}private AvlNode searchMin(AvlNode x) {if (x.left != null){x = x.left;}return x;}}
3、红黑树实现
未全部实现,删除操作尚未实现。
package search;/*** 红黑树的java实现* @author zwlstart* @create 2020-12-27 21:01*/public class RedBalckTree {/*** 查找一个节点*/public RBNode get(RBNode x,int k){if (x == null){return null;}int i = x.val - k;if (i == 0){return x;}else if (i > 0){return get(x.left,k);}else{return get(x.right,k);}}/*** 返回树的全部节点数量*/public int size(RBNode x){if (x == null){return 0;}else{return x.n;}}/*** 插入一个节点,需保持红黑树的性质*/public RBNode put(RBNode x,int v){if (x == null){return new RBNode(v,1,true);}int i = x.val - v;if (i == 0){x.val = v;}else if (i > 0){x.left = put(x.left,v);}else{x.right = put(x.right,v);}if (isRed(x.right) && !isRed(x.left)){x = rotateRight(x);}if (isRed(x.left) && isRed(x.left.left)){x = rotateLeft(x);}if (isRed(x.left) && isRed(x.right)){x = flipColors(x);}x.n = size(x.left) + size(x.right) + 1;return x;}/*** 判断该节点是否是红链接所指向的* @param x* @return*/public boolean isRed(RBNode x){if (x == null){return false;}return x.color;}/*** 右旋* @param x* @return*/public RBNode rotateRight(RBNode x){RBNode t = x.right;x.right = t.left;t.left = x;t.color = x.color;x.color = true;t.n = x.n;x.n = size(x.left) + size(x.right) + 1;return t;}/*** 左旋* @param x* @return*/public RBNode rotateLeft(RBNode x){RBNode t = x.left;x.left = t.right;t.right = x;t.color = x.color;x.color = true;t.n = x.n;x.n = size(x.left) + size(x.right) + 1;return t;}/*** 变换节点颜色* @param x* @return*/public RBNode flipColors(RBNode x){x.right.color = false;x.left.color = false;x.color = true;return x;}//查找第i个节点public int search(RBNode root,int i){if (root == null || i > size(root) || i < 0){return -1;}int size = size(root.left);if (size > i){return search(root.left,i);}else if(size < i){return search(root.right,i - size - 1);}else {return root.val;}}/*** 给定一个数,然后二叉树中节点值小于此数的节点数目* @param v* @return*/public int rank(RBNode x,int v){if (x == null){return -1;}int i = x.val - v;if (i == 0){return size(x.left);}else if (i > 0){return rank(x.left,v);}else{return size(x.left) + 1 + rank(x.right,v);}}/*** 删除树中的最小值* @param root* @return*/public RBNode deleteMin(RBNode root){if (root.left == null){return root.right;}root.left = deleteMin(root.left);root.n = size(root.left) + size(root.right) + 1;return root;}}
4、散列表的实现
SeparateChainingHashST.javaBelow is the syntax highlighted version of SeparateChainingHashST.java./******************************************************************************* Compilation: javac SeparateChainingHashST.java* Execution: java SeparateChainingHashST < input.txt* Dependencies: StdIn.java StdOut.java* Data files: https://algs4.cs.princeton.edu/34hash/tinyST.txt** A symbol table implemented with a separate-chaining hash table.*******************************************************************************/package edu.princeton.cs.algs4;/*** The {@code SeparateChainingHashST} class represents a symbol table of generic* key-value pairs.* It supports the usual <em>put</em>, <em>get</em>, <em>contains</em>,* <em>delete</em>, <em>size</em>, and <em>is-empty</em> methods.* It also provides a <em>keys</em> method for iterating over all of the keys.* A symbol table implements the <em>associative array</em> abstraction:* when associating a value with a key that is already in the symbol table,* the convention is to replace the old value with the new value.* Unlike {@link java.util.Map}, this class uses the convention that* values cannot be {@code null}—setting the* value associated with a key to {@code null} is equivalent to deleting the key* from the symbol table.* <p>* This implementation uses a separate chaining hash table. It requires that* the key type overrides the {@code equals()} and {@code hashCode()} methods.* The expected time per <em>put</em>, <em>contains</em>, or <em>remove</em>* operation is constant, subject to the uniform hashing assumption.* The <em>size</em>, and <em>is-empty</em> operations take constant time.* Construction takes constant time.* <p>* For additional documentation, see <a href="https://algs4.cs.princeton.edu/34hash">Section 3.4</a> of* <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.* For other implementations, see {@link ST}, {@link BinarySearchST},* {@link SequentialSearchST}, {@link BST}, {@link RedBlackBST}, and* {@link LinearProbingHashST},** @author Robert Sedgewick* @author Kevin Wayne*/public class SeparateChainingHashST<Key, Value> {private static final int INIT_CAPACITY = 4;private int n; // number of key-value pairsprivate int m; // hash table sizeprivate SequentialSearchST<Key, Value>[] st; // array of linked-list symbol tables/*** Initializes an empty symbol table.*/public SeparateChainingHashST() {this(INIT_CAPACITY);}/*** Initializes an empty symbol table with {@code m} chains.* @param m the initial number of chains*/public SeparateChainingHashST(int m) {this.m = m;st = (SequentialSearchST<Key, Value>[]) new SequentialSearchST[m];for (int i = 0; i < m; i++)st[i] = new SequentialSearchST<Key, Value>();}// resize the hash table to have the given number of chains,// rehashing all of the keysprivate void resize(int chains) {SeparateChainingHashST<Key, Value> temp = new SeparateChainingHashST<Key, Value>(chains);for (int i = 0; i < m; i++) {for (Key key : st[i].keys()) {temp.put(key, st[i].get(key));}}this.m = temp.m;this.n = temp.n;this.st = temp.st;}// hash function for keys - returns value between 0 and m-1private int hashTextbook(Key key) {return (key.hashCode() & 0x7fffffff) % m;}// hash function for keys - returns value between 0 and m-1 (assumes m is a power of 2)// (from Java 7 implementation, protects against poor quality hashCode() implementations)private int hash(Key key) {int h = key.hashCode();h ^= (h >>> 20) ^ (h >>> 12) ^ (h >>> 7) ^ (h >>> 4);return h & (m-1);}/*** Returns the number of key-value pairs in this symbol table.** @return the number of key-value pairs in this symbol table*/public int size() {return n;}/*** Returns true if this symbol table is empty.** @return {@code true} if this symbol table is empty;* {@code false} otherwise*/public boolean isEmpty() {return size() == 0;}/*** Returns true if this symbol table contains the specified key.** @param key the key* @return {@code true} if this symbol table contains {@code key};* {@code false} otherwise* @throws IllegalArgumentException if {@code key} is {@code null}*/public boolean contains(Key key) {if (key == null) throw new IllegalArgumentException("argument to contains() is null");return get(key) != null;}/*** Returns the value associated with the specified key in this symbol table.** @param key the key* @return the value associated with {@code key} in the symbol table;* {@code null} if no such value* @throws IllegalArgumentException if {@code key} is {@code null}*/public Value get(Key key) {if (key == null) throw new IllegalArgumentException("argument to get() is null");int i = hash(key);return st[i].get(key);}/*** Inserts the specified key-value pair into the symbol table, overwriting the old* value with the new value if the symbol table already contains the specified key.* Deletes the specified key (and its associated value) from this symbol table* if the specified value is {@code null}.** @param key the key* @param val the value* @throws IllegalArgumentException if {@code key} is {@code null}*/public void put(Key key, Value val) {if (key == null) throw new IllegalArgumentException("first argument to put() is null");if (val == null) {delete(key);return;}// double table size if average length of list >= 10if (n >= 10*m) resize(2*m);int i = hash(key);if (!st[i].contains(key)) n++;st[i].put(key, val);}/*** Removes the specified key and its associated value from this symbol table* (if the key is in this symbol table).** @param key the key* @throws IllegalArgumentException if {@code key} is {@code null}*/public void delete(Key key) {if (key == null) throw new IllegalArgumentException("argument to delete() is null");int i = hash(key);if (st[i].contains(key)) n--;st[i].delete(key);// halve table size if average length of list <= 2if (m > INIT_CAPACITY && n <= 2*m) resize(m/2);}// return keys in symbol table as an Iterablepublic Iterable<Key> keys() {Queue<Key> queue = new Queue<Key>();for (int i = 0; i < m; i++) {for (Key key : st[i].keys())queue.enqueue(key);}return queue;}/*** Unit tests the {@code SeparateChainingHashST} data type.** @param args the command-line arguments*/public static void main(String[] args) {SeparateChainingHashST<String, Integer> st = new SeparateChainingHashST<String, Integer>();for (int i = 0; !StdIn.isEmpty(); i++) {String key = StdIn.readString();st.put(key, i);}// print keysfor (String s : st.keys())StdOut.println(s + " " + st.get(s));}}
