一、跳表的原理
跳表的原理
二、跳表的Java代码实现
public class Node<T extends Comparable>{
private Node<T> down;
private Node<T> right;
private T value;
....
}
ArrayList<Node<T>> heads=new ArrayList<>();
int list_Level;
- 初始化
`public void createSkipList() {
Node<T> h=new Node<>(null);
heads.add(h);
list_Level=0;
}`
- 插入
private int produceLevel() {
int level=0;
while(Math.random()<0.5D) {
level++;
}
return level;
}
/**
* lastTop
* top=head[level]
* if head top.getRight==null || (top.getRight()!=null&&top.getRight>value)
* new_Node.setRight(top.getRight)
* top.setRight(new_Node)
* lastTop=new_Node;
* top=head[level]
* else if not head
* top=top.getRight
* @Bug1:001 插入相同元素时出错
* @param value
*/
@SuppressWarnings("unchecked")
public void insert(T value) {
int level=produceLevel();
Node<T> lastTop = null;
Node<T> new_Node;
if(level>list_Level) {
level=list_Level;
++list_Level;
heads.add(new Node<>(null));
new_Node=new Node<>(value);
heads.get(list_Level).setRight(new_Node);
lastTop=new_Node;
}
Node<T> top=heads.get(level);
Node<T> topRight=top.getRight();
for(;level>-1;--level) {
if (top.getValue() == null) {
top = heads.get(level);
topRight=top.getRight();
if (topRight==null||(topRight != null && topRight.getValue().compareTo(value) >= 0)) {
//会在同一层值不变@Bug:001
//top = heads.get(level);
//topRight=top.getRight();
lastTop = addNewNode(top,lastTop,value);
continue;
}
top=topRight;
}
while(top.getRight()!=null
&& top.getRight().getValue().compareTo(value)<0) {
top=top.getRight();
}
lastTop = addNewNode(top,lastTop,value);
top = top.getDown();
}
}
/**
*
* @param preNode 前驱结点
* @param topNode 上一层节点
* @param value
* @return
*/
private Node<T> addNewNode(Node<T> preNode,Node<T> topNode,T value) {
Node<T> new_Node = new Node<>(value);
new_Node.setRight(preNode.getRight());
preNode.setRight(new_Node);
if (topNode != null) {
topNode.setDown(new_Node);
}
return new_Node;
}`
- 搜索
@SuppressWarnings("unchecked")
public Node<T> search(T value) {
int level=list_Level;
Node<T> top=heads.get(level);
Node<T> topRight=top.getRight();
//the list is empty
if (topRight==null) {
return null;
}
for (; level >= 0;level--) {
//search list head
if (top.getValue()==null) {
top = heads.get(level);
topRight = top.getRight();
if (topRight.getValue().compareTo(value) >= 0) {
//level若不满足无法更新
// top = heads.get(level);
// topRight = top.getRight();
if(topRight.getValue().equals(value)) {
return topRight;
}
continue;
} else {
//enter list
top = topRight;
}
}
while (top.getRight() != null && top.getRight().getValue().compareTo(value) < 0) {
top = top.getRight();
}
//find the node
if (top.getRight()!=null&&top.getRight().getValue().equals(value)) {
return top.getRight();
}
//skip
top=top.getDown();
}
return null;
}
- 删除
@SuppressWarnings("unchecked")
public void delete(T value){
int level=list_Level;
Node<T> top=heads.get(level);
Node<T> topRight=top.getRight();
ArrayList<Node<T>> update=new ArrayList<>();
//the list is empty
if (topRight==null) {
return;
}
for (; level >= 0;level--) {
//search list head
if (top.getValue()==null) {
top = heads.get(level);
topRight = top.getRight();
if (topRight.getValue().compareTo(value) >= 0) {
//level若不满足无法更新
// top = heads.get(level);
// topRight = top.getRight();
if(topRight.getValue().equals(value)) {
update.add(top);
}
continue;
}
//enter list
top = topRight;
}
while (top.getRight() != null && top.getRight().getValue().compareTo(value) < 0) {
top = top.getRight();
}
//find the node
if (top.getRight()!=null&&top.getRight().getValue().equals(value)) {
update.add(top);
}
top=top.getDown();
}
//System.out.println(value+"删除时updateSize="+update.size());
for (Node<T> e:update) {
e.setRight(e.getRight().getRight());
if (e.getValue()==null&&e.getRight()==null&&list_Level>0) {
--list_Level;
}
}
}
- 辅助输出
public void print(Node<T> head) {
Node<T> h=head;
while(h!=null) {
System.out.print(h.getValue()+"--");
h=h.getRight();
}
System.out.println("");
}
public void printAll() {
for (int i=0;i<list_Level+1;++i) {
System.out.println("level"+i);
print(heads.get(i));
}
System.out.println("____________________________________________");
}
三、性能测试
- 测试代码
public static void main(String[] args) {
// TODO Auto-generated method stub
SkipList<Integer> sl=new SkipList<>();
LinkedList<Integer> ls=new LinkedList<>();
int testNum=1000;
long start,end;
System.out.println("开始生成SkipList");
start=System.currentTimeMillis();
for (int i=0;i<testNum;++i) {
sl.insert(i);
}
end=System.currentTimeMillis();
System.out.println("__________________"+(end-start)+"ms");
System.out.println("开始生成LinkedList");
start=System.currentTimeMillis();
for (int i=0;i<testNum;++i) {
ls.add(i);
}
end=System.currentTimeMillis();
System.out.println("__________________"+(end-start)+"ms");
sl.printAll();
System.out.println("开始搜索SkipList");
start=System.currentTimeMillis();
for (int i=0;i<testNum;++i) {
sl.search(i);
}
end=System.currentTimeMillis();
System.out.println("__________________"+(end-start)+"ms");
System.out.println("开始搜索LinkedList");
start=System.currentTimeMillis();
for (int i=0;i<testNum;++i) {
ls.indexOf(i);
}
end=System.currentTimeMillis();
System.out.println("__________________"+(end-start)+"ms");
System.out.println("开始删除SkipList");
start=System.currentTimeMillis();
for (int i=0;i<testNum;++i) {
sl.delete(i);
}
end=System.currentTimeMillis();
System.out.println("__________________"+(end-start)+"ms");
sl.printAll();
System.out.println("开始删除LinkedList");
start=System.currentTimeMillis();
for (int i=0;i<testNum;++i) {
ls.remove(0);
}
end=System.currentTimeMillis();
System.out.println("__________________"+(end-start)+"ms");
for(int i=0;i<testNum;++i) {
sl.insert(i);
}
sl.printAll();
for (int i=0;i<333;++i) {
sl.delete(i);
}
sl.printAll();
for(int i=0;i<testNum;++i) {
sl.search(i);
}
}
- 测试数据
欢迎大家指出bugs和提出优化意见