发布时间:2026/8/25 7:44:55
符号表--01---概述与实现 符号表定义:符号表最主要的目的就是将一个键和一个值联系起来符号表能够将存储的数据元素是一个键和一个值共同组成的键值对数据我们可以根据键来查找对应的值。符号表中键具有唯一性。使用场景:符号表在实际生活中的使用场景是非常广泛的见下表链表实现符号表API设计:结点类符号表代码实现:publicclassSymbolTableKey,Value{//记录首结点privateNodehead;//记录符号表中元素的个数privateintN;publicSymbolTable(){this.headnewNode(null,null,null);this.N0;}//获取符号表中键值对的个数publicintsize(){returnN;}//往符号表中插入键值对publicvoidput(Keykey,Valuevalue){//符号表中已经存在了键为key的键值对那么只需要找到该结点替换值为value即可Nodenhead;while(n.next!null){//变换nnn.next;//判断n结点存储的键是否为key如果是则替换n结点的值if(n.key.equals(key)){n.valuevalue;return;}}//如果符号表中不存在键为key的键值对只需要创建新的结点保存要插入的键值对把新结点插入到链表的头部 head.next新结点即可NodenewNodenewNode(key,value,null);NodeoldFirsthead.next;newNode.nextoldFirst;head.nextnewNode;//元素个数1N;}//删除符号表中键为key的键值对publicvoiddelete(Keykey){//找到键为key的结点把该结点从链表中删除Nodenhead;while(n.next!null){//判断n结点的下一个结点的键是否为key如果是就删除该结点if(n.next.key.equals(key)){n.nextn.next.next;N--;return;}//变换nnn.next;}}//从符号表中获取key对应的值publicValueget(Keykey){//找到键为key的结点Nodenhead;while(n.next!null){//变换nnn.next;if(n.key.equals(key)){returnn.value;}}returnnull;}//节点类privateclassNode{//键publicKeykey;//值publicValuevalue;//下一个结点publicNodenext;publicNode(Keykey,Valuevalue,Nodenext){this.keykey;this.valuevalue;this.nextnext;}}}测试:publicclassSymbolTableTest{publicstaticvoidmain(String[]args){//创建符号表对象SymbolTableInteger,StringsymbolTablenewSymbolTable();//测试put方法插入,替换symbolTable.put(1,乔峰);symbolTable.put(2,虚竹);symbolTable.put(3,段誉);System.out.println(插入完毕后元素的个数为:symbolTable.size());symbolTable.put(2,慕容复);System.out.println(替换完毕后的元素的个数为:symbolTable.size());//测试get方法System.out.println(替换完毕后键2对应的值为:symbolTable.get(2));//测试删除方法symbolTable.delete(2);System.out.println(删除完毕后元素的个数:symbolTable.size());}}有序符号表刚才实现的符号表我们可以称之为无序符号表因为在插入的时候并没有考虑键值对的顺序而在实际生活中有时候我们需要根据键的大小进行排序插入数据时要考虑顺序那么接下来我们就实现一下有序符号表。有序链表实现:publicclassOrderSymbolTableKeyextendsComparableKey,Value{//记录首结点privateNodehead;//记录符号表中元素的个数privateintN;privateclassNode{//键publicKeykey;//值publicValuevalue;//下一个结点publicNodenext;publicNode(Keykey,Valuevalue,Nodenext){this.keykey;this.valuevalue;this.nextnext;}}publicOrderSymbolTable(){this.headnewNode(null,null,null);this.N0;}//获取符号表中键值对的个数publicintsize(){returnN;}//往符号表中插入键值对publicvoidput(Keykey,Valuevalue){//定义两个Node变量分别记录当前结点和当前结点的上一个结点Nodecurrhead.next;Nodeprehead;while(curr!nullkey.compareTo(curr.key)0){//变换当前结点和前一个结点即可precurr;currcurr.next;}//如果当前结点curr的键和要插入的key一样则替换if(curr!nullkey.compareTo(curr.key)0){curr.valuevalue;return;}//如果当前结点curr的键和要插入的key不一样把新的结点插入到curr之前NodenewNodenewNode(key,value,curr);pre.nextnewNode;//元素的个数1N;}//删除符号表中键为key的键值对publicvoiddelete(Keykey){//找到键为key的结点把该结点从链表中删除Nodenhead;while(n.next!null){//判断n结点的下一个结点的键是否为key如果是就删除该结点if(n.next.key.equals(key)){n.nextn.next.next;N--;return;}//变换nnn.next;}}//从符号表中获取key对应的值publicValueget(Keykey){//找到键为key的结点Nodenhead;while(n.next!null){//变换nnn.next;if(n.key.equals(key)){returnn.value;}}returnnull;}}debug测试:数组二分查找实现:使用一对平行数组一个存储键一个存储值。二分查找的思想是在内部维护一个按照key排好序的二维数组每一次查找的时候跟中间元素进行比较如果该元素小则继续左半部分递归查找否则继续右半部分递归查找。整个实现代码如下二分查找的 rank() 方法至关重要当键在表中时它能够知道该键的位置当键不在表中时它也能知道在何处插入新键。/** * 有序数组符号表 */publicclassSymbolTableKextendsComparableK,V{privateK[]keys;//键数组privateV[]values;//值数组publicintsize;privatestaticfinalintinitSize10;//默认数组初始大小publicSymbolTable(){this(initSize);}publicSymbolTable(intcapacity){keys(K[])newComparable[capacity];values(V[])newObject[capacity];}/** * 查找键为K的值 */publicVget(Kk){if(isEmpty()){returnnull;}//在数组中找出值intirank(k);if(isizekeys[i].compareTo(k)0){returnvalues[i];}returnnull;}/** * 插入要给键值对 */publicvoidput(Kk,Vv){intirank(k);//如果已经存在了键就交换值if(isizekeys[i].compareTo(k)0){values[i]v;return;}//否则就把键值插入到最小于K的值之后for(intjsize;ji;j--){keys[j]keys[j-1];values[j]values[j-1];}keys[i]k;values[i]v;size;}publicbooleanisEmpty(){returnsize0;}publicintrank(Kk){intlow0;//低位起始下标inthighsize-1;//高位下标长度-1//高低交叉之前都一直查询while(lowhigh){intmidlow(high-low)/2;//找到中位下标intcmdk.compareTo(keys[mid]);//获取数组中中位值与比较K的大小//如果两个值相等说明找到了if(cmd0){returnmid;//小于0说明比中位值小从数组中中位置左侧搜索}elseif(cmd0){highmid-1;//和上面相反从数组右侧搜索}else{lowmid1;}}//否侧返回低位的值这个值就是小于被查找值的数量returnlow;}}debug测试:总结:本文介绍了符号表这一抽象数据结构然后介绍了两种基本实现基于无序链表的实现和基于有序数组的实现两种实现的时间复杂度如下无序链表实现:插入的时候先要查找如果存在则更新value查找的时候需要从链表头进行查找所以插入和查找的平均时间复杂度均为O(n)数组二分查找:采用二分查找只需要最多 logN1次的比较即可找到对应元素所以查找效率比较高。但是对于插入元素来说每一次插入不存在的元素需要将该元素放到指定的位置然后将他后面的元素依次后移所以平均时间复杂度O(n)对于插入来说效率仍然比较低。使用有序数组的二分查找法提高了符号表的查找速度但是插入效率仍旧没有得到提高而且在要维护数组有序还需要进行排序操作。这两种实现方式简单直观但是无法同时达到较高查找和插入效率。本文只是一个引子后面的系列文章将会介绍二叉查找树平衡查找树以及哈希表。数组实现和链表实现对比:

相关新闻

2026/8/25 7:44:55

I2C协议进阶:快速模式、高速模式与10位寻址详解

1. 从标准模式到性能跃迁:为什么需要更快的I2C?搞嵌入式开发的朋友,对I2C(Inter-Integrated Circuit)协议肯定不陌生。它那两根线(SDA数据线、SCL时钟线)的简洁设计,让连接多个低速外…

2026/8/25 7:44:55

Mendeley文献管理工具:从入门到精通,打造高效学术工作流

1. 从文献混乱到高效管理:为什么你需要Mendeley如果你正在读研、搞科研,或者从事任何需要大量阅读和引用文献的工作,那么你肯定对下面这个场景不陌生:电脑里塞满了从各个数据库下载的PDF文件,文件名千奇百怪&#xff0…

2026/8/25 10:15:32

DanmakuFactory:三步把 XML 弹幕转成 ASS 字幕,特殊弹幕不丢

DanmakuFactory:三步把 XML 弹幕转成 ASS 字幕,特殊弹幕不丢 【免费下载链接】DanmakuFactory 支持特殊弹幕的xml转ass格式转换工具 项目地址: https://gitcode.com/gh_mirrors/da/DanmakuFactory 直播归档的人,手里多半都有一个从弹幕…

2026/8/25 10:15:32

AR+AI翻译、具身智能与极简交互:技术融合下的AI工程实践与机遇

1. 从“ARAI翻译”到“具身智能GPT”:一次技术融合的深度观察最近,几个看似独立的技术热点在圈子里被频繁提及:ARAI翻译系统、具身智能的“GPT时刻”,以及Claude带来的“极简革命”。乍一看,它们分属增强现实、人工智能…

2026/8/25 10:15:32

基于QClaw的动漫资源自动化追踪与推送系统实战指南

1. 项目缘起:从“追番焦虑”到自动化解决方案作为一个老二次元,我敢说每个追番人都有过类似的烦恼:每周要手动去各个平台、论坛、资源站翻找最新一集,生怕错过更新;遇到喜欢的冷门作品,更是要像侦探一样四处…

2026/8/25 10:15:32

Vue3+Element-Plus侧边菜单折叠:从状态管理到移动端适配的实战方案

1. 项目概述:从“能用”到“好用”的菜单交互进化在后台管理系统的开发中,左侧导航菜单的折叠与展开功能,看似是一个基础得不能再基础的交互。很多开发者,尤其是刚接触Vue3和Element-Plus的朋友,可能会觉得这不过就是控…

2026/8/25 10:15:32

Vue3+Element-Plus实现后台管理系统侧边菜单折叠与展开功能详解

1. 项目概述与核心价值最近在重构一个后台管理系统,菜单栏的折叠与展开功能是每个开发者都绕不开的“标配”。乍一看,这功能简单得像是“点击按钮,切换宽度”,但真做起来,你会发现从状态管理、动画过渡到布局自适应&am…

2026/8/25 10:10:31

FuAdmin表单设计器使用教程:可视化拖拽快速搭建复杂表单

FuAdmin表单设计器使用教程:可视化拖拽快速搭建复杂表单 【免费下载链接】fu-admin 采用当前最流行的技术栈 Vben Vue Vue3 Python Django Ninja(Fast Api 和 Django的结合)开发的后端管理系统 项目地址: https://gitcode.com/gh_mirrors/f…

2026/8/25 1:04:19

[光学原理与应用-521]:对光的错误理解与纠偏

首先光是一种能量的载体和形态,宏观上观察到的光是由无数个微观的光量子组成的,每个光子在产生的瞬间,其在真空的空间中以确定不变的速度沿着一个初始的方向一直向前,在微观层面,每个光量子的运动轨迹是以波函数所展现…

2026/8/24 1:12:32

SIP通话转接原理与REFER方法实战解析

1. 通话转接不是“挂断再拨号”,而是SIP会话的动态重定向你有没有遇到过这样的场景:客服坐席A正在和客户通电话,突然需要把这通对话无缝转给专家坐席B,客户完全感知不到中间的断连——既没听到忙音,也没被要求重新拨号…

2026/8/24 8:17:29

Kolla-ansible单节点OpenStack部署实战:从环境准备到排坑指南

1. 为什么选择Kolla-ansible来部署单节点OpenStack?如果你正在寻找一种能把OpenStack从“概念”快速变成“可用的实验环境”的方法,那么Kolla-ansible几乎是当前最主流、最省心的选择。我见过太多人卡在手动编译依赖、配置服务、处理版本冲突的泥潭里&am…

2026/8/25 0:04:14

三步把QQ空间历史说说导出到本地:GetQzonehistory 极简指南

三步把QQ空间历史说说导出到本地:GetQzonehistory 极简指南 【免费下载链接】GetQzonehistory 获取QQ空间发布的历史说说 项目地址: https://gitcode.com/GitHub_Trending/ge/GetQzonehistory Meta Description:GetQzonehistory 是一个QQ空间历史说…

2026/8/25 0:04:14

洛谷 P7912:[CSP-J 2021 T4] 小熊的果篮 ← 双向链表

【题目来源】 https://www.luogu.com.cn/problem/P7912 【题目描述】 小熊的水果店里摆放着一排 n 个水果。每个水果只可能是苹果或桔子,从左到右依次用正整数 1,2,…,n 编号。连续排在一起的同一种水果称为一个“块”。小熊要把这一排水果挑到若干个果篮里&#x…

2026/8/24 13:42:17

实测才敢推 AI论文网站 2026最新测评与推荐

2026年真正好用的AI论文网站,核心看生成的论文质量、低AI味、格式正确、学术适配四大指标。综合实测,千笔AI、ThouPen、豆包、DeepSeek、Grammarly 是当前最值得推荐的梯队,覆盖从免费到付费、从中文到英文、从文科到理工的全场景需求。一、综…

2026/8/24 18:13:48

2026必备!AI论文网站测评:最新推荐与深度对比

2026年真正好用的AI论文网站,核心看生成的论文质量、低AI味、格式正确、学术适配四大指标。综合实测,千笔AI、ThouPen、豆包、DeepSeek、Grammarly 是当前最值得推荐的梯队,覆盖从免费到付费、从中文到英文、从文科到理工的全场景需求。 一、…

2026/8/25 1:08:14

摆脱论文困扰!盘点2026年全网爆红的的AI论文写作工具

一天写完毕业论文在2026年已不再是天方夜谭。2026年最炸裂、实测能大幅提速的AI论文写作工具,覆盖选题构思、文献整理、内容生成、格式排版等核心场景,真正帮你高效搞定论文难题。 一、全流程王者:一站式搞定论文全链路(一天定稿首…