Algoritmusok és adatszerkezetek II. Horváth Gyula Szegedi Tudományegyetem Természettudományi és Informatikai Kar horvath@inf.u-szeged.hu
6. Ugrólista (Skiplist) Definíció. Olyan adatszerkezet, amelyre teljesül az alábbi három feltétel: 1. Minden cellának az 1. szomszéd kapcsolatát tekintve rendezett lánc. 2. Minden cella k-adik szomszédja megelőzi a láncban a k + 1-edik szomszédját. 3. Bármely x cellára ha y szomszédja x-nek, akkor minden olyan z cellának, amely a láncban x és y között van, bármely szomszédja nem y után van a láncban. 1. ábra. Az 1. rendezett lánc tulajdonság. 1 2 3 4 2. ábra. A 2. előremutató rendezési tulajdonság. x z y 3. ábra. A 3. keresztezés mentesség tulajdonság.
Fej Lab 4 3 2 1 b c e f g h j k l m n o p q r x 4. ábra. Példa ugrólista. A keresztezés mentesség tulajdonság biztosítható úgy, hogy minden cellából a k-adik szintről induló él arra a cellára mutasson, amelyik tőle jobbra az első legalább k magas cella.
Adott cellából előremutató élek számát véletlen válasszuk meg, úgy hogy "jó" eloszlású legyen! n elemet (cellát) tartalmazó ugrólista esetén jelölje N(k) a k magas cellák számát és L k = N(k) n és L k = pl k 1 teljesüljön adott 1 < p < 1 valós számra. Ekkor azaz Mivel így L 1 kifejezhető L 2 -vel Továbbá i=2 1 = L 1 = 1 L i i=1 L i i=2 L i = L 2 + L 3 + = L 2 + pl 2 + p 2 L 2 + L 1 = 1 L 2 p i i=0 p i = 1 i=0 1 p Így L 1 = 1 L 2 1 p. Mivel L 2 = pl 1, azt kapjuk, hogy L 1 = 1 pl 1 1 p L 1 = 1 p
A maximális toronymagasság: L(n)? Az a legkisebb k, amelyre p k n 1, azaz n ( 1 p )k, tehát Hogyan biztosítható ilyen eloszlás? L(n) = log 1/p n private byte randomlevel() { //új toronymagasság véletlen generálása byte i=0; while (i<=magas && Math.random()<prob ) i++; return i;
Fej Lab 4 3 2 1 b c e f g h j k l m n o p q r x
Fej Lab 4 3 2 1 b c e f g h j k l m n o p q r x
Fej Lab 4 3 2 1 b c e f g h j k l m n o p q r x
Fej Lab 4 3 2 1 b c e f g h j k l m n o p q r x
Fej Lab 4 3 2 1 b c e f g h j k l m n o p q r x
Fej Lab 4 3 2 1 b c e f g h j k l m n o p q r x
Fej Lab 4 3 2 1 b c e f g h j k l m n o p q r x
11 10 9 8 7 6 5 4 3 2 1 U[11]............... x y............ U[10] U[9] U[8] U[7] U[6] U[5] U[4] U[3] P U[2] U[1] Q 5. ábra. Ugrólista bővítése.
11 10 9 8 7 6 5 4 3 2 1 U[11]............... x y............ U[10] U[9] U[8] U[7] U[6] U[5] U[4] U[3] P U[2] U[1] Q 6. ábra. Törlés ugrólistából.
public class ULista<E extends Comparable<E>> implements Iterable<E>{ private static final int MaxSzint=32; public UListaPont<E> fej, lab; // protected byte magas; //a legmagasabb torony magassága private double prob=0.5;//küszöb a véletlen toronymagasság generálásához private boolean multi=true;//többszösös elem megengedett-e public static class UListaPont<E extends Comparable<E>>{ private E elem; public UListaPont<E>[] csat; UListaPont(E x, int m){ csat=new UListaPont[m+1]; this.elem=x;
public UListaPont<E> PKeres(E x) { // UListaPont<E> p = fej; // lab.elem=x; for (int i=magas; i>=0; i--) // while (p.csat[i].elem.compareto(x)<0 ) p = p.csat[i]; // p = p.csat[0]; // if ((p!= lab) && p.elem.equals(x)) return p; // else return null; // public E Keres(E x){ // UListaPont<E> p = PKeres(x); // if (p!= null) return p.elem; // else return null; //
public boolean Bovit(E x) { // byte ujszint = randomlevel(); // UListaPont<E> p = fej; // UListaPont<E> q = fej; // lab.elem=x; for (int i=magas; i>=0; i--) {// q=p.csat[i]; while ( q.elem.compareto(x)<0 ){ p = q; q = p.csat[i]; lab.csat[i] = p; if (!multi && q!=lab && q.elem.equals(x)){ return false; else{
UListaPont<E> ujp = new UListaPont<E>(x, ujszint); if (ujszint > magas) { magas=ujszint; lab.csat[ujszint]=fej; for (int i=0; i<=ujszint; i++) { // p=lab.csat[i]; ujp.csat[i]=p.csat[i]; p.csat[i] = ujp; // return true;
public boolean Torol(E x){ UListaPont<E> p = fej; UListaPont<E> q = null; lab.elem=x; for (int i=magas; i>=0; i--) {// q=p.csat[i]; while ( q.elem.compareto(x)<0 ){ p = q; q = p.csat[i]; lab.csat[i] = p; if (q==lab q.elem.compareto(x)!=0 ) return false;
int i=0; while (true){ lab.csat[i].csat[i]=q.csat[i]; i++; if (i>magas lab.csat[i].csat[i]!=q) break; q=null; while (magas>=0 && fej.csat[magas]==lab) magas--; return true; //Torol
public ULista<E> Vag(E x){ UListaPont<E> ujfej=new UListaPont<E>(null, MaxSzint); UListaPont<E> ujlab=new UListaPont<E>(null, MaxSzint); ULista<E> UL2=new ULista<E>(); for (int i=0; i<=maxszint; i++) ujfej.csat[i]=fej.csat[i]; UListaPont<E> p = fej; // UListaPont<E> q = fej; // lab.elem=x; byte magas1=0; for (byte i=magas; i>=0; i--) {// q=p.csat[i]; while ( q.elem.compareto(x)<0 ){ p = q; q = p.csat[i]; ujfej.csat[i]=q; p.csat[i]=ujlab; if (p!=fej && magas1==0) magas1=i;
for (int i=magas1+1; i<=maxszint; i++) fej.csat[i]=ujlab; magas=magas1; UL2.lab=lab; UL2.fej=ujfej; magas1=maxszint; while (magas1>0 && ujfej.csat[magas1]==lab) magas1--; UL2.magas=magas1; this.lab=ujlab; return UL2;
public void Egyesit(ULista<E> U2){ if (U2.Min()==null) return; if (Min()==null){ fej=u2.fej; lab=u2.lab; magas=u2.magas; U2.Uresit(); return; multi=u2.multi; if ( Max().compareTo(U2.Min())>=0 ) throw new RuntimeException("A két halmaz nem erősen diszjunkt"); byte ujmagas= (magas<u2.magas)? U2.magas : magas; for (byte i=maxszint; i>magas; i--) fej.csat[i]=u2.fej.csat[i]; UListaPont<E> p = fej; for (byte i=magas; i>=0; i--){ while (p.csat[i]!=lab) p=p.csat[i]; p.csat[i]=u2.fej.csat[i]; magas=ujmagas; lab=u2.lab; U2.Uresit(); return;
A KERES BOVIT TOROL algoritmusok futási idejének várható értéke: L(n) p + 1 (1 p) = log 1/p n + 1 p (1 p) = O(lgn)