实现跳表SkipList

实现语言为java

package com.github.ralgond.yousuggest;

import java.util.Iterator;
import java.util.Random;

public class SkipListSet<E extends Comparable<? super E>> implements Iterable<E> {
	private class Node {
		public E data;
		public Object nextArray[];
		public Node(E data, int level) {
			this.data = data;
			nextArray = new Object[level];
		}
		public Node next(int level) {
			return (Node)nextArray[level];
		}
		public void setNext(int level, Node n) {
			nextArray[level] = n;
		}
		public int level() {
			return nextArray.length;
		}
	}
	private final static int MAX_LEVEL = 10;
	
	private Node head;
	private Object[] prevArray;
	private Random rand = new Random(1);
	private int count = 0;
	
	public SkipListSet() {
		head = new Node(null, MAX_LEVEL);
		prevArray = new Object[MAX_LEVEL];
	}
	
	private Node getPrev(int level) {
		return (Node)prevArray[level];
	}
	
	private void setPrev(int level, Node n) {
		prevArray[level] = n;
	}
	
	protected boolean findAndRecordPrev(E e) {
		for (int i = 0; i < MAX_LEVEL; i++) {
			prevArray[i] = head;
		}
		
		int level = head.level() - 1;
		Node curr = head;
		while (level >= 0) {
			while (curr.next(level) != null && curr.next(level).data.compareTo(e) < 0) {
				curr = curr.next(level);
			}
			setPrev(level, curr);
			level--;
		}
		
		if (getPrev(0).next(0) == null)
			return false;
		
		return getPrev(0).next(0).data.equals(e);
	}
	
	public boolean contains(E e) {
		return findAndRecordPrev(e);
	}
	
	protected int randomLevel() {
		int l = 1;
		while (rand.nextInt()%2 == 1) {
			l++;
		}
		l = l < MAX_LEVEL? l : MAX_LEVEL;
		return l;
	}
	
	public void add(E e) {
		boolean found = findAndRecordPrev(e);
		if (found)
			return;
		
		int randLevel = randomLevel();
		Node n = new Node(e, randLevel);
		
		for (int l = 0; l < randLevel; l++) {
			n.setNext(l, getPrev(l).next(l));
			getPrev(l).setNext(l, n);
		}
		count++;
	}
	
	public void remove(E e) {
		boolean found = findAndRecordPrev(e);
		if (!found)
			return;
		
		Node n = getPrev(0).next(0);
		assert(n.data.equals(e));
		int level = n.level();
		for (int l = 0; l < level; l++) {
			getPrev(l).setNext(l, n.next(l));
		}
		count--;
	}

	public Iterator<E> iterator() {
		return new Iterator<E>() {
			Node curr = head.next(0);
			public boolean hasNext() {
				return curr != null;
			}

			public E next() {
				Node ret = curr;
				curr = curr.next(0);
				return ret.data;
			}
			
		};
	}
	
	public int size() {
		return count;
	}
	
	public void clear() {
		for (int i = 0; i < head.level(); i++) {
			head.setNext(i, null);
		}
		count = 0;
	}
}

单元测试

package com.github.ralgond.yousuggest;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import java.util.Iterator;

import org.junit.Test;

public class SkipListSetTest {
	
	public void assertEquals2(Iterator<Integer> it, int... ints) {
		for (int i = 0;i < ints.length; i++) {
			int j = ints[i];
			assertEquals((Integer)j, it.next());
		}
		assertFalse(it.hasNext());
	}
	
	@Test
	public void test0() {
		int a[][] = {
				{6,7,8,9},
				{6,7,9,8},
				{6,8,7,9},
				{6,8,9,7},
				{6,9,8,7},
				{6,9,7,8},
				{7,6,8,9},
				{7,6,9,8},
				{7,8,6,9},
				{7,8,9,6},
				{7,9,8,6},
				{7,9,6,8},
				{8,7,6,9},
				{8,7,9,6},
				{8,6,7,9},
				{8,6,9,7},
				{8,9,6,7},
				{8,9,7,6},
				{9,7,8,6},
				{9,7,6,8},
				{9,8,7,6},
				{9,8,6,7},
				{9,6,8,7},
				{9,6,7,8}
		};
		
		SkipListSet<Integer> set = new SkipListSet<>();
		
		for (int i = 0; i < a.length; i++) {
			int[] b = a[i];
			for (int j = 0; j < b.length; j++) {
				set.add(b[j]);
			}
			
			assertEquals2(set.iterator(), 6,7,8,9);
			assertEquals(4, set.size());
			
			for (int j = 0; j < b.length; j++) {
				set.remove(b[j]);
			}
			
			assertEquals(0, set.size());
			assertFalse(set.iterator().hasNext());
		}
	}
	
