自定义红黑树
import com.sun.org.apache.regexp.internal.RE;
/**
* @description: 自定义红黑树
* @author: liangrui
* @create: 2019-12-24 13:50
**/
public class RedBlackTree<K extends Comparable<K>,V> {
private static final boolean RED=true;
private static final boolean BLACK=false;
private class Node{
public K key;
public V value;
public Node left,right;
public boolean color;
public Node(K key,V value){
this.key=key;
this.value=value;
left=null;
right=null;
color=RED;
}
}
private Node root;
private int size;
public RedBlackTree(){
root=null;
size=0;
}
public int getSize(){
return size;
}
public boolean isEmpty(){
return size==0;
}
/**
* 判断节点node的颜色
* @param node
* @return
*/
private boolean isRed(Node node){
if (node==null){
return BLACK;
}
return node.color;
}
// node x
// / \ 左旋转 / \
// T1 x ---------> node T3
// / \ / \
// T2 T3 T1 T2
private Node leftRotate(Node node){
Node x=node.right;
//左旋转
node.right=x.left;
x.left=node;
x.color=node.color;
node.color=RED;
return x;
}
// node x
// / \ 右旋转 / \
// x T2 -------> y node
// / \ / \
// y T1 T1 T2
private Node rightRotate(Node node){
Node x=node.left;
//右旋转
node.left=x.right;
x.right=node;
x.color=node.color;
node.color=RED;
return x;
}
/**
* 颜色翻转
* @param node
*/
private void flipColors(Node node){
node.color=RED;
node.left.color=BLACK;
node.right.color=BLACK;
}
/**
* 向红黑树中添加新的元素(key,value)
* @param key
* @param value
*/
public void add(K key,V value){
root=add(root,key,value);
root.color=BLACK;
}
/**
* 向以node为根的红黑树中插入元素(key,value),递归算法
* @param node
* @param key
* @param value
* @return 返回插入新节点后红黑树的根
*/
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;
}
if (isRed(node.right)&&!isRed(node.left)){
node=leftRotate(node);
}
if (isRed(node.left)&&isRed(node.left.left)){
node=rightRotate(node);
}
if (isRed(node.left)&&isRed(node.right)){
flipColors(node);
}
return node;
}
// 返回以node为根节点的二分搜索树中,key所在的节点
private Node getNode(Node node, K key){
if(node == null)
return null;
if(key.equals(node.key))
return node;
else if(key.compareTo(node.key) < 0)
return getNode(node.left, key);
else // if(key.compareTo(node.key) > 0)
return getNode(node.right, key);
}
public boolean contains(K key){
return getNode(root, key) != null;
}
public V get(K key){
Node node = getNode(root, key);
return node == null ? null : node.value;
}
public void set(K key, V newValue){
Node node = getNode(root, key);
if(node == null)
throw new IllegalArgumentException(key + " doesn't exist!");
node.value = newValue;
}
}
main测试
import java.util.ArrayList;
public class Main {
public static void main(String[] args) {
System.out.println("Pride and Prejudice");
ArrayList<String> words=new ArrayList<>();
if (FileOperation.readFile("pride-and-prejudice.txt",words)){
System.out.println("Total words:"+words.size());
RedBlackTree<String,Integer> redBlackTree=new RedBlackTree<>();
for (String word : words) {
if (redBlackTree.contains(word)){
redBlackTree.set(word,redBlackTree.get(word)+1);
}else {
redBlackTree.add(word,1);
}
}
System.out.println("Total different words:"+redBlackTree.getSize());
System.out.println("Frequency of 'pride':"+redBlackTree.get("pride"));
System.out.println("Frequency of 'prejudice':"+redBlackTree.get("prejudice"));
}
}
}
文件操作类FileOperation
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Locale;
import java.util.Scanner;
// 文件相关操作
public class FileOperation {
// 读取文件名称为filename中的内容,并将其中包含的所有词语放进words中
public static boolean readFile(String filename, ArrayList<String> words){
if (filename == null || words == null){
System.out.println("filename is null or words is null");
return false;
}
// 文件读取
Scanner scanner;
try {
File file = new File(filename);
if(file.exists()){
FileInputStream fis = new FileInputStream(file);
scanner = new Scanner(new BufferedInputStream(fis), "UTF-8");
scanner.useLocale(Locale.ENGLISH);
}
else
return false;
}
catch(IOException ioe){
System.out.println("Cannot open " + filename);
return false;
}
// 简单分词
// 这个分词方式相对简陋, 没有考虑很多文本处理中的特殊问题
// 在这里只做demo展示用
if (scanner.hasNextLine()) {
String contents = scanner.useDelimiter("\\A").next();
int start = firstCharacterIndex(contents, 0);
for (int i = start + 1; i <= contents.length(); )
if (i == contents.length() || !Character.isLetter(contents.charAt(i))) {
String word = contents.substring(start, i).toLowerCase();
words.add(word);
start = firstCharacterIndex(contents, i);
i = start + 1;
} else
i++;
}
return true;
}
// 寻找字符串s中,从start的位置开始的第一个字母字符的位置
private static int firstCharacterIndex(String s, int start){
for( int i = start ; i < s.length() ; i ++ )
if( Character.isLetter(s.charAt(i)) )
return i;
return s.length();
}
}
测试结果:
Pride and Prejudice
Total words:125901
Total different words:6530
Frequency of ‘pride’:53
Frequency of ‘prejudice’:11