当前位置: 首页 > news >正文

跳表的C语言实现

跳表(Skip List)是一种基于链表的动态数据结构,用于实现高效的查找、插入和删除操作。它通过引入多级索引来加速查找过程,类似于多级索引的有序链表。跳表的平均时间复杂度为 O(logn),在某些场景下可以替代平衡树。

以下是跳表的基本实现思路和一个简单的 C 语言实现示例。


1. 跳表的基本概念

  • 节点结构:每个节点包含一个值和多个指向不同层级的指针。

  • 层级:每个节点的层级是随机的,通常通过抛硬币的方式决定。层级越高,索引的作用越强。

  • 头节点:跳表的入口,包含指向各级索引的指针。

  • 尾节点(可选):用于快速判断是否到达链表末尾。


2. 跳表的关键操作

  1. 查找:从最高层开始,逐层向下查找,直到找到目标值或到达底层。

  2. 插入:找到插入位置后,随机生成节点的层级,并更新指针。

  3. 删除:找到目标节点后,更新相关指针,并释放节点。


3. C语言实现

以下是一个简单的跳表实现,支持查找、插入和删除操作:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>#define MAX_LEVEL 16  // 最大层级
#define PROBABILITY 0.5  // 随机层级的概率typedef struct SkipListNode {int value;struct SkipListNode* next[MAX_LEVEL];
} SkipListNode;typedef struct SkipList {SkipListNode* head;int level;
} SkipList;// 创建新节点
SkipListNode* createNode(int value, int level) {SkipListNode* node = (SkipListNode*)malloc(sizeof(SkipListNode));node->value = value;for (int i = 0; i < level; i++) {node->next[i] = NULL;}return node;
}// 创建跳表
SkipList* createSkipList() {SkipList* list = (SkipList*)malloc(sizeof(SkipList));list->head = createNode(-1, MAX_LEVEL);  // 创建头节点list->level = 0;return list;
}// 随机生成层级
int randomLevel() {int level = 1;while (rand() / (double)RAND_MAX < PROBABILITY && level < MAX_LEVEL) {level++;}return level;
}// 查找操作
SkipListNode* search(SkipList* list, int value) {SkipListNode* current = list->head;for (int i = list->level - 1; i >= 0; i--) {while (current->next[i] != NULL && current->next[i]->value < value) {current = current->next[i];}}current = current->next[0];if (current != NULL && current->value == value) {return current;}return NULL;
}// 插入操作
void insert(SkipList* list, int value) {int level = randomLevel();SkipListNode* newNode = createNode(value, level);SkipListNode* update[MAX_LEVEL] = {NULL};SkipListNode* current = list->head;for (int i = list->level - 1; i >= 0; i--) {while (current->next[i] != NULL && current->next[i]->value < value) {current = current->next[i];}update[i] = current;}for (int i = 0; i < level; i++) {newNode->next[i] = update[i]->next[i];update[i]->next[i] = newNode;}if (level > list->level) {for (int i = list->level; i < level; i++) {list->head->next[i] = newNode;}list->level = level;}
}// 删除操作
void deleteNode(SkipList* list, int value) {SkipListNode* update[MAX_LEVEL] = {NULL};SkipListNode* current = list->head;for (int i = list->level - 1; i >= 0; i--) {while (current->next[i] != NULL && current->next[i]->value < value) {current = current->next[i];}update[i] = current;}current = current->next[0];if (current != NULL && current->value == value) {for (int i = 0; i < list->level; i++) {if (update[i]->next[i] != current) {break;}update[i]->next[i] = current->next[i];}free(current);while (list->level > 1 && list->head->next[list->level - 1] == NULL) {list->level--;}}
}// 打印跳表
void printSkipList(SkipList* list) {for (int i = list->level - 1; i >= 0; i--) {SkipListNode* current = list->head->next[i];printf("Level %d: ", i);while (current != NULL) {printf("%d ", current->value);current = current->next[i];}printf("\n");}
}int main() {srand(time(NULL));SkipList* list = createSkipList();insert(list, 3);insert(list, 6);insert(list, 7);insert(list, 9);insert(list, 12);insert(list, 19);insert(list, 17);insert(list, 26);insert(list, 21);insert(list, 25);printf("Skip List:\n");printSkipList(list);SkipListNode* result = search(list, 19);if (result != NULL) {printf("Found %d in the skip list.\n", result->value);} else {printf("Value not found.\n");}deleteNode(list, 19);printf("Skip List after deletion:\n");printSkipList(list);return 0;
}

