🔥🔥Java开发者的Python快速进修指南:实战之简易跳表
前言
之前我已经将Python的基本语法与Java进行了比较,相信大家对Python也有了一定的了解。我不会选择去写一些无用的业务逻辑来加强对Python的理解。相反,我更喜欢通过编写一些数据结构和算法来加深自己对Python编程的理解。学习任何语言都一样。
通过编写数据结构和算法,不仅可以加强我自己的思维能力,还能提高对Python编程语言的熟练程度。在这个过程中,我会不断地优化我的代码,以提高算法的效率和性能。我相信通过这种方式,我能够更好地掌握Python编程,并且在解决实际问题时能够更加灵活地运用Python的特性和语法。
跳表
今天我们来使用Python实现一个简易版本的跳表。所谓跳表就是一种跳跃式的数据结构。
假设你是一位图书馆管理员,你需要在图书馆的书架上找到一本特定的书。如果图书馆只是一个普通的书架,你需要逐本书进行查找,这样会花费很多时间和精力。
然而,如果图书馆采用了跳表这种数据结构,书架上的书被分成了几个层次,每一层都有一个索引,上面标注了每本书的位置信息。当你需要找到一本书时,你可以先查看最高层的索引,快速定位到可能包含该书的区域,然后再在该区域内根据索引逐步查找,直到找到目标书籍。
这样,跳表的索引层就相当于图书馆的书籍分类系统,它提供了一个快速查找的方法。通过索引层,你可以迅速定位到书籍所在的区域,减少了查找的次数和时间。
跳表主要的思想是利用索引的概念。因此,每个节点除了保存下一个链表节点的地址之外,还需要额外存储索引地址,用于指示下一步要跳转的地址。它在有序链表的基础上增加了多层索引,以提高查找效率。
而且这适合于读多写少的场景。在实现过程中,无论是在插入数据完毕后重新建立索引,还是在插入数据的同时重新建立索引,都会导致之前建立的索引丢弃,浪费了大量时间。而且,如果考虑多线程的情况,情况会更糟糕。写这种东西时,通常先实现一个简单版,然后根据各个环节进行优化,逐步改进算法。因此,我们今天先实现一个简单版的跳表。
具体实现
我们先来实现一个简单版的跳表,不动态规定步长。我们可以先定义一个固定的步长,比如2。
为了实现跳表,我们需要定义一个节点的数据结构。这个节点包含以下信息:当前节点的值(value),指向前一个节点的指针(before_node),指向后一个节点的指针(next_node),以及指向索引节点的指针(index_node)。
class SkipNode:
def __init__(self,value,before_node=None,next_node=None,index_node=None):
self.value = value
self.before_node = before_node
self.next_node = next_node
self.index_node = index_node
head = SkipNode(-1)
tail = SkipNode(-1)
为了方便操作,我先生成了两个特殊节点,一个是头节点,另一个是尾节点。头节点作为跳表的起始点,尾节点作为跳表的结束点。
数据插入
在跳表中插入节点时,我们按照从小到大的升序进行排序。插入节点时,无需维护索引节点。一旦完成插入操作,我们需要重新规划索引节点,以确保跳表的性能优化。
def insert_node(node):
if head.next_node is None:
head.next_node = node
node.next_node = tail
node.before_node = head
tail.before_node = node
return
temp = head.next_node
# 当遍历到尾节点时,需要直接插入
while temp.next_node is not None or temp == tail:
if temp.value > node.value or temp == tail:
before = temp.before_node
before.next_node = node
temp.before_node = node
node.before_node = before
node.next_node = temp
break
temp = temp.next_node
re_index()
重建索引
为了重新规划索引,我们可以先将之前已经规划好的索引全部删除。然后,我们可以使用步长为2的方式重新规划索引。
def re_index():
step = 2
# 用来建立索引的节点
index_temp = head.next_node
# 用来遍历的节点
temp = head.next_node
while temp.next_node is not None:
temp.index_node = None
if step == 0:
step = 2
index_temp.index_node = temp
index_temp = temp
temp = temp.next_node
step -= 1
查询节点
查询:从头节点开始查询,根据节点的值与目标值进行比较。如果节点的值小于目标值,则向右移动到下一个节点或者索引节点继续比较。如果节点的值等于目标值,则找到了目标节点,返回结果。如果节点的值大于目标值,则则说明目标节点不存在。
def search_node(value):
temp = head.next_node
step = 0
while temp.next_node is not None:
step += 1
if value == temp.value:
print(f"该值已找到,经历了{step}次查询")
return
elif value < temp.value:
print(f"该值在列表不存在,经历了{step}次查询")
return
if temp.index_node is not None and value > temp.index_node.value:
temp = temp.index_node
else:
temp = temp.next_node
print(f"该值在列表不存在,经历了{step}次查询")
遍历
为了方便查看,我特意编写了一个用于遍历和查看当前数据的功能,以便更清楚地了解数据的结构和内容。
def print_node():
my_list = []
temp = head.next_node
while temp.next_node is not None:
if temp.index_node is not None:
my_dict = {"current_value": temp.value, "index_value": temp.index_node.value}
else:
my_dict = {"current_value": temp.value, "index_value": None} # 设置一个默认值为None
my_list.append(my_dict)
temp = temp.next_node
for item in my_list:
print(item)
查看结果
所有代码已经准备完毕,现在我们可以在另一个文件中运行并查看跳表的内容和数据。让我们快速进行操作一下。
import skipList
import random
for i in range(0,10):
random_number = random.randint(1, 100)
temp = skipList.SkipNode(random_number)
skipList.insert_node(temp)
skipList.print_node()
skipList.search_node(89)
以下是程序的运行结果。为了方便查看,我特意打印了索引节点的值,以告诉你要跳到哪一个节点。

