[{"data":1,"prerenderedAt":1939},["ShallowReactive",2],{"blog-taxonomies":3,"blog-stats":507,"post-数据结构\u002F数据结构-线性表链表":1083},[4,11,16,21,25,29,36,39,44,47,52,58,63,66,71,76,80,84,87,93,96,101,105,110,113,117,122,127,132,136,141,143,146,151,155,157,162,165,169,173,176,179,183,186,190,193,197,200,205,208,211,214,219,222,228,234,237,239,245,249,253,256,260,266,271,276,281,283,287,290,293,298,301,304,306,308,311,314,316,318,321,327,332,337,342,347,352,354,356,358,361,365,367,369,371,374,376,378,381,386,390,393,396,400,404,407,411,413,415,417,421,423,425,428,431,433,435,437,439,441,443,446,448,450,454,456,459,461,463,465,467,469,471,473,477,483,486,488,491,493,495,497,499,501,503,505],{"category":5,"tags":6},"笔记",[7,8,9,10],"QQ","插件","LiteLoader","美化",{"category":12,"tags":13},"其他",[14,15,10],"博客","IP签名",{"category":17,"tags":18},"杂谈",[19,20],"互联网","观点",{"category":5,"tags":22},[14,23,24],"GitHub","数据可视化",{"category":5,"tags":26},[14,27,28],"访问统计","不蒜子",{"category":30,"tags":31},"工具",[32,33,34,35],"Python","爬虫","选课脚本","广州大学",{"category":5,"tags":37},[38,5],"数学分析",{"category":40,"tags":41},"算法",[42,40,43],"数据结构","线性表",{"category":40,"tags":45},[42,46],"复习",{"category":5,"tags":48},[49,50,51],"高等代数","线性代数","知识点",{"category":5,"tags":53},[14,54,55,56,57],"Typora","PicGo","图床","Markdown",{"category":30,"tags":59},[60,61,62],"Jupyter","工具配置","中文",{"category":30,"tags":64},[65,61,10],"VSCode",{"category":30,"tags":67},[68,69,70,35],"路由器","OpenWrt","校园网",{"category":12,"tags":72},[73,74,75],"网络协议","Wireshark","DEVP2P",{"category":5,"tags":77},[73,74,78,79],"Lua","解码器",{"category":5,"tags":81},[82,5,83],"常微分方程","数学",{"category":5,"tags":85},[86,5,83],"概率论",{"category":30,"tags":88},[89,90,91,92],"Docker","WSL","Windows","磁盘清理",{"category":30,"tags":94},[32,33,95,35],"课程表",{"category":5,"tags":97},[14,98,99,100],"Hexo","Gitalk","评论系统",{"category":5,"tags":102},[14,103,98,104],"Obsidian","写作工具",{"category":12,"tags":106},[107,108,109],"课题研究","泊松分布","参数估计",{"category":12,"tags":111},[107,108,109,112],"组会",{"category":12,"tags":114},[109,115,108,116],"IM模型","统计学",{"category":17,"tags":118},[119,120,121],"软考","网络规划","信息系统项目管理",{"category":30,"tags":123},[124,125,126],"Arch Linux","AppImage","Linux",{"category":5,"tags":128},[129,130,131],"编程语言","计算机科学","内存管理",{"category":5,"tags":133},[134,135],"Canvas","前端",{"category":5,"tags":137},[14,138,139,140],"GitHub Actions","Vite","部署",{"category":5,"tags":142},[135],{"category":5,"tags":144},[135,145],"系统设计",{"category":5,"tags":147},[135,148,149,150],"安全","XSS","CSRF",{"category":152,"tags":153},"项目",[134,154],"PixiJS",{"category":152,"tags":156},null,{"category":40,"tags":158},[42,159,160,161],"栈","队列","JavaScript",{"category":40,"tags":163},[42,164,161],"哈希表",{"category":5,"tags":166},[167,161,168],"ES6","Set",{"category":40,"tags":170},[40,171,172],"动态规划","背包问题",{"category":40,"tags":174},[40,175],"滑动窗口",{"category":40,"tags":177},[42,178,161],"链表",{"category":40,"tags":180},[40,181,161,182],"ACM","面试",{"category":40,"tags":184},[40,161,185],"数据类型转换",{"category":40,"tags":187},[42,188,178,189],"顺序表","TypeScript",{"category":5,"tags":191},[135,154,134,192],"渲染",{"category":5,"tags":194},[135,195,134,196],"富文本编辑","wangEditor",{"category":40,"tags":198},[199,40,178],"力扣",{"category":5,"tags":201},[202,203,204,91],"DNS","加密","网络安全",{"category":5,"tags":206},[135,207],"Axios",{"category":5,"tags":209},[135,207,189,210],"接口封装",{"category":5,"tags":212},[135,213,145],"JWT",{"category":152,"tags":215},[134,216,217,154,218],"画布","React","项目开发",{"category":17,"tags":220},[221],"日志",{"category":5,"tags":223},[224,225,226,227],"Neo4j","图数据库","中心度分析","PageRank",{"category":12,"tags":229},[230,231,232,233],"论文","机器学习","随机森林","保险欺诈",{"category":5,"tags":235},[236],"人工智能",{"category":5,"tags":238},[231,40,32],{"category":12,"tags":240},[241,242,243,244],"共识算法","最长链","区块链","算法设计",{"category":5,"tags":246},[161,247,248,135],"闭包","作用域",{"category":5,"tags":250},[14,138,251,252],"RSS","自动化",{"category":30,"tags":254},[89,90,91,255],"安装",{"category":30,"tags":257},[258,91,259],"MSYS2","开发环境",{"category":5,"tags":261},[262,263,264,265],"团队协作","Git","Commit规范","代码审查",{"category":30,"tags":267},[268,269,270],"oh-my-posh","终端美化","CLI",{"category":5,"tags":272},[273,274,275],"上下文工程","Agent","RAG",{"category":5,"tags":277},[278,279,280],"前端工程化","技术选型","工程基建",{"category":5,"tags":282},[275],{"category":5,"tags":284},[285,286],"SDD","规格驱动开发",{"category":5,"tags":288},[289],"neovim",{"category":5,"tags":291},[292],"技术写作",{"category":5,"tags":294},[295,32,296,89,297],"FastAPI","后端","工程实践",{"category":152,"tags":299},[274,300],"Harness Engineering",{"category":5,"tags":302},[303],"RFC",{"category":152,"tags":305},[274,300,275],{"category":152,"tags":307},[274],{"category":40,"tags":309},[199,40,161,310],"两数之和",{"category":40,"tags":312},[199,40,161,313],"双指针",{"category":40,"tags":315},[199,40,161,178],{"category":40,"tags":317},[199,40,161,175],{"category":40,"tags":319},[199,40,161,320],"回溯",{"category":5,"tags":322},[323,324,325,326],"分布式处理与计算","Spark","Scala","RDD",{"category":5,"tags":328},[323,329,330,331],"线性回归","逻辑回归","监督学习",{"category":5,"tags":333},[323,334,335,336],"数值优化","牛顿法","收敛性",{"category":5,"tags":338},[323,339,340,341],"PCA","数据降维","正则化",{"category":5,"tags":343},[323,344,345,346],"聚类","层次聚类","K-Means",{"category":5,"tags":348},[323,349,350,351],"随机模拟","统计推断","EM算法",{"category":5,"tags":353},[24],{"category":5,"tags":355},[24],{"category":5,"tags":357},[24],{"category":40,"tags":359},[42,360],"图论",{"category":40,"tags":362},[42,363,364],"树","二叉树",{"category":40,"tags":366},[42,160],{"category":40,"tags":368},[42],{"category":40,"tags":370},[42,159],{"category":40,"tags":372},[42,40,373],"复杂度分析",{"category":40,"tags":375},[42,43,178],{"category":40,"tags":377},[42,43,188],{"category":40,"tags":379},[42,380],"基础概念",{"category":17,"tags":382},[383,384,385],"随记","照片","高中",{"category":17,"tags":387},[383,388,389],"团建","战地",{"category":17,"tags":391},[383,392],"生活",{"category":17,"tags":394},[383,395],"文学",{"category":17,"tags":397},[383,398,399],"SCP","模因",{"category":17,"tags":401},[383,402,403],"画集","艺术",{"category":17,"tags":405},[14,406,383],"写作",{"category":17,"tags":408},[383,409,410],"音乐","摇滚",{"category":17,"tags":412},[383,392],{"category":17,"tags":414},[383,409],{"category":17,"tags":416},[383,35,392],{"category":17,"tags":418},[383,419,420],"同人","手书",{"category":17,"tags":422},[383,392],{"category":17,"tags":424},[383,392],{"category":17,"tags":426},[383,427],"植物",{"category":17,"tags":429},[383,430],"读书",{"category":17,"tags":432},[383,392],{"category":17,"tags":434},[383,392],{"category":17,"tags":436},[383,392],{"category":17,"tags":438},[383,392],{"category":17,"tags":440},[383,392],{"category":17,"tags":442},[383,392],{"category":17,"tags":444},[14,445,383],"一周年",{"category":17,"tags":447},[383,392],{"category":17,"tags":449},[383,392],{"category":17,"tags":451},[35,452,453],"开源组织","SITE-193",{"category":17,"tags":455},[383,392],{"category":17,"tags":457},[383,458],"年末",{"category":17,"tags":460},[383,392],{"category":17,"tags":462},[383,392],{"category":17,"tags":464},[14,17],{"category":17,"tags":466},[383,392],{"category":17,"tags":468},[383,392],{"category":17,"tags":470},[383,392],{"category":17,"tags":472},[383,392],{"category":17,"tags":474},[383,475,476],"游戏","Control",{"category":30,"tags":478},[479,480,481,482],"Quadim","图像处理","四叉树","Rust",{"category":17,"tags":484},[14,485],"上线纪念",{"category":17,"tags":487},[383,395],{"category":30,"tags":489},[203,490],"测试",{"category":17,"tags":492},[383],{"category":17,"tags":494},[383,392],{"category":17,"tags":496},[383],{"category":5,"tags":498},[40],{"category":5,"tags":500},[40],{"category":5,"tags":502},[40],{"category":5,"tags":504},[40],{"category":5,"tags":506},[40],[508,512,516,520,524,528,532,536,540,544,548,552,556,560,564,568,572,576,579,583,587,590,594,598,602,606,610,614,618,622,626,630,634,638,642,646,650,654,658,662,666,670,674,678,682,686,690,694,698,702,706,710,714,718,722,726,730,734,738,742,746,750,754,758,762,766,770,774,778,782,786,790,794,798,801,805,809,813,817,821,825,829,833,837,841,845,849,853,857,861,865,869,873,877,881,885,889,893,897,901,904,907,911,915,919,923,927,930,934,938,942,946,950,954,957,961,965,969,973,977,981,984,988,992,996,1000,1004,1007,1011,1015,1019,1023,1027,1031,1035,1039,1043,1047,1051,1055,1059,1063,1067,1071,1075,1079],{"path":509,"words":510,"published":511,"date":156},"\u002Fposts\u002F2024\u002F2024-06-25-liteloaderqqnt",1296,"2024-06-25 11:03:08",{"path":513,"words":514,"published":515,"date":156},"\u002Fposts\u002F2024\u002F2024-06-26-ip签名",0,"2024-06-26 22:53:53",{"path":517,"words":518,"published":519,"date":156},"\u002Fposts\u002F2024\u002F2024-06-29-何加盐中文互联网正在加速崩塌",4853,"2024-06-29 00:47:13",{"path":521,"words":522,"published":523,"date":156},"\u002Fposts\u002F2024\u002F2024-07-12-github-chart",270,"2024-07-12 20:02:50",{"path":525,"words":526,"published":527,"date":156},"\u002Fposts\u002F2024\u002F2024-07-14-访客数统计",192,"2024-07-24 01:34:28",{"path":529,"words":530,"published":531,"date":156},"\u002Fposts\u002F2024\u002F2024-07-26-广大选课脚本",110,"2024-07-26 01:34:28",{"path":533,"words":534,"published":535,"date":156},"\u002Fposts\u002F2024\u002F2024-07-26-数学分析笔记其二",14,"2024-07-26 23:54:02",{"path":537,"words":538,"published":539,"date":156},"\u002Fposts\u002F2024\u002F2024-07-26-数据结构复习其二",12856,"2024-07-26 02:48:08",{"path":541,"words":542,"published":543,"date":156},"\u002Fposts\u002F2024\u002F2024-07-26-数据结构复习相关",32856,"2024-07-26 02:24:14",{"path":545,"words":546,"published":547,"date":156},"\u002Fposts\u002F2024\u002F2024-07-26-线性代数与空间解析几何知识点全汇总",6110,"2024-07-26 03:27:55",{"path":549,"words":550,"published":551,"date":156},"\u002Fposts\u002F2024\u002F2024-07-31-typora-picgo-兰空图床打造markdown写作环境",311,"2024-07-31 12:56:23",{"path":553,"words":554,"published":555,"date":156},"\u002Fposts\u002F2024\u002F2024-09-02-jupyter配置中文",441,"2024-09-02 23:49:05",{"path":557,"words":558,"published":559,"date":156},"\u002Fposts\u002F2024\u002F2024-09-02-自定义vscode背景图片",100,"2024-09-02 23:39:00",{"path":561,"words":562,"published":563,"date":156},"\u002Fposts\u002F2024\u002F2024-09-03-制作gzhu校园网路由器",1423,"2024-09-03 23:43:18",{"path":565,"words":566,"published":567,"date":156},"\u002Fposts\u002F2024\u002F2024-09-26-09-25-2024",136,"2024-09-26 00:49:26",{"path":569,"words":570,"published":571,"date":156},"\u002Fposts\u002F2024\u002F2024-11-04-创建一个网络包解码器分析devp2p协议",1943,"2024-11-04 16:45:19",{"path":573,"words":574,"published":575,"date":156},"\u002Fposts\u002F2024\u002F2025-03-09-2024一些笔记常微分",16,"2024-12-09 22:51:00",{"path":577,"words":574,"published":578,"date":156},"\u002Fposts\u002F2024\u002F2025-03-09-2024一些笔记概率论","2025-03-09 22:51:00",{"path":580,"words":581,"published":582,"date":156},"\u002Fposts\u002F2025\u002F2025-03-01-windows下释放docker占用的wsl空间",164,"2025-03-01 13:54:15",{"path":584,"words":585,"published":586,"date":156},"\u002Fposts\u002F2025\u002F2025-03-01-爬虫实战-爬取广州大学课程表",774,"2025-03-01 14:55:48",{"path":588,"words":530,"published":589,"date":156},"\u002Fposts\u002F2025\u002F2025-04-03-hexo集成gitalk的问题","2025-04-03 14:26:34",{"path":591,"words":592,"published":593,"date":156},"\u002Fposts\u002F2025\u002F2025-09-22-记一次配置obsidian配合hexo写博客",92,"2025-09-22 16:47:52",{"path":595,"words":596,"published":597,"date":156},"\u002Fposts\u002F2025\u002F2025-10-24-10-20课题",204,"2025-10-24 08:15:01",{"path":599,"words":600,"published":601,"date":156},"\u002Fposts\u002F2025\u002F2025-11-02-组会朝花夕拾",501,"2025-11-02 18:56:59",{"path":603,"words":604,"published":605,"date":156},"\u002Fposts\u002F2025\u002F2025-11-05-基于随机加权推断模型im的参数估计算法",481,"2025-11-05 20:51:41",{"path":607,"words":608,"published":609,"date":156},"\u002Fposts\u002F2025\u002F2025-11-09-关于软考高项网规",884,"2025-11-09 19:54:52",{"path":611,"words":612,"published":613,"date":156},"\u002Fposts\u002F2025\u002F2025-11-17-arch-linux运行appimage相关",365,"2025-11-17 09:59:59",{"path":615,"words":616,"published":617,"date":156},"\u002Fposts\u002F2025\u002F2025-11-19-相关概念",2058,"2025-11-19 11:06:20",{"path":619,"words":620,"published":621,"date":156},"\u002Fposts\u002F2025\u002F2025-11-21-web可视化实践canvas",6393,"2025-11-21 14:50:48",{"path":623,"words":624,"published":625,"date":156},"\u002Fposts\u002F2025\u002F2025-11-22-使用-github-actions-自动部署基于vite的项目到-github-pages",272,"2025-11-23 01:59:24",{"path":627,"words":628,"published":629,"date":156},"\u002Fposts\u002F2025\u002F2025-11-22-关于前端包管理器npmpnpmyarn和bun",4890,"2025-11-22 21:21:15",{"path":631,"words":632,"published":633,"date":156},"\u002Fposts\u002F2025\u002F2025-11-23-undo-redo-机制具体实现",7839,"2025-11-23 19:15:00",{"path":635,"words":636,"published":637,"date":156},"\u002Fposts\u002F2025\u002F2025-11-27-前端安全-关于xss与crsf",1866,"2025-11-28 02:05:25",{"path":639,"words":640,"published":641,"date":156},"\u002Fposts\u002F2025\u002F2025-12-05-现代协同-2d-画布编辑器pixijs-v8",4285,"2025-12-05 02:00:16",{"path":643,"words":644,"published":645,"date":156},"\u002Fposts\u002F2025\u002F2025-12-07-杂谈-课题组系统设计",3710,"2025-12-07 21:09:33",{"path":647,"words":648,"published":649,"date":156},"\u002Fposts\u002F2025\u002F2025-12-25-javascript中的数组方法与栈stack和队列queue的实现",474,"2025-11-29 16:58:15",{"path":651,"words":652,"published":653,"date":156},"\u002Fposts\u002F2025\u002F2025-12-25-关于javascript-实现哈希表",189,"2025-11-27 11:31:39",{"path":655,"words":656,"published":657,"date":156},"\u002Fposts\u002F2025\u002F2025-12-25-关于javascript的set方法",332,"2025-12-25 15:26:18",{"path":659,"words":660,"published":661,"date":156},"\u002Fposts\u002F2025\u002F2025-12-25-关于动态规划(背包问题为例)",1238,"2025-11-17 18:24:04",{"path":663,"words":664,"published":665,"date":156},"\u002Fposts\u002F2025\u002F2025-12-25-关于滑动窗口",712,"2025-11-20 15:04:40",{"path":667,"words":668,"published":669,"date":156},"\u002Fposts\u002F2025\u002F2025-12-25-关于链表(javascript)",500,"2025-11-25 13:00:48",{"path":671,"words":672,"published":673,"date":156},"\u002Fposts\u002F2025\u002F2025-12-25-面试算法acm模式构建构建输入输出模板",2051,"2025-12-25 23:09:45",{"path":675,"words":676,"published":677,"date":156},"\u002Fposts\u002F2025\u002F2025-12-26-javascript-数字数组字符串的处理",483,"2025-12-26 11:20:25",{"path":679,"words":680,"published":681,"date":156},"\u002Fposts\u002F2025\u002F2025-12-26-javascripttypescript-的顺序表链表实现",446,"2025-12-26 12:16:12",{"path":683,"words":684,"published":685,"date":156},"\u002Fposts\u002F2025\u002F2025-12-27-前端画布设计vol-1-实现基础yuan素渲染和状态控制",2136,"2025-12-28 01:23:08",{"path":687,"words":688,"published":689,"date":156},"\u002Fposts\u002F2025\u002F2025-12-27-前端画布设计vol-2-实现富文本编辑",1838,"2025-12-28 02:58:47",{"path":691,"words":692,"published":693,"date":156},"\u002Fposts\u002F2025\u002F2025-12-27-算法刷题-关于链表操作",2135,"2025-12-27 16:12:42",{"path":695,"words":696,"published":697,"date":156},"\u002Fposts\u002F2025\u002F2025-12-27-配置dnscrypt-proxy实现加密dns服务windows",1899,"2025-11-15 01:06:37",{"path":699,"words":700,"published":701,"date":156},"\u002Fposts\u002F2025\u002F2025-12-28-前端-关于网络请求xhrajaxfetchaxios",7788,"2025-10-28 15:48:46",{"path":703,"words":704,"published":705,"date":156},"\u002Fposts\u002F2025\u002F2025-12-28-前端-接口封装与请求规范axios为例",2373,"2025-12-29 01:01:18",{"path":707,"words":708,"published":709,"date":156},"\u002Fposts\u002F2025\u002F2025-12-28-前端-身份验证管理-基于-jwt-token-的实现",2709,"2025-11-23 22:04:41",{"path":711,"words":712,"published":713,"date":156},"\u002Fposts\u002F2025\u002F2025-12-29-记canvas画布项目开发",6254,"2025-12-29 04:52:15",{"path":715,"words":716,"published":717,"date":156},"\u002Fposts\u002F2025\u002Fabout-site",116,"2025-03-31 16:44:24",{"path":719,"words":720,"published":721,"date":156},"\u002Fposts\u002F2025\u002F使用neo4j图数据科学库gds进行中心度分析",143,"2025-04-02 23:37:24",{"path":723,"words":724,"published":725,"date":156},"\u002Fposts\u002F2026\u002F2026-01-03-论文实训草稿",10445,"2026-01-03 14:10:49",{"path":727,"words":728,"published":729,"date":156},"\u002Fposts\u002F2026\u002F2026-01-06-人工智能导论",11461,"2026-01-07 03:25:49",{"path":731,"words":732,"published":733,"date":156},"\u002Fposts\u002F2026\u002F2026-01-07-机器学习相关算法",82,"2026-01-08 02:28:13",{"path":735,"words":736,"published":737,"date":156},"\u002Fposts\u002F2026\u002F2026-01-16-关于低复杂度最长链共识算法设计",4466,"2026-01-16 10:33:23",{"path":739,"words":740,"published":741,"date":156},"\u002Fposts\u002F2026\u002F2026-01-19-杂记2026-01-19",5754,"2026-01-20 01:03:26",{"path":743,"words":744,"published":745,"date":156},"\u002Fposts\u002F2026\u002F2026-01-22-github-action-自动同步博客到-github-主页",1069,"2026-01-22 16:31:47",{"path":747,"words":748,"published":749,"date":156},"\u002Fposts\u002F2026\u002F2026-03-01-windows-wsl安装docker",257,"2026-03-01 20:55:31",{"path":751,"words":752,"published":753,"date":156},"\u002Fposts\u002F2026\u002F2026-03-14-关于-msys2",701,"2026-03-15 03:05:04",{"path":755,"words":756,"published":757,"date":156},"\u002Fposts\u002F2026\u002F2026-03-28-团队项目协作规范随记",2419,"2026-03-29 05:33:50",{"path":759,"words":760,"published":761,"date":156},"\u002Fposts\u002F2026\u002F2026-03-29-oh-my-posh配置分享",104,"2026-03-29 16:34:43",{"path":763,"words":764,"published":765,"date":156},"\u002Fposts\u002F2026\u002F2026-06-13-从上下文工程到-agent-harness-engineering",8840,"2026-06-13 21:06:20",{"path":767,"words":768,"published":769,"date":156},"\u002Fposts\u002F2026\u002F2026-07-13-简谈前端基建质量标准与ai友好建设",3814,"2026-07-13 21:06:20",{"path":771,"words":772,"published":773,"date":156},"\u002Fposts\u002F2026\u002F2026-07-15-agentic-rag-系统实践",13357,"2026-07-15 21:06:20",{"path":775,"words":776,"published":777,"date":156},"\u002Fposts\u002F2026\u002F2026-07-18-简谈sdd规范驱动开发-copy",4476,"2026-07-18 11:06:20",{"path":779,"words":780,"published":781,"date":156},"\u002Fposts\u002F2026\u002F2026-07-20-个人neovim配置分享",366,"2026-07-22 13:46:50",{"path":783,"words":784,"published":785,"date":156},"\u002Fposts\u002F2026\u002F2026-07-20-关于技术写作-设计文档",6763,"2026-07-20 13:46:50",{"path":787,"words":788,"published":789,"date":156},"\u002Fposts\u002F2026\u002F2026-07-29-fastapi-工程实践随记",3417,"2026-07-29 04:58:34",{"path":791,"words":792,"published":793,"date":156},"\u002Fposts\u002Frfc_agentic_project\u002F2026-06-19-rfc-liskin_code_agent",3563,"2026-06-19 15:18:20",{"path":795,"words":796,"published":797,"date":156},"\u002Fposts\u002Frfc_agentic_project\u002F2026-07-25-rfc-glushkov_ogas",13461,"2026-07-28 23:46:50",{"path":799,"words":800,"published":793,"date":156},"\u002Fposts\u002Frfc_agentic_project\u002F2026-08-03-adr-ogas-arkhiv",2698,{"path":802,"words":803,"published":804,"date":156},"\u002Fposts\u002Frfc_agentic_project\u002Frag\u002F2026-08-12-arkhiv_rag-vol-1",4366,"2026-08-12 15:18:20",{"path":806,"words":807,"published":808,"date":156},"\u002Fposts\u002Fleetcode\u002F2025-12-25-力扣百题速练javascripttypescriptvol-1",3108,"2025-12-25 13:57:08",{"path":810,"words":811,"published":812,"date":156},"\u002Fposts\u002Fleetcode\u002F2025-12-26-力扣百题速练javascripttypescriptvol-2",3185,"2025-12-26 13:57:08",{"path":814,"words":815,"published":816,"date":156},"\u002Fposts\u002Fleetcode\u002F2025-12-28-力扣百题速练javascripttypescriptvol-3",2533,"2025-12-29 02:15:44",{"path":818,"words":819,"published":820,"date":156},"\u002Fposts\u002Fleetcode\u002F2026-01-17-力扣百题速练javascripttypescriptvol-4",3024,"2026-01-17 22:53:01",{"path":822,"words":823,"published":824,"date":156},"\u002Fposts\u002Fleetcode\u002F2026-01-19-力扣百题速练javascripttypescriptvol-5",293,"2026-01-19 15:15:12",{"path":826,"words":827,"published":828,"date":156},"\u002Fposts\u002F分布式处理与计算\u002F分布式处理与计算spark系统与scala语言",4320,"2026-07-06 14:10:49",{"path":830,"words":831,"published":832,"date":156},"\u002Fposts\u002F分布式处理与计算\u002F分布式处理与计算分类与回归分析",2081,"2026-07-07 12:40:29",{"path":834,"words":835,"published":836,"date":156},"\u002Fposts\u002F分布式处理与计算\u002F分布式处理与计算数值优化方法",2182,"2026-07-07 13:50:29",{"path":838,"words":839,"published":840,"date":156},"\u002Fposts\u002F分布式处理与计算\u002F分布式处理与计算数据降维",1583,"2026-07-07 21:50:29",{"path":842,"words":843,"published":844,"date":156},"\u002Fposts\u002F分布式处理与计算\u002F分布式处理与计算聚类分析",1882,"2026-07-07 16:50:29",{"path":846,"words":847,"published":848,"date":156},"\u002Fposts\u002F分布式处理与计算\u002F分布式处理与计算随机模拟与统计推断",2433,"2026-07-06 22:40:29",{"path":850,"words":851,"published":852,"date":156},"\u002Fposts\u002F数据可视化\u002F2026-06-14-数据可视化-基本图像",10011,"2026-06-14 20:18:20",{"path":854,"words":855,"published":856,"date":156},"\u002Fposts\u002F数据可视化\u002F2026-06-14-数据可视化-概论",10030,"2026-06-14 15:18:20",{"path":858,"words":859,"published":860,"date":156},"\u002Fposts\u002F数据可视化\u002F2026-06-15-数据可视化-可视化库",2032,"2026-06-15 20:18:20",{"path":862,"words":863,"published":864,"date":156},"\u002Fposts\u002F数据结构\u002F2025-09-29-数据结构-图",5451,"2025-04-15 20:48:06",{"path":866,"words":867,"published":868,"date":156},"\u002Fposts\u002F数据结构\u002F2025-09-29-数据结构-树",4211,"2025-04-30 02:19:06",{"path":870,"words":871,"published":872,"date":156},"\u002Fposts\u002F数据结构\u002F2025-09-29-数据结构-队列",921,"2025-04-11 15:30:08",{"path":874,"words":875,"published":876,"date":156},"\u002Fposts\u002F数据结构\u002F关于数据结构的一些想法",456,"2025-04-04 19:13:49",{"path":878,"words":879,"published":880,"date":156},"\u002Fposts\u002F数据结构\u002F数据结构-栈",920,"2025-04-18 00:17:37",{"path":882,"words":883,"published":884,"date":156},"\u002Fposts\u002F数据结构\u002F数据结构-算法复杂度",2153,"2025-04-05 16:09:55",{"path":886,"words":887,"published":888,"date":156},"\u002Fposts\u002F数据结构\u002F数据结构-线性表链表",4572,"2025-04-06 00:24:40",{"path":890,"words":891,"published":892,"date":156},"\u002Fposts\u002F数据结构\u002F数据结构-线性表顺序表",4191,"2025-04-05 22:09:59",{"path":894,"words":895,"published":896,"date":156},"\u002Fposts\u002F数据结构\u002F数据结构-绪论",2881,"2025-04-05 11:31:22",{"path":898,"words":899,"published":156,"date":900},"\u002Fposts\u002F杂记\u002F2023-12-26-2023年12月26日",7,"2023-12-26 23:51:33",{"path":902,"words":899,"published":156,"date":903},"\u002Fposts\u002F杂记\u002F2024-01-01-2024团建","2024-01-01 01:51:27",{"path":905,"words":581,"published":156,"date":906},"\u002Fposts\u002F杂记\u002F2024-01-09-随记","2024-01-09 20:50:35",{"path":908,"words":909,"published":156,"date":910},"\u002Fposts\u002F杂记\u002F2024-03-12-花名",5275,"2024-03-12 16:04:23",{"path":912,"words":913,"published":156,"date":914},"\u002Fposts\u002F杂记\u002F2024-04-15-逆模因",1353,"2024-04-15 00:26:16",{"path":916,"words":917,"published":156,"date":918},"\u002Fposts\u002F杂记\u002F2024-05-03-艺作",27,"2024-05-03 00:01:00",{"path":920,"words":921,"published":156,"date":922},"\u002Fposts\u002F杂记\u002F2024-05-21-关于博客",1720,"2024-02-21 23:21:11",{"path":924,"words":925,"published":156,"date":926},"\u002Fposts\u002F杂记\u002F2024-06-20-dnvrc维克多崔专访-2023",2036,"2024-06-20 00:28:39",{"path":928,"words":760,"published":156,"date":929},"\u002Fposts\u002F杂记\u002F2024-06-25-6月25日随记","2024-06-25 12:46:36",{"path":931,"words":932,"published":156,"date":933},"\u002Fposts\u002F杂记\u002F2024-06-25-歌名-想見星星",148,"2024-06-25 22:47:59",{"path":935,"words":936,"published":156,"date":937},"\u002Fposts\u002F杂记\u002F2024-07-11-桂花岗",6,"2024-07-11 00:28:17",{"path":939,"words":940,"published":156,"date":941},"\u002Fposts\u002F杂记\u002F2024-07-15-rolling-bocci",9,"2024-07-15 21:25:56",{"path":943,"words":944,"published":156,"date":945},"\u002Fposts\u002F杂记\u002F2024-07-22-七月九日",34,"2024-07-09 17:54:23",{"path":947,"words":948,"published":156,"date":949},"\u002Fposts\u002F杂记\u002F2024-07-22-六月随记",1052,"2024-07-22 01:03:19",{"path":951,"words":952,"published":156,"date":953},"\u002Fposts\u002F杂记\u002F2024-07-22-石菖蒲",41,"2024-07-10 01:26:05",{"path":955,"words":514,"published":156,"date":956},"\u002Fposts\u002F杂记\u002F2024-07-23-新书","2024-07-23 01:05:49",{"path":958,"words":959,"published":156,"date":960},"\u002Fposts\u002F杂记\u002F2024-07-29-年前",74,"2024-07-29 23:59:07",{"path":962,"words":963,"published":156,"date":964},"\u002Fposts\u002F杂记\u002F2024-07-30-周边",138,"2024-07-30 02:03:23",{"path":966,"words":967,"published":156,"date":968},"\u002Fposts\u002F杂记\u002F2024-07-31-2024-7-31日",185,"2024-07-31 01:21:52",{"path":970,"words":971,"published":156,"date":972},"\u002Fposts\u002F杂记\u002F2024-08-02-八月",1710,"2024-08-30 00:31:02",{"path":974,"words":975,"published":156,"date":976},"\u002Fposts\u002F杂记\u002F2024-09-01-九月",1484,"2024-09-26 16:30:15",{"path":978,"words":979,"published":156,"date":980},"\u002Fposts\u002F杂记\u002F2024-09-08-2024年9月8日",97,"2024-09-08 13:59:36",{"path":982,"words":514,"published":156,"date":983},"\u002Fposts\u002F杂记\u002F2024-09-19-博客站的一周年","2024-09-18 23:36:24",{"path":985,"words":986,"published":156,"date":987},"\u002Fposts\u002F杂记\u002F2024-10-03-十月",1028,"2024-10-31 23:54:27",{"path":989,"words":990,"published":156,"date":991},"\u002Fposts\u002F杂记\u002F2024-11-04-十一月",2134,"2024-11-30 00:04:39",{"path":993,"words":994,"published":156,"date":995},"\u002Fposts\u002F杂记\u002F2024-11-10-gzhu-site-193",80,"2024-11-10 19:19:12",{"path":997,"words":998,"published":156,"date":999},"\u002Fposts\u002F杂记\u002F2024-12-01-十二月",455,"2024-12-30 23:13:47",{"path":1001,"words":1002,"published":156,"date":1003},"\u002Fposts\u002F杂记\u002F2024-12-21-年末",23,"2024-12-21 23:21:49",{"path":1005,"words":522,"published":156,"date":1006},"\u002Fposts\u002F杂记\u002F2025-01-30-一月","2025-01-30 23:44:41",{"path":1008,"words":1009,"published":156,"date":1010},"\u002Fposts\u002F杂记\u002F2025-03-01-二月",224,"2025-02-28 00:11:08",{"path":1012,"words":1013,"published":156,"date":1014},"\u002Fposts\u002F杂记\u002F2025-03-01-博客杂谈",344,"2025-03-01 16:03:18",{"path":1016,"words":1017,"published":156,"date":1018},"\u002Fposts\u002F杂记\u002F2025-03-05-三月",2090,"2025-03-05 19:17:28",{"path":1020,"words":1021,"published":156,"date":1022},"\u002Fposts\u002F杂记\u002F2025-07-10-七月",361,"2025-07-10 22:04:32",{"path":1024,"words":1025,"published":156,"date":1026},"\u002Fposts\u002F杂记\u002F2025-09-21-九月",781,"2025-09-21 20:53:37",{"path":1028,"words":1029,"published":156,"date":1030},"\u002Fposts\u002F杂记\u002F2025-10-09-十月",591,"2025-10-09 00:35:07",{"path":1032,"words":1033,"published":156,"date":1034},"\u002Fposts\u002F杂记\u002Fcontrol",13,"2023-09-25 13:03:59",{"path":1036,"words":1037,"published":156,"date":1038},"\u002Fposts\u002F杂记\u002Fquadim四叉树图像处理",1094,"2023-10-21 11:27:06",{"path":1040,"words":1041,"published":156,"date":1042},"\u002Fposts\u002F杂记\u002Fsuccess",24,"2023-09-22 15:59:07",{"path":1044,"words":1045,"published":156,"date":1046},"\u002Fposts\u002F杂记\u002F三光年",295,"2023-11-18 04:18:40",{"path":1048,"words":1049,"published":156,"date":1050},"\u002Fposts\u002F杂记\u002F加密测试",961,"2023-11-21 14:24:01",{"path":1052,"words":1053,"published":156,"date":1054},"\u002Fposts\u002F杂记\u002F啊啊啊啊啊啊啊",54,"2023-09-20 17:29:33",{"path":1056,"words":1057,"published":156,"date":1058},"\u002Fposts\u002F杂记\u002F杂谈",124,"2023-09-25 23:11:32",{"path":1060,"words":1061,"published":156,"date":1062},"\u002Fposts\u002F杂记\u002F艹",25,"2023-10-21 17:40:43",{"path":1064,"words":1065,"published":1066,"date":156},"\u002Fposts\u002F神经网络\u002F神经网络与深度学习卷积神经网络",3168,"2026-06-07 11:23:08",{"path":1068,"words":1069,"published":1070,"date":156},"\u002Fposts\u002F神经网络\u002F神经网络与深度学习循环神经网络",2348,"2026-06-07 11:33:08",{"path":1072,"words":1073,"published":1074,"date":156},"\u002Fposts\u002F神经网络\u002F神经网络与深度学习改进学习方法",3360,"2026-06-07 10:13:08",{"path":1076,"words":1077,"published":1078,"date":156},"\u002Fposts\u002F神经网络\u002F神经网络与深度学习深度生成模型",2727,"2026-06-07 11:43:08",{"path":1080,"words":1081,"published":1082,"date":156},"\u002Fposts\u002F神经网络\u002F神经网络与深度学习神经网络基础",3205,"2026-06-07 10:03:08",{"id":1084,"title":1085,"abbrlink":1086,"body":1087,"category":40,"cover":156,"date":156,"description":1166,"extension":1928,"mathjax":1929,"meta":1930,"navigation":1933,"path":886,"published":888,"readingMinutes":1934,"seo":1935,"stem":1936,"sticky":156,"swiper_index":156,"tags":1937,"updated":156,"words":887,"__hash__":1938},"posts\u002Fposts\u002F数据结构\u002F数据结构-线性表（链表）.md","数据结构-线性表（链表）","42928",{"type":1088,"value":1089,"toc":1899},"minimark",[1090,1095,1099,1102,1109,1112,1115,1120,1123,1126,1131,1137,1140,1145,1148,1151,1156,1159,1170,1175,1179,1182,1192,1204,1207,1210,1215,1218,1221,1224,1235,1238,1244,1247,1253,1256,1259,1265,1268,1273,1276,1279,1284,1287,1290,1293,1299,1302,1305,1316,1319,1327,1330,1335,1338,1344,1347,1350,1355,1358,1366,1369,1375,1380,1383,1386,1389,1400,1403,1409,1412,1417,1419,1425,1428,1433,1435,1441,1444,1447,1450,1453,1459,1462,1465,1468,1471,1477,1480,1483,1485,1488,1491,1494,1497,1500,1503,1508,1511,1514,1525,1530,1533,1539,1542,1545,1548,1556,1559,1565,1568,1574,1577,1582,1585,1588,1591,1596,1599,1602,1605,1610,1613,1616,1624,1627,1632,1635,1641,1644,1652,1657,1660,1666,1669,1677,1682,1685,1688,1694,1697,1700,1705,1708,1713,1716,1730,1733,1738,1741,1755,1758,1763,1766,1777,1780,1786,1789,1792,1795,1801,1804,1807,1810,1816,1819,1822,1825,1830,1833,1836,1845,1848,1851,1856,1859,1864,1867,1870,1873,1876,1882,1885,1891,1894],[1091,1092,1094],"h2",{"id":1093},"链表链式存储结构","链表（链式存储结构）",[1096,1097,1098],"p",{},"链表又称单链表、链式存储结构，用于存储逻辑关系为“一对一”的数据。",[1096,1100,1101],{},"和顺序表不同，使用链表存储数据，不强制要求数据在内存中集中存储，各个元素可以分散存储在内存中。例如，使用链表存储 {1,2,3}，各个元素在内存中的存储状态可能是：",[1096,1103,1104],{},[1105,1106],"img",{"alt":1107,"src":1108},"动图封面","https:\u002F\u002Fpic2.zhimg.com\u002Fv2-5d42c22a139067e60fadd7957ef2c383_b.jpg",[1096,1110,1111],{},"可以看到，数据不仅没有集中存放，在内存中的存储次序也是混乱的。那么，链表是如何存储数据间逻辑关系的呢？",[1096,1113,1114],{},"链表存储数据间逻辑关系的实现方案是：为每一个元素配置一个指针，每个元素的指针都指向自己的直接后继元素，如下图所示：",[1096,1116,1117],{},[1105,1118],{"alt":1107,"src":1119},"https:\u002F\u002Fpic4.zhimg.com\u002Fv2-fdb02aabf90a9eb2d64c5e8a06feb053_b.jpg",[1096,1121,1122],{},"显然，我们只需要记住元素 1 的存储位置，通过它的指针就可以找到元素 2，通过元素 2 的指针就可以找到元素 3，以此类推，各个元素的先后次序一目了然。",[1096,1124,1125],{},"像图 2 这样，数据元素随机存储在内存中，通过指针维系数据之间“一对一”的逻辑关系，这样的存储结构就是链表。",[1127,1128,1130],"h3",{"id":1129},"结点节点","结点（节点）",[1132,1133,1134],"blockquote",{},[1096,1135,1136],{},"很多教材中，也将“结点”写成“节点”，它们是一个意思。",[1096,1138,1139],{},"在链表中，每个数据元素都配有一个指针，这意味着，链表上的每个“元素”都长下图这个样子：",[1096,1141,1142],{},[1105,1143],{"alt":1107,"src":1144},"https:\u002F\u002Fpic3.zhimg.com\u002Fv2-375eac6ce04146b28224cf447e00b012_b.jpg",[1096,1146,1147],{},"数据域用来存储元素的值，指针域用来存放指针。数据结构中，通常将图 3 这样的整体称为结点。",[1096,1149,1150],{},"也就是说，链表中实际存放的是一个一个的结点，数据元素存放在各个结点的数据域中。举个简单的例子，图 2 中 {1,2,3} 的存储状态用链表表示，如下图所示：",[1096,1152,1153],{},[1105,1154],{"alt":1107,"src":1155},"https:\u002F\u002Fpic1.zhimg.com\u002Fv2-6c920d117fb3d0a2bdcccfd3b002e20c_b.jpg",[1096,1157,1158],{},"在 C 语言中，可以用结构体表示链表中的结点，例如：",[1160,1161,1167],"pre",{"className":1162,"code":1164,"language":1165,"meta":1166},[1163],"language-c++","typedef struct link{\n    char elem; \u002F\u002F代表数据域\n    struct link * next; \u002F\u002F代表指针域，指向直接后继元素\n}Link;\n","c++","",[1168,1169,1164],"code",{"__ignoreMap":1166},[1132,1171,1172],{},[1096,1173,1174],{},"我们习惯将结点中的指针命名为 next，因此指针域又常称为“Next 域”。",[1127,1176,1178],{"id":1177},"头结点头指针和首元结点","头结点、头指针和首元结点",[1096,1180,1181],{},"图 4 所示的链表并不完整，一个完整的链表应该由以下几部分构成：",[1183,1184,1185,1189],"ol",{},[1186,1187,1188],"li",{},"头指针：一个和结点类型相同的指针，它的特点是：永远指向链表中的第一个结点。上文提到过，我们需要记录链表中第一个元素的存储位置，就是用头指针实现。",[1186,1190,1191],{},"结点：链表中的节点又细分为头结点、首元结点和其它结点：",[1193,1194,1195,1198,1201],"ul",{},[1186,1196,1197],{},"头结点：某些场景中，为了方便解决问题，会故意在链表的开头放置一个空结点，这样的结点就称为头结点。也就是说，头结点是位于链表开头、数据域为空（不利用）的结点。",[1186,1199,1200],{},"首元结点：指的是链表开头第一个存有数据的结点。",[1186,1202,1203],{},"其他节点：链表中其他的节点。",[1096,1205,1206],{},"也就是说，一个完整的链表是由头指针和诸多个结点构成的。每个链表都必须有头指针，但头结点不是必须的。",[1096,1208,1209],{},"例如，创建一个包含头结点的链表存储 {1,2,3}，如下图所示：",[1096,1211,1212],{},[1105,1213],{"alt":1107,"src":1214},"https:\u002F\u002Fpic1.zhimg.com\u002Fv2-f2b1f40c7ed8cb36d1c7f3215f7b5530_b.jpg",[1096,1216,1217],{},"再次强调，头指针永远指向链表中的第一个结点。换句话说，如果链表中包含头结点，那么头指针指向的是头结点，反之头指针指向首元结点。",[1127,1219,1220],{"id":1220},"链表的创建",[1096,1222,1223],{},"创建一个链表，实现步骤如下：",[1183,1225,1226,1229,1232],{},[1186,1227,1228],{},"定义一个头指针；",[1186,1230,1231],{},"创建一个头结点或者首元结点，让头指针指向它；",[1186,1233,1234],{},"每创建一个结点，都令其直接前驱结点的指针指向它。",[1096,1236,1237],{},"例如，创建一个存储 {1,2,3,4} 且无头节点的链表，C 语言实现代码为：",[1160,1239,1242],{"className":1240,"code":1241,"language":1165,"meta":1166},[1163],"Link* initLink() {\n    int i;\n    \u002F\u002F1、创建头指针\n    Link* p = NULL;\n    \u002F\u002F2、创建首元结点\n    Link* temp = (Link*)malloc(sizeof(Link));\n    temp->elem = 1;\n    temp->next = NULL;\n    \u002F\u002F头指针指向首元结点\n    p = temp;\n    \u002F\u002F3、每创建一个结点，都令其直接前驱结点的指针指向它\n    for (i = 2; i \u003C 5; i++) {\n        \u002F\u002F创建一个结点\n        Link* a = (Link*)malloc(sizeof(Link));\n        a->elem = i;\n        a->next = NULL;\n        \u002F\u002F每次 temp 指向的结点就是 a 的直接前驱结点\n        temp->next = a;\n        \u002F\u002Ftemp指向下一个结点（也就是a),为下次添加结点做准备\n        temp = temp->next;\n    }\n    return p;\n}\n",[1168,1243,1241],{"__ignoreMap":1166},[1096,1245,1246],{},"再比如，创建一个存储 {1,2,3,4} 且含头节点的链表，则 C 语言实现代码为：",[1160,1248,1251],{"className":1249,"code":1250,"language":1165,"meta":1166},[1163],"Link* initLink() {\n    int i;\n    \u002F\u002F1、创建头指针\n    Link* p = NULL;\n    \u002F\u002F2、创建头结点\n    Link* temp = (Link*)malloc(sizeof(Link));\n    temp->elem = 0;\n    temp->next = NULL;\n    \u002F\u002F头指针指向头结点\n    p = temp;\n    \u002F\u002F3、每创建一个结点，都令其直接前驱结点的指针指向它\n    for (i = 1; i \u003C 5; i++) {\n        \u002F\u002F创建一个结点\n        Link* a = (Link*)malloc(sizeof(Link));\n        a->elem = i;\n        a->next = NULL;\n        \u002F\u002F每次 temp 指向的结点就是 a 的直接前驱结点\n        temp->next = a;\n        \u002F\u002Ftemp指向下一个结点（也就是a),为下次添加结点做准备\n        temp = temp->next;\n    }\n    return p;\n}\n",[1168,1252,1250],{"__ignoreMap":1166},[1127,1254,1255],{"id":1255},"链表的使用",[1096,1257,1258],{},"对于创建好的链表，我们可以依次获取链表中存储的数据，例如：",[1160,1260,1263],{"className":1261,"code":1262,"language":1165,"meta":1166},[1163],"#include \u003Cstdio.h>\n#include \u003Cstdlib.h>\n\u002F\u002F链表中节点的结构\ntypedef struct link {\n    int  elem;\n    struct link* next;\n}Link;\nLink* initLink() {\n    int i;\n    \u002F\u002F1、创建头指针\n    Link* p = NULL;\n    \u002F\u002F2、创建头结点\n    Link* temp = (Link*)malloc(sizeof(Link));\n    temp->elem = 0;\n    temp->next = NULL;\n    \u002F\u002F头指针指向头结点\n    p = temp;\n    \u002F\u002F3、每创建一个结点，都令其直接前驱结点的指针指向它\n    for (i = 1; i \u003C 5; i++) {\n        \u002F\u002F创建一个结点\n        Link* a = (Link*)malloc(sizeof(Link));\n        a->elem = i;\n        a->next = NULL;\n        \u002F\u002F每次 temp 指向的结点就是 a 的直接前驱结点\n        temp->next = a;\n        \u002F\u002Ftemp指向下一个结点（也就是a),为下次添加结点做准备\n        temp = temp->next;\n    }\n    return p;\n}\nvoid display(Link* p) {\n    Link* temp = p;\u002F\u002Ftemp指针用来遍历链表\n    \u002F\u002F只要temp指向结点的next值不是NULL，就执行输出语句。\n    while (temp) {\n        Link* f = temp;\u002F\u002F准备释放链表中的结点\n        printf(\"%d \", temp->elem);\n        temp = temp->next;\n        free(f);\n    }\n    printf(\"\\n\");\n}\nint main() {\n    Link* p = NULL;\n    printf(\"初始化链表为：\\n\");\n    \u002F\u002F创建链表{1,2,3,4}\n    p = initLink();\n    \u002F\u002F输出链表中的数据\n    display(p);\n    return 0;\n}\n",[1168,1264,1262],{"__ignoreMap":1166},[1096,1266,1267],{},"程序中创建的是带头结点的链表，头结点的数据域存储的是元素 0，因此最终的输出结果为：",[1132,1269,1270],{},[1096,1271,1272],{},"0 1 2 3 4",[1096,1274,1275],{},"如果不想输出头结点的值，可以将 p->next 作为实参传递给 display() 函数。",[1096,1277,1278],{},"如果程序中创建的是不带头结点的链表，最终的输出结果应该是：",[1132,1280,1281],{},[1096,1282,1283],{},"1 2 3 4",[1091,1285,1286],{"id":1286},"单链表的基本操作",[1096,1288,1289],{},"学会创建链表之后，本节继续讲解链表的一些基本操作，包括向链表中添加数据、删除链表中的数据、查找和更改链表中的数据。",[1096,1291,1292],{},"首先，创建一个带头结点的链表，链表中存储着 {1,2,3,4}：",[1160,1294,1297],{"className":1295,"code":1296,"language":1165,"meta":1166},[1163],"\u002F\u002F链表中节点的结构\ntypedef struct link {\n    int  elem;\n    struct link* next;\n}Link;\nLink* initLink() {\n    int i;\n    \u002F\u002F1、创建头指针\n    Link* p = NULL;\n    \u002F\u002F2、创建头结点\n    Link* temp = (Link*)malloc(sizeof(Link));\n    temp->elem = 0;\n    temp->next = NULL;\n    \u002F\u002F头指针指向头结点\n    p = temp;\n    \u002F\u002F3、每创建一个结点，都令其直接前驱结点的指针指向它\n    for (i = 1; i \u003C 5; i++) {\n        \u002F\u002F创建一个结点\n        Link* a = (Link*)malloc(sizeof(Link));\n        a->elem = i;\n        a->next = NULL;\n        \u002F\u002F每次 temp 指向的结点就是 a 的直接前驱结点\n        temp->next = a;\n        \u002F\u002Ftemp指向下一个结点（也就是a),为下次添加结点做准备\n        temp = temp->next;\n    }\n    return p;\n}\n",[1168,1298,1296],{"__ignoreMap":1166},[1127,1300,1301],{"id":1301},"链表插入元素",[1096,1303,1304],{},"同顺序表一样，向链表中增添元素，根据添加位置不同，可分为以下 3 种情况：",[1193,1306,1307,1310,1313],{},[1186,1308,1309],{},"插入到链表的头部，作为首元节点；",[1186,1311,1312],{},"插入到链表中间的某个位置；",[1186,1314,1315],{},"插入到链表的最末端，作为链表中最后一个结点；",[1096,1317,1318],{},"对于有头结点的链表，3 种插入元素的实现思想是相同的，具体步骤是：",[1183,1320,1321,1324],{},[1186,1322,1323],{},"将新结点的 next 指针指向插入位置后的结点；",[1186,1325,1326],{},"将插入位置前结点的 next 指针指向插入结点；",[1096,1328,1329],{},"例如，在链表 {1,2,3,4}的基础上分别实现在头部、中间、尾部插入新元素 5，其实现过程如下图所示：",[1096,1331,1332],{},[1105,1333],{"alt":1107,"src":1334},"https:\u002F\u002Fpica.zhimg.com\u002Fv2-2b74576c4133d98967e430da2a156c6e_b.jpg",[1096,1336,1337],{},"从图中可以看出，虽然新元素的插入位置不同，但实现插入操作的方法是一致的，都是先执行步骤 1 ，再执行步骤 2。实现代码如下：",[1160,1339,1342],{"className":1340,"code":1341,"language":1165,"meta":1166},[1163],"void insertElem(Link* p, int elem, int add) {\n    int i;\n    Link* c = NULL;\n    Link* temp = p;\u002F\u002F创建临时结点temp\n    \u002F\u002F首先找到要插入位置的上一个结点\n    for (i = 1; i \u003C add; i++) {\n        temp = temp->next;\n        if (temp == NULL) {\n            printf(\"插入位置无效\\n\");\n            return;\n        }\n    }\n    \u002F\u002F创建插入结点c\n    c = (Link*)malloc(sizeof(Link));\n    c->elem = elem;\n    \u002F\u002F① 将新结点的 next 指针指向插入位置后的结点\n    c->next = temp->next;\n    \u002F\u002F② 将插入位置前结点的 next 指针指向插入结点；\n    temp->next = c;\n}\n",[1168,1343,1341],{"__ignoreMap":1166},[1096,1345,1346],{},"注意：链表插入元素的操作必须是先步骤 1，再步骤 2；反之，若先执行步骤 2，除非再添加一个指针，作为插入位置后续链表的头指针，否则会导致插入位置后的这部分链表丢失，无法再实现步骤 1。",[1096,1348,1349],{},"对于没有头结点的链表，在头部插入结点比较特殊，需要单独实现。",[1096,1351,1352],{},[1105,1353],{"alt":1107,"src":1354},"https:\u002F\u002Fpica.zhimg.com\u002Fv2-bc993f6cb9d4f6bfd732b0a341cfdf84_b.jpg",[1096,1356,1357],{},"和 2)、3) 种情况相比，由于链表没有头结点，在头部插入新结点，此结点之前没有任何结点，实现的步骤如下：",[1183,1359,1360,1363],{},[1186,1361,1362],{},"将新结点的指针指向首元结点；",[1186,1364,1365],{},"将头指针指向新结点。",[1096,1367,1368],{},"实现代码如下：",[1160,1370,1373],{"className":1371,"code":1372,"language":1165,"meta":1166},[1163],"Link* insertElem(Link* p, int elem, int add) {\n    if (add == 1) {\n        \u002F\u002F创建插入结点c\n        Link* c = (Link*)malloc(sizeof(Link));\n        c->elem = elem;\n        c->next = p;\n        p = c;\n        return p;\n    }\n    else {\n        int i;\n        Link* c = NULL;\n        Link* temp = p;\u002F\u002F创建临时结点temp\n        \u002F\u002F首先找到要插入位置的上一个结点\n        for (i = 1; i \u003C add-1; i++) {\n            temp = temp->next;\n            if (temp == NULL) {\n                printf(\"插入位置无效\\n\");\n                return p;\n            }\n        }\n        \u002F\u002F创建插入结点c\n        c = (Link*)malloc(sizeof(Link));\n        c->elem = elem;\n        \u002F\u002F向链表中插入结点\n        c->next = temp->next;\n        temp->next = c;\n        return p;\n    }\n}\n",[1168,1374,1372],{"__ignoreMap":1166},[1132,1376,1377],{},[1096,1378,1379],{},"注意当 add==1 成立时，形参指针 p 的值会发生变化，因此需要它的新值作为函数的返回值返回。",[1127,1381,1382],{"id":1382},"链表删除元素",[1096,1384,1385],{},"从链表中删除指定数据元素时，实则就是将存有该数据元素的节点从链表中摘除。",[1096,1387,1388],{},"对于有头结点的链表来说，无论删除头部（首元结点）、中部、尾部的结点，实现方式都一样，执行以下三步操作：",[1183,1390,1391,1394,1397],{},[1186,1392,1393],{},"找到目标元素所在结点的直接前驱结点；",[1186,1395,1396],{},"将目标结点从链表中摘下来;",[1186,1398,1399],{},"手动释放结点占用的内存空间；",[1096,1401,1402],{},"从链表上摘除目标节点，只需找到该节点的直接前驱节点 temp，执行如下操作：",[1160,1404,1407],{"className":1405,"code":1406,"language":1165,"meta":1166},[1163],"temp->next=temp->next->next;\n",[1168,1408,1406],{"__ignoreMap":1166},[1096,1410,1411],{},"例如，从存有 {1,2,3,4}的链表中删除存储元素 3 的结点，则此代码的执行效果如图 3 所示：",[1096,1413,1414],{},[1105,1415],{"alt":1107,"src":1416},"https:\u002F\u002Fpica.zhimg.com\u002Fv2-6d8f7d30515db53226312254da2db706_b.jpg",[1096,1418,1368],{},[1160,1420,1423],{"className":1421,"code":1422,"language":1165,"meta":1166},[1163],"\u002F\u002Fp为原链表，elem 为要删除的目标元素\nint delElem(Link* p, int elem) {\n    Link* del = NULL, *temp = p;\n    int find = 0;\n    \u002F\u002F1、找到目标元素的直接前驱结点\n    while (temp->next) {\n        if (temp->next->elem == elem) {\n            find = 1;\n            break;\n        }\n        temp = temp->next;\n    }\n    if (find == 0) {\n        return -1;\u002F\u002F删除失败\n    }\n    else\n    {\n        \u002F\u002F标记要删除的结点\n        del = temp->next;\n        \u002F\u002F2、将目标结点从链表上摘除\n        temp->next = temp->next->next;\n        \u002F\u002F3、释放目标结点\n        free(del);\n        return 1;\n    }\n}\n",[1168,1424,1422],{"__ignoreMap":1166},[1096,1426,1427],{},"对于不带头结点的链表，需要单独考虑删除首元结点的情况，删除其它结点的方式和上图完全相同，如下图所示：",[1096,1429,1430],{},[1105,1431],{"alt":1107,"src":1432},"https:\u002F\u002Fpica.zhimg.com\u002Fv2-a82095c25e668736e2d38dcccf45a5bc_b.jpg",[1096,1434,1368],{},[1160,1436,1439],{"className":1437,"code":1438,"language":1165,"meta":1166},[1163],"\u002F\u002Fp为原链表，elem 为要删除的目标元素\nint delElem(Link** p, int elem) {\n    Link* del = NULL, *temp = *p;\n    \u002F\u002F删除首元结点需要单独考虑\n    if (temp->elem == elem) {\n        (*p) = (*p)->next;\n        free(temp);\n        return 1;\n    }\n    else\n    {\n        int find = 0;\n        \u002F\u002F1、找到目标元素的直接前驱结点\n        while (temp->next) {\n            if (temp->next->elem == elem) {\n                find = 1;\n                break;\n            }\n            temp = temp->next;\n        }\n        if (find == 0) {\n            return -1;\u002F\u002F删除失败\n        }\n        else\n        {\n            \u002F\u002F标记要删除的结点\n            del = temp->next;\n            \u002F\u002F2、将目标结点从链表上摘除\n            temp->next = temp->next->next;\n            \u002F\u002F3、释放目标结点\n            free(del);\n            return 1;\n        }\n    }\n}\n",[1168,1440,1438],{"__ignoreMap":1166},[1096,1442,1443],{},"函数返回 1 时，表示删除成功；返回 -1，表示删除失败。注意，该函数的形参 p 为二级指针，调用时需要传递链表头指针的地址。",[1127,1445,1446],{"id":1446},"链表查找元素",[1096,1448,1449],{},"在链表中查找指定数据元素，最常用的方法是：从首元结点开始依次遍历所有节点，直至找到存储目标元素的结点。如果遍历至最后一个结点仍未找到，表明链表中没有存储该元素。",[1096,1451,1452],{},"因此，链表中查找特定数据元素的 C 语言实现代码为：",[1160,1454,1457],{"className":1455,"code":1456,"language":1165,"meta":1166},[1163],"\u002F\u002Fp为原链表，elem表示被查找元素\nint selectElem(Link* p, int elem) {\n    int i = 1;\n    \u002F\u002F带头结点，p 指向首元结点\n    p = p->next;\n    while (p) {\n        if (p->elem == elem) {\n            return i;\n        }\n        p = p->next;\n        i++;\n    }\n    return -1;\u002F\u002F返回-1，表示未找到\n}\n",[1168,1458,1456],{"__ignoreMap":1166},[1096,1460,1461],{},"注意第 5 行代码，对于有结点的链表，需要先将 p 指针指向首元结点；反之，对于不带头结点的链表，注释掉第 5 行代码即可。",[1127,1463,1464],{"id":1464},"链表更新元素",[1096,1466,1467],{},"更新链表中的元素，只需通过遍历找到存储此元素的节点，对节点中的数据域做更改操作即可。",[1096,1469,1470],{},"直接给出链表中更新数据元素的 C 语言实现代码：",[1160,1472,1475],{"className":1473,"code":1474,"language":1165,"meta":1166},[1163],"\u002F\u002Fp 为有头结点的链表，oldElem 为旧元素，newElem 为新元素\nint amendElem(Link* p, int oldElem, int newElem) {\n    p = p->next;\n    while (p) {\n        if (p->elem == oldElem) {\n            p->elem = newElem;\n            return 1;\n        }\n        p = p->next;\n    }\n    return -1;\n}\n",[1168,1476,1474],{"__ignoreMap":1166},[1096,1478,1479],{},"函数返回 1，表示更改成功；返回数字 -1，表示更改失败。如果是没有头结点的链表，直接删除第 3 行代码即可。",[1481,1482],"hr",{},[1481,1484],{},[1091,1486,1487],{"id":1487},"双向链表",[1096,1489,1490],{},"目前我们所学到的链表，无论是动态链表还是静态链表，表中各个节点都只包含一个指针（游标），且都统一指向直接后继节点，这类链表又统称为单向链表或单链表。",[1096,1492,1493],{},"虽然单链表能 100% 存储逻辑关系为 \"一对一\" 的数据，但在解决某些实际问题时，单链表的执行效率并不高。例如，若实际问题中需要频繁地查找某个结点的前驱结点，使用单链表存储数据显然没有优势，因为单链表的强项是从前往后查找目标元素，不擅长从后往前查找元素。",[1096,1495,1496],{},"解决此类问题，可以建立双向链表（简称双链表）。",[1127,1498,1499],{"id":1499},"双向链表是什么",[1096,1501,1502],{},"从名字上理解双向链表，即链表是 \"双向\" 的，如下图所示：",[1096,1504,1505],{},[1105,1506],{"alt":1107,"src":1507},"https:\u002F\u002Fpic4.zhimg.com\u002Fv2-62da5191aa8b27e80c1ffc4b1d61d367_b.jpg",[1096,1509,1510],{},"“双向”指的是各节点之间的逻辑关系是双向的，头指针通常只设置一个。",[1096,1512,1513],{},"从上图中可以看到，双向链表中各节点包含以下 3 部分信息（如图 2 所示）：",[1183,1515,1516,1519,1522],{},[1186,1517,1518],{},"指针域：用于指向当前节点的直接前驱节点；",[1186,1520,1521],{},"数据域：用于存储数据元素。",[1186,1523,1524],{},"指针域：用于指向当前节点的直接后继节点；",[1096,1526,1527],{},[1105,1528],{"alt":1107,"src":1529},"https:\u002F\u002Fpic4.zhimg.com\u002Fv2-6b063e7219eb5143755d567c16dc06b1_b.jpg",[1096,1531,1532],{},"因此，双链表的节点结构用 C 语言实现为：",[1160,1534,1537],{"className":1535,"code":1536,"language":1165,"meta":1166},[1163],"typedef struct line{\n    struct line * prior; \u002F\u002F指向直接前趋\n    int data;\n    struct line * next; \u002F\u002F指向直接后继\n}Line;\n",[1168,1538,1536],{"__ignoreMap":1166},[1127,1540,1541],{"id":1541},"双向链表的创建",[1096,1543,1544],{},"同单链表相比，双链表仅是各节点多了一个用于指向直接前驱的指针域。因此，我们可以在单链表的基础轻松实现对双链表的创建。",[1096,1546,1547],{},"需要注意的是，与单链表不同，双链表创建过程中，每创建一个新节点都要与其前驱节点建立两次联系，分别是：",[1193,1549,1550,1553],{},[1186,1551,1552],{},"将新节点的 prior 指针指向直接前驱节点；",[1186,1554,1555],{},"将直接前驱节点的 next 指针指向新节点；",[1096,1557,1558],{},"这里给出创建双向链表的 C 语言实现代码：",[1160,1560,1563],{"className":1561,"code":1562,"language":1165,"meta":1166},[1163],"Line* initLine(Line* head) {\n    Line* list = NULL;\n    head = (Line*)malloc(sizeof(Line));\u002F\u002F创建链表第一个结点（首元结点）\n    head->prior = NULL;\n    head->next = NULL;\n    head->data = 1;\n    list = head;\n    for (int i = 2; i \u003C= 5; i++) {\n        \u002F\u002F创建并初始化一个新结点\n        Line* body = (Line*)malloc(sizeof(Line));\n        body->prior = NULL;\n        body->next = NULL;\n        body->data = i;\n        \u002F\u002F直接前趋结点的next指针指向新结点\n        list->next = body;\n        \u002F\u002F新结点指向直接前趋结点\n        body->prior = list;\n        list = list->next;\n    }\n    return head;\n}\n",[1168,1564,1562],{"__ignoreMap":1166},[1096,1566,1567],{},"我们可以尝试着在 main 函数中输出创建的双链表，C 语言代码如下：",[1160,1569,1572],{"className":1570,"code":1571,"language":1165,"meta":1166},[1163],"#include \u003Cstdio.h>\n#include \u003Cstdlib.h>\ntypedef struct line {\n    struct line* prior; \u002F\u002F指向直接前趋\n    int data;\n    struct line* next; \u002F\u002F指向直接后继\n}Line;\n\nLine* initLine(Line* head) {\n    int i;\n    Line* list = NULL;\n    head = (Line*)malloc(sizeof(Line));\u002F\u002F创建链表第一个结点（首元结点）\n    head->prior = NULL;\n    head->next = NULL;\n    head->data = 1;\n    list = head;\n    for (i = 2; i \u003C= 5; i++) {\n        \u002F\u002F创建并初始化一个新结点\n        Line* body = (Line*)malloc(sizeof(Line));\n        body->prior = NULL;\n        body->next = NULL;\n        body->data = i;\n        \u002F\u002F直接前趋结点的next指针指向新结点\n        list->next = body;\n        \u002F\u002F新结点指向直接前趋结点\n        body->prior = list;\n        list = list->next;\n    }\n    return head;\n}\n\u002F\u002F输出链表中的数据\nvoid display(Line* head) {\n    Line* temp = head;\n    while (temp) {\n        \u002F\u002F如果该节点无后继节点，说明此节点是链表的最后一个节点\n        if (temp->next == NULL) {\n            printf(\"%d\\n\", temp->data);\n        }\n        else {\n            printf(\"%d \u003C-> \", temp->data);\n        }\n        temp = temp->next;\n    }\n}\n\u002F\u002F释放链表中结点占用的空间\nvoid free_line(Line* head) {\n    Line* temp = head;\n    while (temp) {\n        head = head->next;\n        free(temp);\n        temp = head;\n    }\n}\n\nint main()\n{\n    \u002F\u002F创建一个头指针\n    Line* head = NULL;\n    \u002F\u002F调用链表创建函数\n    head = initLine(head);\n    \u002F\u002F输出创建好的链表\n    display(head);\n    \u002F\u002F显示双链表的优点\n    printf(\"链表中第 4 个节点的直接前驱是：%d\", head->next->next->next->prior->data);\n    free_line(head);\n    return 0;\n}\n",[1168,1573,1571],{"__ignoreMap":1166},[1096,1575,1576],{},"程序运行结果：",[1132,1578,1579],{},[1096,1580,1581],{},"1 \u003C-> 2 \u003C-> 3 \u003C-> 4 \u003C-> 5 链表中第 4 个节点的直接前驱是：3",[1091,1583,1584],{"id":1584},"双向链表基本操作",[1096,1586,1587],{},"前面学习了如何创建一个双向链表，本节学习有关双向链表的一些基本操作，即如何在双向链表中添加、删除、查找或更改数据元素。",[1096,1589,1590],{},"本节知识基于已熟练掌握双向链表创建过程的基础上，我们继续上节所创建的双向链表来学习本节内容，创建好的双向链表如下图所示：",[1096,1592,1593],{},[1105,1594],{"alt":1107,"src":1595},"https:\u002F\u002Fpic2.zhimg.com\u002Fv2-c5f7cce2077c56369e912c09fbe8b1ef_b.jpg",[1096,1597,1598],{},"图 双向链表示意图",[1127,1600,1601],{"id":1601},"双向链表添加节点",[1096,1603,1604],{},"根据数据添加到双向链表中的位置不同，可细分为以下 3 种情况：",[1183,1606,1607],{},[1186,1608,1609],{},"添加至表头",[1096,1611,1612],{},"将新数据元素添加到表头，只需要将该元素与表头元素建立双层逻辑关系即可。",[1096,1614,1615],{},"换句话说，假设新元素节点为 temp，表头节点为 head，则需要做以下 2 步操作即可：",[1183,1617,1618,1621],{},[1186,1619,1620],{},"temp->next=head; head->prior=temp;",[1186,1622,1623],{},"将 head 移至 temp，重新指向新的表头；",[1096,1625,1626],{},"例如，将新元素 7 添加至双链表的表头，则实现过程如图 2 所示：",[1096,1628,1629],{},[1105,1630],{"alt":1107,"src":1631},"https:\u002F\u002Fpic2.zhimg.com\u002Fv2-b9156e5d719713d2e4e61c308869a13b_b.jpg",[1096,1633,1634],{},"图 添加元素至双向链表的表头",[1183,1636,1638],{"start":1637},2,[1186,1639,1640],{},"添加至表的中间位置",[1096,1642,1643],{},"同单链表添加数据类似，双向链表中间位置添加数据需要经过以下 2 个步骤，如下图所示：",[1183,1645,1646,1649],{},[1186,1647,1648],{},"新节点先与其直接后继节点建立双层逻辑关系；",[1186,1650,1651],{},"新节点的直接前驱节点与之建立双层逻辑关系；",[1096,1653,1654],{},[1105,1655],{"alt":1107,"src":1656},"https:\u002F\u002Fpic2.zhimg.com\u002Fv2-f5407b137acf9de84e56c5e30cfc16e7_b.jpg",[1096,1658,1659],{},"图 双向链表中间位置添加数据元素",[1183,1661,1663],{"start":1662},3,[1186,1664,1665],{},"添加至表尾",[1096,1667,1668],{},"与添加到表头是一个道理，实现过程如下（如图 4 所示）：",[1183,1670,1671,1674],{},[1186,1672,1673],{},"找到双链表中最后一个节点；",[1186,1675,1676],{},"让新节点与最后一个节点进行双层逻辑关系；",[1096,1678,1679],{},[1105,1680],{"alt":1107,"src":1681},"https:\u002F\u002Fpic1.zhimg.com\u002Fv2-829fe83055126221b40116352bf5cdc6_b.jpg",[1096,1683,1684],{},"图 双向链表尾部添加数据元素",[1096,1686,1687],{},"因此，我们可以试着编写双向链表添加数据的 C 语言代码，参考代码如下：",[1160,1689,1692],{"className":1690,"code":1691,"language":1165,"meta":1166},[1163],"Line* insertLine(Line* head, int data, int add) {\n    \u002F\u002F新建数据域为data的结点\n    Line* temp = (Line*)malloc(sizeof(Line));\n    temp->data = data;\n    temp->prior = NULL;\n    temp->next = NULL;\n    \u002F\u002F插入到链表头，要特殊考虑\n    if (add == 1) {\n        temp->next = head;\n        head->prior = temp;\n        head = temp;\n    }\n    else {\n        int i;\n        Line* body = head;\n        \u002F\u002F找到要插入位置的前一个结点\n        for (i = 1; i \u003C add - 1; i++) {\n            body = body->next;\n            \u002F\u002F只要 body 不存在，表明插入位置输入错误\n            if (!body) {\n                printf(\"插入位置有误！\\n\");\n                return head;\n            }\n        }\n        \u002F\u002F判断条件为真，说明插入位置为链表尾，实现第 2 种情况\n        if (body && (body->next == NULL)) {\n            body->next = temp;\n            temp->prior = body;\n        }\n        else {\n            \u002F\u002F第 2 种情况的具体实现\n            body->next->prior = temp;\n            temp->next = body->next;\n            body->next = temp;\n            temp->prior = body;\n        }\n    }\n    return head;\n}\n",[1168,1693,1691],{"__ignoreMap":1166},[1127,1695,1696],{"id":1696},"双向链表删除节点",[1096,1698,1699],{},"和添加结点的思想类似，在双向链表中删除目标结点也分为 3 种情况。",[1183,1701,1702],{},[1186,1703,1704],{},"删除表头结点",[1096,1706,1707],{},"删除表头结点的过程如下图所示：",[1096,1709,1710],{},[1105,1711],{"alt":1107,"src":1712},"https:\u002F\u002Fpicx.zhimg.com\u002Fv2-66cf8b9a6cc816e4a69143a68b662e25_b.jpg",[1096,1714,1715],{},"删除表头结点的实现过程是：",[1183,1717,1718,1721,1724,1727],{},[1186,1719,1720],{},"新建一个指针指向表头结点；",[1186,1722,1723],{},"断开表头结点和其直接后续结点之间的关联，更改 head 头指针的指向，同时将其直接后续结点的 prior 指针指向 NULL；",[1186,1725,1726],{},"释放表头结点占用的内存空间。",[1186,1728,1729],{},"删除表中结点",[1096,1731,1732],{},"删除表中结点的过程如下图所示：",[1096,1734,1735],{},[1105,1736],{"alt":1107,"src":1737},"https:\u002F\u002Fpic2.zhimg.com\u002Fv2-08e8d26851903ee8889321bbd20279d9_b.jpg",[1096,1739,1740],{},"删除表中结点的实现过程是：",[1183,1742,1743,1746,1749,1752],{},[1186,1744,1745],{},"找到目标结点，新建一个指针指向改结点；",[1186,1747,1748],{},"将目标结点从链表上摘除；",[1186,1750,1751],{},"释放该结点占用的内存空间。",[1186,1753,1754],{},"删除表尾结点",[1096,1756,1757],{},"删除表尾结点的过程如下图所示：",[1096,1759,1760],{},[1105,1761],{"alt":1107,"src":1762},"https:\u002F\u002Fpicx.zhimg.com\u002Fv2-8c26da9694cfa9d5cdbe2043e553795b_b.jpg",[1096,1764,1765],{},"删除表尾结点的实现过程是：",[1183,1767,1768,1771,1774],{},[1186,1769,1770],{},"找到表尾结点，新建一个指针指向该结点；",[1186,1772,1773],{},"断点表尾结点和其直接前驱结点的关联，并将其直接前驱结点的 next 指针指向 NULL；",[1186,1775,1776],{},"释放表尾结点占用的内存空间。",[1096,1778,1779],{},"双向链表删除节点的 C 语言实现代码如下：",[1160,1781,1784],{"className":1782,"code":1783,"language":1165,"meta":1166},[1163],"\u002F\u002F删除结点的函数，data为要删除结点的数据域的值\nLine* delLine(Line* head, int data) {\n    Line* temp = head;\n    while (temp) {\n        if (temp->data == data) {\n            \u002F\u002F删除表头结点\n            if (temp->prior == NULL) {\n                head = head->next;\n                if (head) {\n                    head->prior = NULL;\n                    temp->next = NULL;\n                }\n                free(temp);\n                return head;\n            }\n            \u002F\u002F删除表中结点\n            if (temp->prior && temp->next) {\n                temp->next->prior = temp->prior;\n                temp->prior->next = temp->next;\n                free(temp);\n                return head;\n            }\n            \u002F\u002F删除表尾结点\n            if (temp->next == NULL) {\n                temp->prior->next = NULL;\n                temp->prior = NULL;\n                free(temp);\n                return head;\n            }\n        }\n        temp = temp->next;\n    }\n    printf(\"表中没有目标元素，删除失败\\n\");\n    return head;\n}\n",[1168,1785,1783],{"__ignoreMap":1166},[1127,1787,1788],{"id":1788},"双向链表查找节点",[1096,1790,1791],{},"通常情况下，双向链表和单链表一样都仅有一个头指针。因此，双链表查找指定元素的实现同单链表类似，也是从表头依次遍历表中元素。",[1096,1793,1794],{},"C 语言实现代码为：",[1160,1796,1799],{"className":1797,"code":1798,"language":1165,"meta":1166},[1163],"\u002F\u002Fhead为原双链表，elem表示被查找元素\nint selectElem(line * head,int elem){\n\u002F\u002F新建一个指针t，初始化为头指针 head\n    line * t=head;\n    int i=1;\n    while (t) {\n        if (t->data==elem) {\n            return i;\n        }\n        i++;\n        t=t->next;\n    }\n    \u002F\u002F程序执行至此处，表示查找失败\n    return -1;\n}\n",[1168,1800,1798],{"__ignoreMap":1166},[1127,1802,1803],{"id":1803},"双向链表更改节点",[1096,1805,1806],{},"更改双链表中指定结点数据域的操作是在查找的基础上完成的。实现过程是：通过遍历找到存储有该数据元素的结点，直接更改其数据域即可。",[1096,1808,1809],{},"实现此操作的 C 语言实现代码如下：",[1160,1811,1814],{"className":1812,"code":1813,"language":1165,"meta":1166},[1163],"\u002F\u002F更新函数，其中，add 表示要修改的元素，newElem 为新数据的值\nvoid amendElem(Line* p, int oldElem, int newElem) {\n    Line* temp = p;\n    int find = 0;\n    \u002F\u002F找到要修改的目标结点\n    while (temp)\n    {\n        if (temp->data == oldElem) {\n            find = 1;\n            break;\n        }\n        temp = temp->next;\n    }\n    \u002F\u002F成功找到，则进行更改操作\n    if (find == 1) {\n        temp->data = newElem;\n        return;\n    }\n    \u002F\u002F查找失败，输出提示信息\n    printf(\"链表中未找到目标元素，更改失败\\n\");\n}\n",[1168,1815,1813],{"__ignoreMap":1166},[1091,1817,1818],{"id":1818},"循环链表",[1096,1820,1821],{},"无论静态链表还是动态链表，有时在解决具体问题时，需要我们对其结构进行稍微地调整。比如，可以把链表的两头连接，使其成为了一个环状链表，通常称为循环链表。",[1096,1823,1824],{},"和它名字的表意一样，只需要将表中最后一个结点的指针指向头结点，链表就能成环儿，如下图所示。",[1096,1826,1827],{},[1105,1828],{"alt":1105,"src":1829},"https:\u002F\u002Fpicx.zhimg.com\u002Fv2-584465255c37aeaae235df42d7f2ab39_1440w.jpg",[1096,1831,1832],{},"需要注意的是，虽然循环链表成环状，但本质上还是链表，因此在循环链表中，依然能够找到头指针和首元节点等。循环链表和普通链表相比，唯一的不同就是循环链表首尾相连，其他都完全一样。",[1096,1834,1835],{},"这里给大家一个循环链表的实例，用循环链表实现约瑟夫环",[1096,1837,1838],{},[1839,1840,1844],"a",{"href":1841,"rel":1842},"https:\u002F\u002Flink.zhihu.com\u002F?target=https%3A\u002F\u002Fxiexuewu.github.io\u002Fview\u002F7.html",[1843],"nofollow","循环链表实现约瑟夫环 - 玩转C语言和数据结构xiexuewu.github.io\u002Fview\u002F7.html",[1091,1846,1847],{"id":1847},"双向循环链表",[1096,1849,1850],{},"我们知道，单链表通过首尾连接可以构成单向循环链表，如下图所示：",[1096,1852,1853],{},[1105,1854],{"alt":1107,"src":1855},"https:\u002F\u002Fpic3.zhimg.com\u002Fv2-2996fac84cba2bbc4ce278d68ec1f40c_b.jpg",[1096,1857,1858],{},"同样，双向链表也可以进行首尾连接，构成双向循环链表。如下图所示：",[1096,1860,1861],{},[1105,1862],{"alt":1107,"src":1863},"https:\u002F\u002Fpic3.zhimg.com\u002Fv2-6661ba94cff67952b5108a7af5ca4564_b.jpg",[1096,1865,1866],{},"解决某些问题，可能既需要正向遍历数据，又需要逆向遍历数据，这时就可以考虑使用双向循环链表。",[1127,1868,1869],{"id":1869},"双向循环链表的创建",[1096,1871,1872],{},"创建双向循环链表，只需在创建完成双向链表的基础上，将其首尾节点进行双向连接即可。",[1096,1874,1875],{},"C 语言实现代码如下：",[1160,1877,1880],{"className":1878,"code":1879,"language":1165,"meta":1166},[1163],"\u002F\u002F创建双向循环链表\nLine* initLine(Line* head) {\n    int i;\n    Line* list = NULL;\n    head = (Line*)malloc(sizeof(Line));\u002F\u002F创建链表第一个结点（首元结点）\n    head->prior = NULL;\n    head->next = NULL;\n    head->data = 1;\n    list = head;\n    for (i = 2; i \u003C= 3; i++) {\n        \u002F\u002F创建并初始化一个新结点\n        Line* body = (Line*)malloc(sizeof(Line));\n        body->prior = NULL;\n        body->next = NULL;\n        body->data = i;\n        \u002F\u002F直接前趋结点的next指针指向新结点\n        list->next = body;\n        \u002F\u002F新结点指向直接前趋结点\n        body->prior = list;\n        list = list->next;\n    }\n    \u002F\u002F通过以上代码，已经创建好双线链表，接下来将链表的首尾节点进行双向连接\n    list->next=head;\n    head->prior=list;\n    return head;\n}\n",[1168,1881,1879],{"__ignoreMap":1166},[1096,1883,1884],{},"通过向 main 函数中调用 initLine 函数，就可以成功创建一个存储有 {1,2,3} 数据的双向循环链表，其完整的 C 语言实现代码为：",[1160,1886,1889],{"className":1887,"code":1888,"language":1165,"meta":1166},[1163],"#include \u003Cstdio.h>\n#include \u003Cstdlib.h>\ntypedef struct line {\n    struct line* prior; \u002F\u002F指向直接前趋\n    int data;\n    struct line* next; \u002F\u002F指向直接后继\n}Line;\n\u002F\u002F创建双向循环链表\nLine* initLine(Line* head) {\n    int i;\n    Line* list = NULL;\n    head = (Line*)malloc(sizeof(Line));\u002F\u002F创建链表第一个结点（首元结点）\n    head->prior = NULL;\n    head->next = NULL;\n    head->data = 1;\n    list = head;\n    for (i = 2; i \u003C= 3; i++) {\n        \u002F\u002F创建并初始化一个新结点\n        Line* body = (Line*)malloc(sizeof(Line));\n        body->prior = NULL;\n        body->next = NULL;\n        body->data = i;\n        \u002F\u002F直接前趋结点的next指针指向新结点\n        list->next = body;\n        \u002F\u002F新结点指向直接前趋结点\n        body->prior = list;\n        list = list->next;\n    }\n    \u002F\u002F通过以上代码，已经创建好双线链表，接下来将链表的首尾节点进行双向连接\n    list->next = head;\n    head->prior = list;\n    return head;\n}\n\u002F\u002F输出链表中的数据\nvoid display(Line* head) {\n    Line* temp = head;\n    \u002F\u002F由于是循环链表，所以当遍历指针temp指向的下一个节点是head时，证明此时已经循环至链表的最后一个节点\n    while (temp->next != head) {\n        if (temp->next == NULL) {\n            printf(\"%d\\n\", temp->data);\n        }\n        else {\n            printf(\"%d->\", temp->data);\n        }\n        temp = temp->next;\n    }\n    \u002F\u002F输出循环链表中最后一个节点的值\n    printf(\"%d\", temp->data);\n}\n\u002F\u002F释放链表中结点占用的空间\nvoid free_line(Line* head) {\n    Line* temp = NULL;\n    \u002F\u002F切断循环\n    head->prior->next = NULL;\n    \u002F\u002F从第一个结点开始，依次 free\n    temp = head;\n    while (temp) {\n        head = head->next;\n        free(temp);\n        temp = head;\n    }\n}\n\nint main()\n{\n    \u002F\u002F创建一个头指针\n    Line* head = NULL;\n    \u002F\u002F调用链表创建函数\n    head = initLine(head);\n    \u002F\u002F输出创建好的链表\n    display(head);\n    \u002F\u002F手动释放链表占用的内存\n    free_line(head);\n    return 0;\n}\n",[1168,1890,1888],{"__ignoreMap":1166},[1096,1892,1893],{},"程序输出结果如下：",[1132,1895,1896],{},[1096,1897,1898],{},"1->2->3",{"title":1166,"searchDepth":1900,"depth":1900,"links":1901},4,[1902,1908,1914,1918,1924,1925],{"id":1093,"depth":1637,"text":1094,"children":1903},[1904,1905,1906,1907],{"id":1129,"depth":1662,"text":1130},{"id":1177,"depth":1662,"text":1178},{"id":1220,"depth":1662,"text":1220},{"id":1255,"depth":1662,"text":1255},{"id":1286,"depth":1637,"text":1286,"children":1909},[1910,1911,1912,1913],{"id":1301,"depth":1662,"text":1301},{"id":1382,"depth":1662,"text":1382},{"id":1446,"depth":1662,"text":1446},{"id":1464,"depth":1662,"text":1464},{"id":1487,"depth":1637,"text":1487,"children":1915},[1916,1917],{"id":1499,"depth":1662,"text":1499},{"id":1541,"depth":1662,"text":1541},{"id":1584,"depth":1637,"text":1584,"children":1919},[1920,1921,1922,1923],{"id":1601,"depth":1662,"text":1601},{"id":1696,"depth":1662,"text":1696},{"id":1788,"depth":1662,"text":1788},{"id":1803,"depth":1662,"text":1803},{"id":1818,"depth":1637,"text":1818},{"id":1847,"depth":1637,"text":1847,"children":1926},[1927],{"id":1869,"depth":1662,"text":1869},"md",false,{"uuid":1931,"slots":1932},"7961efb0-123a-11f0-990b-77d7f716039f",{},true,15,{"title":1085,"description":1166},"posts\u002F数据结构\u002F数据结构-线性表（链表）",[42,43,178],"P9N4Yk9Zes_V4VVfxMbeYHzm6EnU3HxfJDXGxgWjdmw",1790443288584]