4. 代码说明

  1. 节点结构:每个节点包含一个值和一个指向不同层级的指针数组。

  2. 随机层级:通过抛硬币的方式决定节点的层级。

  3. 查找:从最高层开始,逐层向下查找。

  4. 插入:找到插入位置后,随机生成节点的层级,并更新相关指针。

  5. 删除:找到目标节点后,更新相关指针,并释放节点。

  6. 打印:逐层打印跳表的内容,方便观察结构。


5. 运行结果

运行程序后,跳表的结构会以多级索引的形式打印出来,查找、插入和删除操作的结果也会显示。


跳表是一种非常灵活的数据结构,适用于需要高效查找和动态更新的场景。希望这个实现对你有所帮助!

相关文章:

跳表的C语言实现

跳表&#xff08;Skip List&#xff09;是一种基于链表的动态数据结构&#xff0c;用于实现高效的查找、插入和删除操作。它通过引入多级索引来加速查找过程&#xff0c;类似于多级索引的有序链表。跳表的平均时间复杂度为 O(logn)&#xff0c;在某些场景下可以替代平衡树。 以…...

Java Web开发实战与项目——Spring Security与权限管理实现

Web应用中&#xff0c;权限管理是系统安全的核心部分&#xff0c;确保用户只能访问他们被授权的资源。Spring Security是Spring框架中的一个安全框架&#xff0c;它提供了强大的认证和授权功能&#xff0c;用于实现用户认证和权限控制。本章节将详细讲解如何使用Spring Securit…...

单元测试方法的使用