总结
通过实现一个简易版本的跳表,可以加深了对Python编程的理解。跳表是一种跳跃式的数据结构,通过索引层提供快速查找的能力,提高了查找的效率。在实现跳表的过程中,会更加熟悉了Python的语法和特性,并且可以更加灵活地运用它来解决实际问题。
🔥🔥Java开发者的Python快速进修指南:实战之简易跳表的更多相关文章
- JAVA开发者的Golang快速指南
Golang作为Docker.Kubernetes和OpenShift等一些酷辣新技术的首选编程语言,越来越受欢迎.尤其它们都是开源的,很多情况下,开源是非常有价值的.深入学习阅Golang等源代码库 ...
- 针对Quant的Python快速入门指南
作者:用Python的交易员 (原创文章,转载请注明出处) 最近有越来越多的朋友在知乎或者QQ上问我如何学习入门Python,就目前需求来看,我需要写这么一篇指南. 针对整个vn.py框架的学习,整体 ...
- MessagePack Java 0.6.X 快速开始指南 - 安装
0.6.x 版本的 MessagePack 已经过期被淘汰了.如果你现在开始使用 MessagePack 话,请不要使用这个版本. 我们再这里保留 0.6.x 版本的内容主要用于参考用途. 最新的 M ...
- [置顶]
【Android实战】----从Retrofit源码分析到Java网络编程以及HTTP权威指南想到的
一.简介 接上一篇[Android实战]----基于Retrofit实现多图片/文件.图文上传中曾说非常想搞明白为什么Retrofit那么屌.最近也看了一些其源码分析的文章以及亲自查看了源码,发现其对 ...
- Java程序员的现代RPC指南(Windows版预编译好的Protoc支持C++,Java,Python三种最常用的语言,Thrift则支持几乎主流的各种语言)
Java程序员的现代RPC指南 1.前言 1.1 RPC框架简介 最早接触RPC还是初学Java时,直接用Socket API传东西好麻烦.于是发现了JDK直接支持的RMI,然后就用得不亦乐乎,各种大 ...
- 阿里巴巴泰山版《Java 开发者手册》,也是一份防坑指南
我是风筝,公众号「古时的风筝」,一个不只有技术的技术公众号,一个在程序圈混迹多年,主业 Java,另外 Python.React 也玩儿的 6 的斜杠开发者. Spring Cloud 系列文章已经完 ...
- 【Android实战】----从Retrofit源代码分析到Java网络编程以及HTTP权威指南想到的
一.简单介绍 接上一篇[Android实战]----基于Retrofit实现多图片/文件.图文上传中曾说非常想搞明确为什么Retrofit那么屌. 近期也看了一些其源代码分析的文章以及亲自查看了源代码 ...
- 学习Keras:《Keras快速上手基于Python的深度学习实战》PDF代码+mobi
有一定Python和TensorFlow基础的人看应该很容易,各领域的应用,但比较广泛,不深刻,讲硬件的部分可以作为入门人的参考. <Keras快速上手基于Python的深度学习实战>系统 ...
- 0基础学Java快速扫盲指南,月入2W的基础
学Java,掌握一些基本的概念是第一步,本文简单为大家介绍一些扫盲级别的内容,希望帮助小白快速入门. 一.基本概念 JVM:java虚拟机,负责将编译产生的字节码转换为特定机器代码,实现一次编译多处执 ...
- Java快速扫盲指南
文章转自:https://segmentfault.com/a/1190000004817465#articleHeader22 JDK,JRE和 JVM 的区别 JVM:java 虚拟机,负责将编译 ...
随机推荐
- 2023-08-04:村里面一共有 n 栋房子 我们希望通过建造水井和铺设管道来为所有房子供水。 对于每个房子 i,我们有两种可选的供水方案: 一种是直接在房子内建造水井 成本为 wells[i -
2023-08-04:村里面一共有 n 栋房子 我们希望通过建造水井和铺设管道来为所有房子供水. 对于每个房子 i,我们有两种可选的供水方案: 一种是直接在房子内建造水井 成本为 wells[i - ...
- next.js 源码解析 - getStaticProps、getStaticPaths 篇
好久前写了关于 getStaticProps 和 getStaticPaths 的内容,然而半年过去了源码解析就一直忘记了,不久前有人提醒才想起来,补下坑. 本文主要是解读下 getStaticPro ...
- 7、Spring之基于注解管理bean
本质上:所有一切的操作都是Java代码来完成的,XML和注解只是告诉框架中的Java代码如何执行. 7.1.环境搭建 创建名为spring_ioc_annotation的新module,过程参考3.1 ...
- 2023-08-22:请用go语言编写。给定一个长度为N的正数数组,还有一个正数K, 返回有多少子序列的最大公约数为K。 结果可能很大,对1000000007取模。 1 <= N <= 10^5, 1
2023-08-22:请用go语言编写.给定一个长度为N的正数数组,还有一个正数K, 返回有多少子序列的最大公约数为K. 结果可能很大,对1000000007取模. 1 <= N <= 1 ...
- [Lua] 实现所有类的基类Object、模拟单继承OO、实现抽象工厂
所有类的基类 Object Lua 没有严格的 oo(Object-Oriented)定义,可以利用元表特性来实现 先定义所有类的基类,即Object类.代码顺序从上到下,自成一体.完整代码 定义一个 ...
- 【题解】Educational Codeforces Round 141(CF1783)
评价:educational A.Make it Beautiful 题目描述: 如果一个数组中存在一个数恰好等于该数前面所有数之和,那么这个数组就是丑的.如果一个数组不是丑的,就是美的. 比如说: ...
- Elasticsearch整合SpringBoot案例
1.elasticsearch官方文档的使用与介绍 1.1.Rest客户端初始化官方文档链接: https://www.elastic.co/guide/en/elasticsearch/client ...
- 「ceoi 2009」harbingers
link. 朴素 dp 大约就是 \(f_x=f_y+v_x\times(d_x-d_y)+s_x\),\(y\) 是 \(x\) 的祖先.这个式子可以斜率优化,在以 \(d_y\) 为横坐标,\(f ...
- Solution -「GXOI / GZOI 2019」AND OR Sum
Description Link. 给定一个 \(N \times N\) 的矩阵,她希望求出: 该矩阵的所有子矩阵的 \(\texttt{AND}\) 值之和(所有子矩阵 \(\texttt{AND ...
- VisionPro学习笔记(4)——PatInspect
如果需要了解其他图像处理的文章,请移步小编的GitHub地址 传送门:请点击我 如果点击有误:https://github.com/LeBron-Jian/ComputerVisionPractice ...