com.mayabot.nlp.segment.wordnet.VertexRow Maven / Gradle / Ivy
/*
* Copyright 2018 mayabot.com authors. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.mayabot.nlp.segment.wordnet;
import com.mayabot.nlp.common.Lists;
import kotlin.collections.AbstractIterator;
import org.jetbrains.annotations.Nullable;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
/**
* 代表一个槽位的行.
* 一行中有多个Vertex节点,每个Vertex的len的是按照从小到大的排序,且具有唯一性
*
* @author jimichan
*/
public final class VertexRow implements Iterable {
/**
* 和sIndex一样,-1表示#start
*/
int rowNum;
Vertex first;
Wordnet wordnet;
/**
* 包含Vertex的数量
*/
private int size;
VertexRow(int rowNum, Wordnet wordnet) {
this.rowNum = rowNum;
this.wordnet = wordnet;
}
public String subString(int length) {
if (rowNum == -1 || length == 0) {
return "";
}
return new String(wordnet.charArray, rowNum, length);
}
public Vertex getOrCrete(int length) {
Vertex v = get(length);
if (v == null) {
v = new Vertex(length);
this.put(v);
}
return v;
}
public void clear() {
this.size = 0;
//select = null;
first = null;
}
/**
* @param length
* @return may be null if not exits
*/
@Nullable
public Vertex get(int length) {
//优化空
if (first == null) {
return null;
}
if (size == 1) {
if (first.length == length) {
return first;
} else {
return null;
}
} else {
for (Vertex x = first; x != null; x = x.next) {
if (x.length == length) {
return x;
} else if (length < x.length) {
// 2 5 因为是从小到大排序的,所以已经是小于当前值了,所以肯定找不到
return null;
}
}
}
return null;
}
/**
* 移除长度为length的节点。成功就返回被删除的节点
*
* @param length 词的长度
* @return 被删除的节点,null表示没有节点被删除
*/
@Nullable
public Vertex remove(short length) {
Vertex v = get(length);
if (v != null) {
unlink(v);
}
return v;
}
/**
* 设置 Vertex 以 length为key ,如果替换了返回被替换者
*
* @param v
* @return 被替换的节点对象,null表示这是新增的Vertex
*/
public Vertex put(Vertex v) {
int key = v.length;
//两种操作要么,要么替换、要么插入
v.vertexRow = this;
v.next = null;
v.prev = null;
if (isEmpty()) {
linkFirst(v);
return null;
}
Vertex point = null;
for (Vertex x = first; x != null; x = x.next) {
point = x;
if (key == x.length) {
//替换吧
replace(x, v);
return x;
}
if (x.next == null) {
if (key < x.length) {
//查到前面
linkBefore(v, x);
return null;
} else {
linkAfter(v, x);
return null;
}
} else {
if (key < x.length) {
linkBefore(v, x);
return null;
} else { // key > x.length
//再分两种情况
if (key < x.next.length) {
linkBefore(v, x.next);
return null;
} else {
}
}
}
}
linkAfter(v, point);
return null;
}
public boolean isEmpty() {
return first == null;
}
public boolean contains(int len) {
return get(len) != null;
}
public int size() {
return size;
}
public Set keys() {
Set set = new TreeSet();
for (Vertex x = first; x != null; x = x.next) {
set.add(x.length);
}
return set;
}
/**
* 返回最长的那个词的长度
*
* @return max word len
*/
public int lastLen() {
int len = 0;
for (Vertex x = first; x != null; x = x.next) {
len = x.length;
}
return len;
}
/**
* Unlinks non-null node x.
*/
private Vertex unlink(Vertex x) {
// assert x != null;
final Vertex next = x.next;
final Vertex prev = x.prev;
if (prev == null) {
first = next;
} else {
prev.next = next;
x.prev = null;
}
if (next == null) {
// last = prev;
} else {
next.prev = prev;
x.next = null;
}
size--;
return x;
}
private void replace(Vertex old, Vertex replaced) {
final Vertex prev = old.prev;
final Vertex next = old.next;
old.prev = null;
old.next = null;
replaced.prev = prev;
replaced.next = next;
if (prev != null) {
prev.next = replaced;
}
if (next != null) {
next.prev = replaced;
}
if (first == old) {
first = replaced;
}
// if(old==select){
// this.select = replaced;
// }
}
/**
* Links e as first element.
*/
private void linkFirst(Vertex newNode) {
newNode.next = null;
newNode.prev = null;
final Vertex f = first;
newNode.next = f;
first = newNode;
if (f == null) {
// last = newNode;
} else {
f.prev = newNode;
}
size++;
}
private void linkAfter(Vertex newNode, Vertex succ) {
// assert succ != null;
final Vertex nexted = succ.next;
newNode.prev = succ;
newNode.next = nexted;
succ.next = newNode;
if (nexted != null) {
nexted.prev = newNode;
}
size++;
}
/**
* Inserts element e before non-null Node succ.
*/
private void linkBefore(Vertex newNode, Vertex succ) {
// assert succ != null;
final Vertex pred = succ.prev;
newNode.prev = pred;
newNode.next = succ;
succ.prev = newNode;
if (pred == null) {
first = newNode;
} else {
pred.next = newNode;
}
size++;
}
@Override
public String toString() {
return "Slot[" + rowNum + "]=>" + this.keys();
}
@Override
public Iterator iterator() {
return new AbstractIterator() {
Vertex point = first;
@Override
protected void computeNext() {
if (point == null) {
done();
return;
} else {
Vertex old = point;
point = old.next;
setNext(old);
return;
}
}
};
}
public List values() {
return Lists.newArrayList(this);
}
public Vertex getFirst() {
return first;
}
public Vertex first() {
return first;
}
public char theChar() {
return wordnet.charAt(rowNum);
}
public int getRowNum() {
return rowNum;
}
public boolean isNotEmpty() {
return first != null;
}
}