跳跃表原理及实现

一、跳表数据结构

         跳表是有序表的一种,其底层是通过链表实现的。链表的特点是插入删除效率高,但是查找节点效率很低,最坏的时间复杂度是O(N),那么跳表就是解决这一痛点而生的。

        为了提高查询效率,我们可以给链表加上索引,利用二分查找的思路,每两个节点抽取一个索引,根据数据规模,提升索引的高度,索引的最高层级为logN,那么跳跃表支持平均0 (1ogN),这样可以快读提高节点访问速度。由于在原始链表的基础上加索引,这些索引需要额外的存储空间,所以这是典型的通过空间换时间。下图简单描述跳跃表原理:

           如果要访问8这个歌节点元素,在没有索引的情况下,需要遍历链表8次才能找到目标节点,但是通过跳表访问(1 -> 5 -> 7-> 7->7 -> 8) ,只需要访问6次,数据规模越大优势越明显。

          对于提取索引,理论上每隔两个元素生成一个索引节点,但是在具体情况下,链表是动态的,删除和增加节点的时机很难确定,通过两个节点维护索引的方式开销成本很大。那么如何添加索引,一个新增节点要不要加索引,索引加到第几层,为了解决这个问题,可以通过投掷硬币的方式(随机数模2),连续投掷正面几次,那么这个次数就是索引的层级。

二、跳表代码实现

  1、跳表结构、操作函数声明
#ifndef SKIPLINKLIST_H__
#define SKIPLINKLIST_H__

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <time.h>
#include <math.h>
#include <unistd.h>

#define MAX_LEVEL 8

//定义数据域
typedef  int SkipLinkListData;

typedef  struct skiplinklistnode
{
    int  level;
    SkipLinkListData  data;
    struct skiplinklistnode*  next;
    struct skiplinklistnode*  down;

} SkipLinkListNode;

/**
 * 创建链表节点
*/
SkipLinkListNode* create_skiplinklist_node(SkipLinkListData data,int level);

/**
 * 插入节点
*/
void  insert_skiplinklist_node(SkipLinkListNode* head,SkipLinkListData data);

/**
 * 维护索引
*/
void create_skiplinklist_index(SkipLinkListNode** index,SkipLinkListNode* node);

/**
 * 随机数投硬币获取索引层高
*/
int   random_skiplinklistnode_level();


/**
 * 遍历跳表
*/
void  show_skiplinglistnode_all(SkipLinkListNode* head);

/**
 * 查询节点
*/
SkipLinkListNode*  search_skiplinklistnode(SkipLinkListNode* head,SkipLinkListData data);

/**
 * 删除跳表元素 重组索引  s
 * 删除的过程其实也是查找
*/
void    delete_skiplinklistnode(SkipLinkListNode* head,SkipLinkListData data);

#endif
2、跳表增删查操作定义

#include "./skiplinklist.h"


SkipLinkListNode* create_skiplinklist_node(SkipLinkListData data,int level){
   SkipLinkListNode*  node = (SkipLinkListNode*) malloc(sizeof(SkipLinkListNode));
   if(node==NULL)
   {
    perror("create node  fail");
    return NULL;
   }
   node->level = level;
   node->data =  data;
   node->next = NULL;
   node->down = NULL;
   return node;
}