	@Test
	public void testRemove1() {
		SkipListSet<Integer> set = new SkipListSet<>();
		set.add(6);
		set.add(9);
		set.add(8);
		set.add(7);
		
		set.remove(7);
		
		assertEquals2(set.iterator(), 6,8,9);
	}
	
	@Test
	public void testRemove2() {
		SkipListSet<Integer> set = new SkipListSet<>();
		set.add(6);
		set.add(9);
		set.add(8);
		set.add(7);
		
		set.remove(7);
		set.remove(8);
		
		assertEquals2(set.iterator(), 6,9);
	}
	
	@Test
	public void testRemove3() {
		SkipListSet<Integer> set = new SkipListSet<>();
		set.add(6);
		set.add(9);
		set.add(8);
		set.add(7);
		
		set.remove(7);
		set.remove(8);
		set.remove(9);
		
		assertEquals2(set.iterator(), 6);
	}
	
	@Test
	public void testRemove4() {
		SkipListSet<Integer> set = new SkipListSet<>();
		set.add(6);
		set.add(9);
		set.add(8);
		set.add(7);
		
		set.remove(6);
		set.remove(7);
		set.remove(8);
		set.remove(9);
		
		assertFalse(set.iterator().hasNext());
	}
	

	@Test
	public void testRemoveAndAdd1() {
		SkipListSet<Integer> set = new SkipListSet<>();
		set.add(6);
		set.add(9);
		set.add(8);
		set.add(7);
		
		set.remove(6);
		
		set.add(6);
		
		assertEquals2(set.iterator(), 6,7,8,9);
	}
	
	@Test
	public void testRemoveAndAdd2() {
		SkipListSet<Integer> set = new SkipListSet<>();
		set.add(6);
		set.add(9);
		set.add(8);
		set.add(7);
		
		set.remove(7);
		
		set.add(7);
		
		assertEquals2(set.iterator(), 6,7,8,9);
	}
	
	@Test
	public void testRemoveAndAdd3() {
		SkipListSet<Integer> set = new SkipListSet<>();
		set.add(6);
		set.add(9);
		set.add(8);
		set.add(7);
		
		set.remove(6);
		set.remove(7);
		set.remove(8);
		set.remove(9);
		
		set.add(6);
		set.add(9);
		set.add(8);
		set.add(7);
		
		assertEquals2(set.iterator(), 6,7,8,9);
	}
	
	@Test
	public void testContains() {
		SkipListSet<Integer> set = new SkipListSet<>();
		set.add(6);
		set.add(9);
		set.add(8);
		set.add(7);
		
		assertTrue(set.contains(6));
		assertTrue(set.contains(7));
		assertTrue(set.contains(8));
		assertTrue(set.contains(9));
		
		assertFalse(set.contains(0));
	}
	
	@Test
	public void testClear() {
		SkipListSet<Integer> set = new SkipListSet<>();
		set.add(6);
		set.add(9);
		set.add(8);
		set.add(7);
		
		set.clear();
		assertEquals(0, set.size());
		

		assertFalse(set.contains(6));
		assertFalse(set.contains(7));
		assertFalse(set.contains(8));
		assertFalse(set.contains(9));
	}
	
	@Test
	public void testDup() {
		SkipListSet<Integer> set = new SkipListSet<>();
		set.add(6);
		set.add(9);
		set.add(8);
		set.add(7);
		
		set.add(6);
		set.add(9);
		set.add(8);
		set.add(7);
		
		assertEquals2(set.iterator(), 6,7,8,9);
		assertEquals(4, set.size());
	}
}
posted @ 2021-01-12 19:32  ralgo  阅读(79)  评论(0)    收藏  举报