跳跃表
画图理解
每一个结点都随机分为不同的层数,除第一层外,每一层均跳跃着连接结点
跳跃表实现
#define MAX_LEVEL 6 //最大层次 层次随机给
typedef int KeyType;
typedef struct {} Record;
typedef struct SkipListNode//结点
{
KeyType key;//关键码
int value;//关键码对应的值
int curlevel;//当前结点所含有的层数
struct SkipListNode* forward[]; //柔性数组(数组大小根据要求而定) 最小为1
//数组每个元素都是指向结点的指针
}SkipListNode;
typedef struct SkipList//跳跃表
{
SkipListNode* head;//头结点
int level;//层高 整个跳跃表最大层高(规定最大层高为6)
int cursize;//当前元素个数
}SkipLinkList;
SkipLinkList* CreateSkipList();//创建跳跃表
bool InsertNode(SkipLinkList* plist, KeyType key, int value);//插入结点
SkipListNode* SearchKey(const SkipLinkList* plist, KeyType key);//按照关键码key查询
void PrintSkipList(const SkipLinkList* plist);//打印跳跃表
bool RemoveNode(SkipLinkList* plist, KeyType key);//删除指定关键码key
//按照结点所需要的层数level分配空间
static SkipListNode* Buynode(int level)
{
SkipListNode* s = (SkipListNode*)malloc(sizeof(SkipListNode) +
sizeof(SkipListNode*) * (level + 1));
//因为柔性数组里面放的是SkipListNode类型的指针
if (NULL == s) exit(1);
memset(s, 0, sizeof(SkipListNode) + sizeof(SkipListNode*) * (level + 1));//初始化为0
return s;
}
//根据跳跃表大小分配空间
static SkipLinkList* BuyList()
{
SkipLinkList* s = (SkipLinkList*)malloc(sizeof(SkipLinkList));
if (NULL == s) exit(1);
memset(s, 0, sizeof(SkipLinkList));
return s;
}
//释放空间
static void FreeNode(void* p)
{
free(p);
}
//随即层数
static int randomLevel()
{
int level = 0;
while (rand() < RAND_MAX / 2 && level < MAX_LEVEL) //RAND_MAX最大伪随机数
{
++level;
}
return level;
}
SkipLinkList* CreateSkipList()
{
SkipLinkList* plist = BuyList();
plist->cursize = 0;
plist->level = 0;
plist->head = Buynode(MAX_LEVEL);//设置头结点
plist->head->key = INT_MIN;//表示最小整数
for (int i = 0; i <= MAX_LEVEL; ++i)//将头结点的柔性数组置空
{
plist->head->forward[i] = NULL;
}
return plist;
}
bool InsertNode(SkipLinkList* plist, KeyType key, int value)
{
assert(plist != NULL);
bool res = false;
SkipListNode* update[MAX_LEVEL + 1] = { 0 };
SkipListNode* p = plist->head;
for (int i = plist->level; i >= 0; i--)
{
if (p->forward[i] != NULL && p->forward[i]->key < key)
{
p = p->forward[i];
}
update[i] = p;//存放要插入结点的前驱
}
p = p->forward[0];//存放要插入结点的后继(比要插入结点key值大的最小值)
if (p == NULL || p->key != key)
{
res = true;
int newlevel = randomLevel();//插入结点的层高
if (newlevel > plist->level)//如果大于设定的最大层高,则指向头结点
{
for (int i = plist->level + 1; i <= newlevel; i++)
{
update[i] = plist->head;
}
plist->level = newlevel;//更新层高
}
SkipListNode* s = Buynode(newlevel);
s->key = key;
s->value = value;
s->curlevel = newlevel;
for (int i = 0; i <=newlevel; i++)
{
s->forward[i] = update[i]->forward[i];//s的后继=前驱的后继
update[i]->forward[i] = s;//前驱的后继=s
}
}
return res;
}
SkipListNode* SearchKey(const SkipLinkList* plist, KeyType key)
{
assert(plist != NULL);
SkipListNode* p = plist->head;
for (int i = plist->level; i >= 0; i--)
{
if (p->forward[i] != NULL && p->forward[i]->key < key)
{
p = p->forward[i];
}
}
p = p->forward[0];//相当于p=p->next;
if (p != NULL && p->key != key)
{
p = NULL;
}
return p;
}
void PrintSkipList(const SkipLinkList* plist)
{
assert(plist != NULL);
SkipListNode* p = plist->head;
for (int i = 0; i <= plist->level; ++i)
{
printf("Level: %d ", i);
SkipListNode* pnode = p->forward[i];
while (pnode != NULL)
{
printf("{%d:%d } ", pnode->key, pnode->curlevel);
pnode = pnode->forward[i];//相当于pnode=pnode->next
}
printf("\n");
}
printf("\n");
}
bool RemoveNode(SkipLinkList* plist, KeyType key)
{
assert(plist != NULL);
bool res = false;
SkipListNode* update[MAX_LEVEL + 1] = { 0 };
SkipListNode* p = plist->head;
for (int i = plist->level; i >= 0; --i)
{ //从最高层开始查找
while (p->forward[i] != NULL && p->forward[i]->key < key)//在第i层找到的结点比key小,就让p指向下一个结点,直到找到key的前驱节点
{
p = p->forward[i];
}
update[i] = p;//记存放待删除结点的前驱
}
p = p->forward[0];//p指向第0层待删除结点
if (p != NULL && p->key == key)//如果p的key等于要删除的key的值
{
res = true;
for (int i = 0; i <= plist->level; ++i)
{
if (update[i]->forward[i] != p)
{
break;//如果超出p的层高就退出
}
update[i]->forward[i] = p->forward[i];
}
FreeNode(p);//释放空间
plist->cursize--;//链表元素减少
while (plist->level > 0 && plist->head->forward[plist->level] == NULL)//如果删除最大层高
{
--plist->level;//层高减少
}
}
return res;
}