void insert_skiplinklist_node(SkipLinkListNode *head, SkipLinkListData data)
{
  SkipLinkListNode *down_ptr = head->down;
  if (down_ptr == NULL)
  {
    head->down =  create_skiplinklist_node(data, 0);
    return;
  }
  int level = random_skiplinklistnode_level(); 
  if(down_ptr->level<level)
  {
     level = down_ptr->level +1;
  }
  SkipLinkListNode* index_node = NULL;
   /// 当前层级小于随机高度时候,需要升级索引
  if(down_ptr->level<level){
      /// 向上升级一层索引
      level = down_ptr->level +1;
      SkipLinkListNode* down_node = create_skiplinklist_node(down_ptr->data,level);
      index_node = create_skiplinklist_node(data,level);
      down_node->next = index_node;
      down_node->down = down_ptr;
      head->down = down_node;
  } 
   /// 搜索节点
  while (down_ptr!= NULL && down_ptr->data<=data && down_ptr->level>0)
  {
      SkipLinkListNode* next_ptr  = down_ptr->next;
      // 查找当前层级索引,定位到离当前数值的最大索引值
      while (next_ptr != NULL && next_ptr->data<=data && next_ptr->next!=NULL)
      {
         next_ptr = next_ptr->next;
      }
      /// 维护索引
      if(down_ptr->level<=level){
          SkipLinkListNode* new_node = create_skiplinklist_node(data, down_ptr->level);
          if(next_ptr==NULL)
          {
            /// 如果当前层索引到达最后一个值,则跳到下一层索引
            down_ptr->next=new_node;
          }
          else
          {
           new_node->next = next_ptr->next;
           next_ptr->next = new_node; 
          }
          create_skiplinklist_index(&index_node,new_node);
      }
      ///跳转下一层索引
      down_ptr = next_ptr != NULL?next_ptr->down:down_ptr->down;    
    }
    /// 遍历链表  数据插入链表
    while (down_ptr != NULL&&down_ptr->next!=NULL&&down_ptr->next->data<data)
    {
         down_ptr = down_ptr->next;
    }
    SkipLinkListNode*  node = create_skiplinklist_node(data, 0);
    SkipLinkListNode*  next_node = down_ptr->next;
    down_ptr->next = node;
    node->next = next_node;
    if(index_node!=NULL)
    {
      create_skiplinklist_index(&index_node,node);
    }
}

void create_skiplinklist_index(SkipLinkListNode** index_node,SkipLinkListNode* new_node)
{
  if ((*index_node) == NULL)
  {
    (*index_node) = new_node;
  }
  else
  {
    SkipLinkListNode* tmp_node = (*index_node);
    while (tmp_node != NULL)
    {
      if (tmp_node->down == NULL)
      {
        tmp_node->down = new_node;
        break;
      }
      tmp_node = tmp_node->down;
    }
  }
}

int  random_skiplinklistnode_level()
{
   int level = 0;
   int mod = 2;
   while (rand() % mod == 0 )
   {
     level++;
   }
   return level>=MAX_LEVEL?MAX_LEVEL:level;
}

void  show_skiplinglistnode_all(SkipLinkListNode* head)
{
 SkipLinkListNode*  down_ptr = head->down;
 while (down_ptr!=NULL)
 {
    if(down_ptr->level==0)
    {
        printf("原 始链表: %d ",down_ptr->data);
    }
    else
    {
       printf("第%d层索引: %d ",down_ptr->level,down_ptr->data);
    }
   
    SkipLinkListNode*  next_ptr = down_ptr->next;
    while (next_ptr!=NULL)
    {
       printf("%d ",next_ptr->data);
       next_ptr = next_ptr->next;
    }
    down_ptr= down_ptr->down; 
    printf("\n");
 }
  printf("\n");
}

SkipLinkListNode*  search_skiplinklistnode(SkipLinkListNode* head,SkipLinkListData data)
{
    SkipLinkListNode* down_ptr =  head->down;
    /// 索引查找
    while (down_ptr!=NULL && down_ptr->data<=data && down_ptr->level>0)
    {
      printf("遍历第%d层次节点:%d\n",down_ptr->level,down_ptr->data);
      if(down_ptr->next!=NULL && down_ptr->next->data>data)
      {
         down_ptr = down_ptr->down;
         continue;
      }
      SkipLinkListNode* next_ptr  = down_ptr->next;
      while (next_ptr != NULL && next_ptr->data<=data && next_ptr->next!=NULL&& next_ptr->next->data<=data)
      {
         next_ptr = next_ptr->next;
         printf("遍历第%d层次节点:%d\n",next_ptr->level,next_ptr->data);
      }
      ///跳转下一层索引
      down_ptr = next_ptr != NULL?next_ptr->down:down_ptr->down;   
    }
    //到达底层链表 遍历目标值
    while (down_ptr!=NULL)
    {
       if(down_ptr->data==data)
       {
          printf("遍历第%d层次节点,命中目标%d\n",down_ptr->level,down_ptr->data);
          return down_ptr;
       }
       down_ptr =  down_ptr->next;
    }
    printf("遍历结束目标节点%d不存在\n",data);
    printf("\n");
    return NULL;
}

