随机化算法:跳跃表

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

随机化算法:跳跃表_第1张图片

(1)注意几个特点:

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

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

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

#include "stdafx.h"
#include "malloc.h"
#include "stdlib.h"
#include "time.h"
#define N 10
typedef 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--;
        }
    }

你可能感兴趣的:(随机化算法:跳跃表)