随机化算法:跳跃表

来源:互联网 发布:高中网络教学视频 编辑:程序博客网 时间:2024/05/18 01:16

摘要:跳跃表主要是用来减少查找的代价,作为单向链表,如果搜寻一个数据需要O(N)的时间代价,但是如果采用随机化跳跃表则可以大大减少搜寻代价.

这里写图片描述

(1)注意几个特点:

[1]跳跃表m阶指针所连接的元素至少具有m阶的指针.

[2]主要难点集中在查询,插入,以及删除操作.这比普通链表要复杂的多.

[3]首先看基本数据结构.

#include "stdafx.h"#include "malloc.h"#include "stdlib.h"#include "time.h"#define N 10typedef struct Listrecord * List;struct Listrecord{    int Element;    int size;//该节点有size阶    List *Pointarray;//存放了所有阶数的指针};int GetRand()//获取随机数{    int i,size = 0;    while(size <= N)    {        i = rand()%2;        if (i == 1)            size++;        else           return (++size);    }    return N;}void Initialize(List L,int size){    if(size > 0)    {        L->Element = -1;        L->Pointarray = (List*)malloc(sizeof(List)*size);        L->size = size;        for(int i = 0;i<=size;i++)            L->Pointarray[i] = NULL;    }}

【2】接着看剩下的操作.如果该节点最高阶指针所指向的元素都依旧小于要找的数据,则大胆的跳到最高阶指针所指的地方吧,否则就要对更低阶的指针进行搜索,因为该元素一定在当前节点和最高阶指针所指节点之间.

List Find(List head,int x){    int k = head->size-1;    List L = head;    while(k>=0) {    if(L->Pointarray[k]==NULL)    {        k--;        continue;    }        if(L->Pointarray[k]->Element < x)//还没有找到        {            L = L->Pointarray[k];            k = L->size-1;        }        else if(L->Pointarray[k]->Element == x)//找到所需元素            return L->Pointarray[k];        else//判定元素所在的区间        {            if (k>=0)                k--;//降一阶,继续搜寻            else                return NULL;        }}        return NULL;}

【3】插入操作,这个要比Find麻烦一点,首先要明确,插入的节点可能会让某些原来的空指针有了着落。同时也有插入位置两边节点指针的调整,注意的细节较多.

void ConnectPoint(List head,List Newnode,int x){    int k = head->size-1,size = Newnode->size,k2=0;    List L = head,Thenode;    while(k>=0)    {        if(L->Pointarray[k] == NULL)    //第一种降阶情况        {            if (k==0)                Thenode = NULL;//保存后半部分            if (size-1>=k)                L->Pointarray[k] = Newnode;                 k--;//降阶            continue;        }         if (L->Pointarray[k]->Element > x)//第二种降阶情况        {            if (k==0)                Thenode = L->Pointarray[0];//保存后半部分            if (size-1>= k)                    L->Pointarray[k] = Newnode;                        k--;//降阶        }        else //继续向前        {            L = L->Pointarray[k];            k = L->size-1;        }    }    //处理后面的拼接    while(k2<=Newnode->size-1)        {               if (Thenode!=NULL)               {                if (k2 <= Thenode->size-1)                Newnode->Pointarray[k2++] = Thenode;                else                    Thenode = Thenode->Pointarray[Thenode->size-1];               }               else                   Newnode->Pointarray[k2++] = NULL;     }}void Insert(List head,int x,int size){    int k = size;//GetRand();    List Newnode;    Newnode = (List)malloc(sizeof(Listrecord)*k);    Initialize(Newnode,k);    Newnode->Element = x;    ConnectPoint(head,Newnode,x);}

[4]删除节点,关键是在查找节点的过程中要特别关注使得指针降阶的节点.注意删除的节点可能使得某个指针指向空,或者指向被删除节点后面的节点.需要在查找的时候就将所有指针安排好

void Delete(List head,int x){       int k = head->size-1;    List L,Deletednode;    L = head;    if(Find(head,x)==NULL)        return;    while(k>=0)    {        if (L->Pointarray[k]==NULL)            k--;        else if(L->Pointarray[k]->Element < x)        {            L = L->Pointarray[k];            k = L->size-1;        }        else if (L->Pointarray[k]->Element > x)            k--;        else //找到deletednode        {            Deletednode = L->Pointarray[k];            L->Pointarray[k] = Deletednode->Pointarray[k];            k--;        }    }
1 0