void delete_skiplinklistnode(SkipLinkListNode *head, SkipLinkListData data)
{
   printf("删除元素开始\n");
  SkipLinkListNode *down_ptr = head->down;
  while (down_ptr != NULL && down_ptr->data < data && down_ptr->level > 0)
  {
    printf("遍历第%d层次节点:%d\n", down_ptr->level, down_ptr->data);
    if (down_ptr->next != NULL && down_ptr->next->data>=data)
    {
      /// 处理要删除的节点存在索引节点
      if(down_ptr->next->data==data)
      {
         SkipLinkListNode* index_ptr = down_ptr->next;
         down_ptr->next = down_ptr->next->next;
         printf("删除第%d层索引%d\n",index_ptr->level,index_ptr->data);
         free(index_ptr);
      }
      down_ptr = down_ptr->down;
      continue;
    }
    SkipLinkListNode *next_ptr = down_ptr->next;
    while (next_ptr != NULL && next_ptr->data < data && next_ptr->next != NULL && next_ptr->next->data <= data)
    {
      if(next_ptr->next->data==data)
      {
        SkipLinkListNode*  index_node= next_ptr->next;
        next_ptr->next = next_ptr->next->next;
        free(index_node);
        continue;
      }
      next_ptr = next_ptr->next;
      printf("遍历第%d层次节点:%d\n", next_ptr->level, next_ptr->data);
    }
    /// 跳转下一层索引
    down_ptr = next_ptr != NULL ? next_ptr->down : down_ptr->down;
  }

  while (down_ptr!=NULL)
  {
     if(down_ptr->next!=NULL && down_ptr->next->data==data)
     {
        SkipLinkListNode* traget_node =  down_ptr->next;
        down_ptr->next =  down_ptr->next->next;
        free(traget_node);
     }
     down_ptr=down_ptr->next;
  }
  printf("删除元素结束\n");

}

三、跳表测试


