动手实现 数据结构 之 “跳跃链表”

来源:互联网 发布:快速拷贝软件fastcopy 编辑:程序博客网 时间:2024/04/29 13:26

C语言 和 随机数原理 实现的跳跃链表

跳跃链表是数组二分查找的一种扩展形式,平均查找时间复杂度等价于二分查找,由能够动态的插入元素 解决了二分查找数组无法高效添加元素的问题

 // 跳跃链表可以有多级指针这里简单的用 3 级指针来讲 level 3->-------------------<-->-----------------------<-->-----------------<-level 2->-------------------<-->------------<-->-------<-->-----------------<-level 1->-----------<-->----<-->----<-->----<-->-------<-->------<-->-------<-data  beforeFirst    5       7       23      25         30        35      afterLast   // beforeFirst 和 afterLast 作为辅助节点 各有3级指针 // 5 有 1 级指针 // 7 有 3 级指针 // 23 有 1 级指针 // 25 有 2 级指针 // 30 有 3 级指针 // 35 有 1 级指针 // // 每一个节点都可以通过左边指针找到前一个元素,右边指针找到后一个元素 // // 查找 35 不用像链表一样一个一个向后查找,可以通过高等级的指针跳跃查找 // 就比如 查找 35 不用从 5 一个一个查找到最后, // 只需通过 beforeFirst 的第三级指针找到 7,再从 7 的第三级指针找到 30,再从 30 的第一级指针找到 35 // // // 节点的指针级数是通过随机数生成的,一级指针占数组的一半,二级指针占一级指针的一半, 三级指针占二级指针的一半,以此类推 // 因此具查找效率 接近于 二分查找 // // // 跳跃链表删除 25 只需 将节点23的一级指针指向30, 把30的一级指针指向23, // 再将节点7的二级指针指向30, 把30的二级指针指向7 // 然后释放节点内存


#include <stdio.h>#include <stdlib.h>#include <time.h>typedef int bool;typedef struct Node {    int level;    struct Node ** front;    struct Node ** back;        int data;}Node;typedef struct JumpList {    struct Node * beforeFirst;// 第一个元素的前一个元素    struct Node * afterLast;  // 最后一个元素的后一个元素}List;#define MAX_LEVEL 5#define MAX 9999unsigned short GetLevel() {    unsigned short level = 1;    unsigned long randomN = (unsigned long)(rand() % MAX);    double n = MAX / 2.0;    while (randomN < n && level < MAX_LEVEL) {        n /= 2.0;        ++level;    }    return level;}struct Node * MakeNode(int level) {    struct Node * node = (struct Node*)malloc(sizeof(struct Node));    node->front = (struct Node**)malloc(level*sizeof(struct Node*));    node->back = (struct Node**)malloc(level*sizeof(struct Node*));    node->level = level;    return node;}void DestroyNode(struct Node * node) {    free(node->front);  // delete[] node->front    free(node->back);   // delete[] node->back    free(node);         // delete node}// 使用链表前必须 调用Initvoid Init(struct JumpList * list) {    srand((unsigned)time(0));    list->beforeFirst = MakeNode(MAX_LEVEL+1);    list->afterLast = MakeNode(MAX_LEVEL+1);    for(int i=0; i<MAX_LEVEL; i++) {        list->beforeFirst->front[i] = NULL;        list->beforeFirst->back[i] = list->afterLast;        list->afterLast->front[i] = list->beforeFirst;        list->afterLast->back[i] = NULL;    }}// 使用完需要使用Destroy将内存释放void Destroy(struct JumpList * list) {    struct Node* back;    for(struct Node* p=list->beforeFirst; p != list->afterLast; p=back) {        back = p->back[0];        DestroyNode(p);    }    DestroyNode(list->afterLast);}bool IsEmpty(struct JumpList * list) {    return list->beforeFirst->back[0] == list->afterLast;}// 在节点 pos 后插入一个节点 数据为datavoid InsertNodeAfter(struct Node* pos, int data) {    struct Node * node = MakeNode(GetLevel());    node->data = data;        struct Node * pre = pos;    struct Node * nex = pos->back[0];    for(int i=0; i<node->level; i++) {        node->front[i] = pre;        node->back[i] = nex;        pre->back[i] = node;        nex->front[i] = node;                while (pre->level < i+2)            pre = pre->front[i];        while (nex->level < i+2)            nex = nex->back[i];    }}// 删除 list 中 pos 节点 (end 前一个元素是最后一个元素,不能删除 end 因为 end 是辅助节点不用于存储)void RemoveNode(struct Node* pos) {    struct Node * pre, * nex;    for(int i=0; i<pos->level; i++) {        pre = pos->front[i];        nex = pos->back[i];        pre->back[i] = nex;        nex->front[i] = pre;    }    DestroyNode(pos);}// 在链表中从头到尾 查找第一个数据为data 的节点struct Node* SearchList(struct JumpList * list, int data) {    int i = MAX_LEVEL-1;    struct Node * node = list->beforeFirst;    while (i >= 0) {        if(node->back[i] == list->afterLast) {            --i;        } else if(data > node->back[i]->data) {            --i;        } else if (node->data == data) {            break;        } else {            node = node->back[i];        }    }    return node;}void PrintList(struct JumpList * list) {    for(struct Node* p=list->beforeFirst->back[0]; p != list->afterLast; p=p->back[0]) {        printf("%d  ", p->data);    }    printf("\n");}int main(void){    List list;    Init(&list);        printf("is empty %d\n",IsEmpty(&list));    InsertNodeAfter(list.beforeFirst, 1);    InsertNodeAfter(list.beforeFirst, 2);    InsertNodeAfter(list.beforeFirst, 3);    InsertNodeAfter(list.beforeFirst, 4);    InsertNodeAfter(list.beforeFirst, 5);        struct Node * searchResult = SearchList(&list, 1);    printf("search %d\n", searchResult->data);    RemoveNode(searchResult);    PrintList(&list);        Destroy(&list);    return 0;}



0 0