import java.util.Date; import org.junit.Test; /** java中的JUnit单元测试* * 步骤:* 1.选中当前项目工程 --》 右键:build path --》 add libraries --》 JUnit 4 --》 下一步* 2.创建一个Java类进行单元测试。* 此时的Java类要求:①此类是公共的 ②此类提供一个公共的无参…...

VScode内接入deepseek包过程(本地部署版包会)

目录 1. 首先得有vscode软件 2. 在我们的电脑本地已经部署了ollama&#xff0c;我将以qwen作为实验例子 3. 在vscode上的扩展商店下载continue 4. 下载完成后&#xff0c;依次点击添加模型 5. 在这里可以添加&#xff0c;各种各样的模型&#xff0c;选择我们的ollama 6. 选…...

flink写入hdfs数据如何保证幂等的?

在 Flink 中使用 HDFS Connector 将数据写入 HDFS 时&#xff0c;保证幂等性是一个重要的需求&#xff0c;尤其是在数据可靠性要求较高的场景下。以下是详细介绍如何通过 Flink 和 HDFS 的特性以及一些设计上的优化来实现幂等性。 一、Flink 的 Checkpoint 机制 Flink 的 Chec…...

newgrp docker需要每次刷新问题

每次都需要运行 newgrp docker 的原因: 当用户被添加到 docker 组后&#xff0c;当前会话并不会立即更新组信息&#xff0c;因此需要通过 newgrp docker 切换到新的用户组以使权限生效 如果不想每次都手动运行 newgrp docker&#xff0c;可以在终端中配置一个自动刷新的脚本。…...

LM_Funny-2-01 递推算法:从数学基础到跨学科应用

目录 第一章 递推算法的数学本质 1.1 形式化定义与公理化体系 定理1.1 (完备性条件) 1.2 高阶递推的特征分析 案例&#xff1a;Gauss同余递推4 第二章 工程实现优化技术 2.1 内存压缩的革新方法 滚动窗口策略 分块存储技术 2.2 异构计算加速方案 GPU并行递推 量子计…...

WDM_OTN_基础知识_波分站点与组网类型

为了便于理解&#xff0c;我们用高铁来打个比方&#xff0c;这是郑州与武汉的高铁&#xff0c;中间经过了许昌孝感等很多个站点&#xff0c;郑州武汉作为始发站和终点站&#xff0c;所有人员都是上车或下车&#xff0c;而许昌等中间站点&#xff0c;既有人员上下车&#xff0c;…...

机器视觉--索贝尔滤波

引言 在图像处理领域&#xff0c;边缘检测是一项至关重要的任务&#xff0c;它能够帮助我们识别图像中不同区域的边界&#xff0c;为后续的目标识别、图像分割等操作奠定基础。索贝尔滤波&#xff08;Sobel Filter&#xff09;作为一种经典的边缘检测算法&#xff0c;因其简单…...

网络分析仪E5071C的回波损耗测量

回波损耗&#xff08;Return Loss&#xff09;是评估射频/微波元件&#xff08;如滤波器、天线、电缆等&#xff09;信号反射特性的关键参数&#xff0c;反映端口阻抗匹配性能。E5071C矢量网络分析仪&#xff08;VNA&#xff09;通过以下步骤实现高精度回波损耗测量&#xff1a…...

力扣-二叉树-98 验证二叉搜索树

思路 第一个特性&#xff0c;二叉搜索树的中序遍历是有序的&#xff0c;第二个特性&#xff0c;利用两个指针判断大小关系 代码 class Solution { public:TreeNode* pre NULL;bool isValidBST(TreeNode* root) {if(root NULL) return true;bool left isValidBST(root->…...

【动态规划】详解 0-1背包问题

文章目录 1. 问题引入2. 从 dfs 到动态规划3. 动态规划过程分析4. 二维 dp 的遍历顺序5. 从二维数组到一维数组6. 一维数组的遍历次序7. 背包的遍历顺序8. 代码总结9. 总结 1. 问题引入 0-1 背包是比较经典的动态规划问题&#xff0c;这里以代码随想录里面的例子来介绍下。总的…...

【Java线程池与线程状态】线程池分类与最佳实践

解析Java线程池与线程状态变化&#xff0c;结合运行机制与业务场景对照&#xff0c;帮助形成系统性知识。 一、线程池核心要素&#xff08;五维模型&#xff09; 采用「参数配置→处理流程→工作模式」三层递进结构 核心参数&#xff08;线程池DNA&#xff09; corePoolSiz…...

【小白学AI系列】NLP 核心知识点(八)多头自注意力机制

文章目录 **多头自注意力机制&#xff08;Multi-Head Self-Attention&#xff09;****核心概念** **1. 自注意力机制&#xff08;Self-Attention&#xff09;****2. 多头机制&#xff08;Multi-Head Attention&#xff09;****3. 为什么要用多头注意力机制&#xff1f;****4. 公…...

学习笔记——word中图目录、表目录 标题引用

目标1&#xff1a; 建立——图1-1 引用——图1-1 1在word文档中的引用——>插入题注 新建标签&#xff0c;然后命名为“图1-“。 点击确认&#xff0c;即可插入如图所示 图1- 1 春天 需要把图1-和后面那个1中间的空格删除&#xff0c;即 图1-1 春天 2怎么去引用这个“…...

3.3 Hugging Face Transformers核心功能模块深度解析

Hugging Face Transformers核心功能模块深度解析 一、模块化架构总览 #mermaid-svg-wxTV5vrEo7Y57IlW {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-wxTV5vrEo7Y57IlW .error-icon{fill:#552222;}#mermaid-svg-wxT…...

linux中设置脚本定时执行ntp命令同步时间

目录 一、背景二、过程1.到系统目录2.安装ntp3.创建文件夹4.创建脚本文件5.提升脚本文件权限6.设置执行时间&#xff1a;7.检查是否设置了执行器&#xff08;执行后输出的内容为执行器中的定时执行内容&#xff09;8.执行脚本文件9.查看日志文件&#xff0c;是否执行成功 三、总…...

map的使用(c++)

在了解map之前&#xff0c;我们先看看两个场景&#xff0c;通过这两个场景的对比&#xff0c;让我们知道为什么要存在存储双关键字的容器 场景一&#xff1a;判断一堆字符串中&#xff0c;某一个字符串是否出现过 在没学set容器之前&#xff0c;我们只能想到把这一堆字符串存到…...

毕业设计—基于Spring Boot的社区居民健康管理平台的设计与实现

&#x1f393; 毕业设计大揭秘&#xff01;想要源码和文章&#xff1f;快来私信我吧&#xff01; Hey小伙伴们~ &#x1f44b; 毕业季又来啦&#xff01;是不是都在为毕业设计忙得团团转呢&#xff1f;&#x1f914; 别担心&#xff0c;我这里有个小小的福利要分享给你们哦&…...

Python:蟒蛇绘制(一笔画)

一、题目要求 使用turtle库&#xff0c;绘制一个蟒蛇形状的图形。‬ 二、代码展示 # 请在下方开始编写你的代码 import turtle turtle.setup(650,350,200,200) turtle.penup() turtle.fd(-250) turtle.pendown() turtle.pensize(25) turtle.pencolor("purple") turt…...

国防科技大学计算机基础课程笔记02信息编码

1.机内码和国标码 国标码就是我们非常熟悉的这个GB2312,但是因为都是16进制&#xff0c;因此这个了16进制的数据既可以翻译成为这个机器码&#xff0c;也可以翻译成为这个国标码&#xff0c;所以这个时候很容易会出现这个歧义的情况&#xff1b; 因此&#xff0c;我们的这个国…...

智慧工地云平台源码,基于微服务架构+Java+Spring Cloud +UniApp +MySql

智慧工地管理云平台系统&#xff0c;智慧工地全套源码&#xff0c;java版智慧工地源码&#xff0c;支持PC端、大屏端、移动端。 智慧工地聚焦建筑行业的市场需求&#xff0c;提供“平台网络终端”的整体解决方案&#xff0c;提供劳务管理、视频管理、智能监测、绿色施工、安全管…...

前端倒计时误差!

提示:记录工作中遇到的需求及解决办法 文章目录 前言一、误差从何而来?二、五大解决方案1. 动态校准法(基础版)2. Web Worker 计时3. 服务器时间同步4. Performance API 高精度计时5. 页面可见性API优化三、生产环境最佳实践四、终极解决方案架构前言 前几天听说公司某个项…...

定时器任务——若依源码分析

分析util包下面的工具类schedule utils&#xff1a; ScheduleUtils 是若依中用于与 Quartz 框架交互的工具类&#xff0c;封装了定时任务的 创建、更新、暂停、删除等核心逻辑。 createScheduleJob createScheduleJob 用于将任务注册到 Quartz&#xff0c;先构建任务的 JobD…...

基于当前项目通过npm包形式暴露公共组件

1.package.sjon文件配置 其中xh-flowable就是暴露出去的npm包名 2.创建tpyes文件夹&#xff0c;并新增内容 3.创建package文件夹...

学习STC51单片机31(芯片为STC89C52RCRC)OLED显示屏1

每日一言 生活的美好&#xff0c;总是藏在那些你咬牙坚持的日子里。 硬件&#xff1a;OLED 以后要用到OLED的时候找到这个文件 OLED的设备地址 SSD1306"SSD" 是品牌缩写&#xff0c;"1306" 是产品编号。 驱动 OLED 屏幕的 IIC 总线数据传输格式 示意图 …...

【服务器压力测试】本地PC电脑作为服务器运行时出现卡顿和资源紧张(Windows/Linux)

要让本地PC电脑作为服务器运行时出现卡顿和资源紧张的情况&#xff0c;可以通过以下几种方式模拟或触发&#xff1a; 1. 增加CPU负载 运行大量计算密集型任务&#xff0c;例如&#xff1a; 使用多线程循环执行复杂计算&#xff08;如数学运算、加密解密等&#xff09;。运行图…...

GitHub 趋势日报 (2025年06月08日)

&#x1f4ca; 由 TrendForge 系统生成 | &#x1f310; https://trendforge.devlive.org/ &#x1f310; 本日报中的项目描述已自动翻译为中文 &#x1f4c8; 今日获星趋势图 今日获星趋势图 884 cognee 566 dify 414 HumanSystemOptimization 414 omni-tools 321 note-gen …...

涂鸦T5AI手搓语音、emoji、otto机器人从入门到实战

“&#x1f916;手搓TuyaAI语音指令 &#x1f60d;秒变表情包大师&#xff0c;让萌系Otto机器人&#x1f525;玩出智能新花样&#xff01;开整&#xff01;” &#x1f916; Otto机器人 → 直接点明主体 手搓TuyaAI语音 → 强调 自主编程/自定义 语音控制&#xff08;TuyaAI…...

wpf在image控件上快速显示内存图像

wpf在image控件上快速显示内存图像https://www.cnblogs.com/haodafeng/p/10431387.html 如果你在寻找能够快速在image控件刷新大图像&#xff08;比如分辨率3000*3000的图像&#xff09;的办法&#xff0c;尤其是想把内存中的裸数据&#xff08;只有图像的数据&#xff0c;不包…...