void  test_skiplinklist()
{

 SkipLinkListNode*  head = create_skiplinklist_node(0,0);
 SkipLinkListData  i;
 int c = 30;
 for(i=1;i<c;i++)
 {
    insert_skiplinklist_node(head,i);   
 }
 
 show_skiplinglistnode_all(head);
 search_skiplinklistnode(head,28);
 delete_skiplinklistnode(head,15);
 show_skiplinglistnode_all(head);
 
}

  • 12
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
课程设计任务书 "一、设计题目 " "基于微程序控制器的简单计算机系统设计与实现 " "二、设计内容 " "设计模型机系统的总体结构、指令系统和时序信号。充分利用FPGA以及相关外围" "器件,设计实现模型机的整机系统。要求所设计的整机系统能支持自动和单步运" "行方式,能正确地执行存放在主存中的程序的功能,对主要的数据流和控制流通" "过LED适时显示信息。尽可能利用EDA软件对模型机系统中各部件进行仿真分析和" "功能验证。在学有余力的前提下,可为模型机增加更多的扩展功能。 " "三、设计要求 " "支持算术运算、逻辑运算、存储器读写、寄存器间数据传送等几类指令; " "支持立即数寻址、直接寻址、隐含寻址、寄存器寻址等几种基本数据寻址方式和" "顺序寻址、跳跃寻址方式; " "支持10条以上的指令; " "能运行由自己设计的指令系统构成的一段程序,程序执行功能正确。 " "四、设计流程 " "根据课程设计指导书的要求,制定出设计方案; " "画出模型计算机系统的原理框图和器件连接图,分析器件连接图中各器件不同引" "脚的功能,哪些可以固定连接,哪些需要通过微程序来控制,以及这些控制信号" "的有效形式; " "画出各指令的指令周期流程图和所需要的控制信号; " "设计出实现指令功能的微程序控制器或硬布线控制器; " "布线、调试、验收; " "课程设计报告和总结。 " "五、成绩评定 " " " "成绩评定根据考勤、课程设计的过程、课程设计的效果、课程设计报告质量等进" "行综合评定;其中设计过程和结果占70%,课程设计报告占30%;课程设计的成绩" "评定等级为不及格、及格、中、良好、优秀五级;对基本功能进行扩展或设计具" "有非常鲜明的特征和一定程度的创新,可根据实际情况加分。 " "六、设计报告要求 " " " "课程设计报告主要内容包括:设计题目、设计目的、设备器材、设计原理及内容" "、设计步骤、遇到的问题及解决方法、设计总结、参考文献等。要求在适当位置" "配合相应的实验原理图、数据通路图、微程序流程图、实验接线图、微指令代码" "表等图表进行说明。总结部分主要写设计工作简介以及设计体会。应做到文理通" "顺,内容正确完整,书写工整,装订整齐。课程设计报告采用《计算机组成原理》" "专用设计报告模板,A4纸双面打印,除框图外需附下载的设计图以及微指令控制" "点图。 " "七、时间安排 " " 课程设计的总体时间为2周,具体安排如下: " "第1天:到实验室布置任务和集中讲解。 " "第2天:学生自己设计,选择并熟悉自己所要的芯片。 " "第3天:领导线和芯片,进行芯片功能测试,在此基础上修改完善原设计方案。 " "第4天到第10天:实验室调试、验收。 " "八、主要参考文献 " "秦磊华,王小兰. 计算机组成原理实验指导及课程设计指导书(基于EDA平台). " "武汉:华中科技大学出版社,2010年. " "秦磊华,吴非,莫正坤.计算机组成原理. 北京:清华大学出版社,2011年. " "DAVID A.PATTERSON(美).计算机组成与设计硬件/软件接口(原书第3版).北京: " "机械工业出版社. 2007年. " "袁春风编著. 计算机组成与系统结构. 北京:清华大学出版社,2011年. " " " " " 目 录 1 课程设计概述 3 1.1 课设目的 3 1.2 设计任务 3 1.3 设计要求 3 2 实验原理与环境 4 2.1 实验原理 4 2.2 实验环境 4 3 总体方案设计 5 3.1 需求分析 5 3.2 硬件设计 5 3.3 软件设计 8 4 详细设计与实现 10 4.1 选用芯片 10 4.2 硬件实现 11 4.3 软件实现 14 5 实验过程与调试 19 5.1 仿真XXX 19 5.2 可自行安排章节 19 5.3 主要故障与调试 19 5.4 功能测试 19 5.5 实验流程图 20 6 设计总结与心得 21 6.1 课设总结 21 6.2 课设心得 21 参考文献 22 课程设计概述 请仔细阅读所有的批注,阅读理解后删除批注 模板各个标题下面的内容仅是举例,作者应依照自己思想重写该部分内容 1、格式不要轻易改动,严格按照模板来,不要自创格式。 2、所以批注阅读后一定要删除 3、模板中的图示意图,不能照搬,要根据自己的设计来画 4、参考文献只是格式和引用方式参考,列出自己实际参考文献 5、图中的文字一定要清晰。 6、所有的表和图都必须有名字和编号。 1 课设目的 计算机组成原理是计算机专业的核心专业基础课。课程设计属于设计型实验,不仅锻 炼学生简单计算机系统的设计能力,而且通过进行设计及实现,进一步提高分析和解决 问题的能力。(自己写) ……(其它内容) 2 设计任务 计算

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值