![算法零基础一本通(Python版)](https://wfqqreader-1252317822.image.myqcloud.com/cover/51/44510051/b_44510051.jpg)
3-8 与链表有关的Python程序
这一节笔者将教导读者使用Python建立链表指标及遍历链表。
3-8-1 建立链表
想要建立链表,首先要建立此链表的节点,我们可以使用下列Node类别建立此节点。
![](https://epubservercos.yuewen.com/6BDBC6/23721658309542706/epubprivate/OEBPS/Images/Figure-P44_61163.jpg?sign=1739481579-m3HMdOXCtVc3AqKDgTIFFbN29HEBcH3l-0-851384bbfca0e85e72920e2aa4d782ee)
Node类别有2个属性,其中data是存储节点数据,next是存储指标,此指标未来可指向下一个节点,在尚未设定前我们可以使用None。
程序实例ch3_1.py:建立一个含3个节点的链表,然后打印此链表。
![](https://epubservercos.yuewen.com/6BDBC6/23721658309542706/epubprivate/OEBPS/Images/Figure-P44_51163.jpg?sign=1739481579-mJlJUuApfysJTEEisbRC0KsKGStz8M6X-0-0b689d203bf690415ef311f1340b089d)
执行结果
![](https://epubservercos.yuewen.com/6BDBC6/23721658309542706/epubprivate/OEBPS/Images/Figure-P45_47825.jpg?sign=1739481579-nw7GY5AmlzpriO1s2aEnYIxXtKj8jqMA-0-2506452d02af6b8019f85987c7eb99ab)
上述执行第8~10行后,可以在内存内建立下列3个节点。
![](https://epubservercos.yuewen.com/6BDBC6/23721658309542706/epubprivate/OEBPS/Images/Figure-P45_47826.jpg?sign=1739481579-BKSwgLZlO51DIHTN0nOa9piHMSbjQ1hk-0-3ee64515159d6e9ae85d9a4934cfbc4f)
执行第11行后链表节点内容如下:
![](https://epubservercos.yuewen.com/6BDBC6/23721658309542706/epubprivate/OEBPS/Images/Figure-P45_47827.jpg?sign=1739481579-yiH7930BnbahrcPrwNC6SiWI3r0pRO6S-0-eee2452736c8661505b6ccebaca4cba6)
执行第12行后链表节点内容如下:
![](https://epubservercos.yuewen.com/6BDBC6/23721658309542706/epubprivate/OEBPS/Images/Figure-P45_47828.jpg?sign=1739481579-6E2xaCPC2IFf4fVxaDcYf1eW9UBnlBUz-0-e423868b5b2933c89c6ff15949a093e1)
执行第13行后会多一个指标ptr:
![](https://epubservercos.yuewen.com/6BDBC6/23721658309542706/epubprivate/OEBPS/Images/Figure-P45_47829.jpg?sign=1739481579-OTLZic8auTyuQlPnvVkEaOQc3MgdJyic-0-5778d4137fb2a4dba965d2f2923aa3ca)
第14~16行可以打印此链表,得到5、15、25。
3-8-2 建立链表类别和遍历此链表
其实前一节笔者已经用实例讲解了建立链表的方式,也说明了遍历链表,这一节主要讲解建立一个链表Linked_list类别,在这个类别内我们使用__init__( )设计链表的第一个节点,同时使用print_list( )打印链表。
程序实例ch3_2.py:以建立Linked_list类别方式重新设计ch3_1.py。
![](https://epubservercos.yuewen.com/6BDBC6/23721658309542706/epubprivate/OEBPS/Images/Figure-P46_51166.jpg?sign=1739481579-wdywxhFCI86HeHVKFRL5Ize7KkfzzPyQ-0-8fd0837673385dd144f6d36971849b9b)
执行结果 与ch3_1.py相同。
3-8-3 在链表第一个节点前插入一个新的节点
在链表的应用中,常常需要插入新的节点数据,这一节重点是将新节点插入链表的第一个节点之前,也就是插在链表开头的位置。
程序实例ch3_3.py:扩充ch3_2.py,新建数据是100的节点,同时将100插入链表开头的位置。
![](https://epubservercos.yuewen.com/6BDBC6/23721658309542706/epubprivate/OEBPS/Images/Figure-P46_51167.jpg?sign=1739481579-NnPyV72VM1FcnOMxKX9yVMqENlqNJuPP-0-c3e34dcb4af6dd5dc69319f1280a29c8)
执行结果
![](https://epubservercos.yuewen.com/6BDBC6/23721658309542706/epubprivate/OEBPS/Images/Figure-P47_47833.jpg?sign=1739481579-PPrLVCi5DXgNjvTMQx2ELqksCFSEL2HZ-0-2f1dd52c3e900b485352509bf534d2ed)
上述程序第34行是调用begining( )方法,同时传递新节点值100,当执行第22行后,链表节点内容如下:
![](https://epubservercos.yuewen.com/6BDBC6/23721658309542706/epubprivate/OEBPS/Images/Figure-P47_47834.jpg?sign=1739481579-GRyPewwXrtEGDrt0DFkMtVQsc9YCge7V-0-0a2f67214fd7ebf87c3907a198e0839e)
当执行第23行后,链表节点内容如下:
![](https://epubservercos.yuewen.com/6BDBC6/23721658309542706/epubprivate/OEBPS/Images/Figure-P47_47835.jpg?sign=1739481579-HKOEyprtI1EBE9Zn2KExcQUaQztxLD89-0-ff3e8a19e3d455216f62f10e7eb1de28)
当执行第24行后,链表节点内容如下:
![](https://epubservercos.yuewen.com/6BDBC6/23721658309542706/epubprivate/OEBPS/Images/Figure-P48_47836.jpg?sign=1739481579-nF5MAvMi2ZTVeBAcINWIFC47CtdaifeG-0-bbe4fe10f45bed848f0642e342857534)
3-8-4 在链表末端插入新的节点
程序实例ch3_4.py:在链表的末端插入新的节点。
![](https://epubservercos.yuewen.com/6BDBC6/23721658309542706/epubprivate/OEBPS/Images/Figure-P48_51170.jpg?sign=1739481579-ndUBkTsmQq5xS3sXSx7FhowFNLckTmfX-0-426ac6135006ffc57533f027da517d54)
执行结果
![](https://epubservercos.yuewen.com/6BDBC6/23721658309542706/epubprivate/OEBPS/Images/Figure-P49_47838.jpg?sign=1739481579-E996e7XuAZ0tmM0AJdHeqYG0fpQbdvqg-0-9c4855a43935860b2c1eb4afe1327f10)
对于在链表末端插入节点,程序在第20~29行使用了ending( )方法,当执行第26行后,链表节点内容如下:
![](https://epubservercos.yuewen.com/6BDBC6/23721658309542706/epubprivate/OEBPS/Images/Figure-P49_47839.jpg?sign=1739481579-dVT5XFo22GlueBlf6rgSRgiLkYZvVi7I-0-5e03d397d6d5af06c1a75f30f3193c9c)
当执行第27~28行后,链表节点内容如下:
![](https://epubservercos.yuewen.com/6BDBC6/23721658309542706/epubprivate/OEBPS/Images/Figure-P49_47840.jpg?sign=1739481579-ns6TleJORWDON4dvEjQLRduClZm80l4q-0-101395f882d1252ced98151d9f591973)
当执行第29行后,链表节点内容如下:
![](https://epubservercos.yuewen.com/6BDBC6/23721658309542706/epubprivate/OEBPS/Images/Figure-P49_47841.jpg?sign=1739481579-voVkQeezJCKsHD9eb9Y3LXdpPzac0YKD-0-295dce9e9a27a43d170bae8aa6ba7729)
3-8-5 在链表中间插入新的节点
程序实例ch3_5.py:在链表n2节点的后面插入新的节点。
![](https://epubservercos.yuewen.com/6BDBC6/23721658309542706/epubprivate/OEBPS/Images/Figure-P49_51172.jpg?sign=1739481579-kFzptNx2CKjZ10uRTa4zS6q65EipJL5x-0-18b3811bc57058dd7448b08fc7433c09)
执行结果
![](https://epubservercos.yuewen.com/6BDBC6/23721658309542706/epubprivate/OEBPS/Images/Figure-P50_47844.jpg?sign=1739481579-1403enofnBA6yW55MGGYjRdDPDsdRKcb-0-faa13a53fed6a045979c468cbb4e3c39)
对于在链表中间插入节点,程序在第20~28行使用了between( )方法,调用这个方法需要使用2个参数,第1个参数pre_node是指出要将新数据插入哪一个节点,第2个参数是新节点的值,当执行第26行后,链表节点内容如下:
![](https://epubservercos.yuewen.com/6BDBC6/23721658309542706/epubprivate/OEBPS/Images/Figure-P50_47845.jpg?sign=1739481579-1Pb6lU5VGkwWlWwHBtLhAYb5XTJHZfmo-0-6d6b8bd9974ada1ebb8d878bc04f449a)
当执行第27行后,链表节点内容如下:
![](https://epubservercos.yuewen.com/6BDBC6/23721658309542706/epubprivate/OEBPS/Images/Figure-P50_47846.jpg?sign=1739481579-5Sl0RrhxqLWaC9F5dm94XU0Q4QiE5B5z-0-7c1fcc7d65161ba9904f859ded83dddd)
当执行第28行后,链表节点内容如下:
![](https://epubservercos.yuewen.com/6BDBC6/23721658309542706/epubprivate/OEBPS/Images/Figure-P51_47847.jpg?sign=1739481579-EJYeYiibYeaRmLduYss4vncMY0X8Pth5-0-f7fadf28d80a16dda4a06c7683c82253)
3-8-6 在链表中删除指定内容的节点
程序实例ch3_6.py:在链表中删除指定的节点前,先建立链表,此链表含有5、15、25这3个节点,然后删除15这个节点。
![](https://epubservercos.yuewen.com/6BDBC6/23721658309542706/epubprivate/OEBPS/Images/Figure-P51_51176.jpg?sign=1739481579-Kh4LAbY0qsID93DeMZhM88lM7KeP6Uf5-0-2de02755f64ee230895c5840845141d7)
执行结果
![](https://epubservercos.yuewen.com/6BDBC6/23721658309542706/epubprivate/OEBPS/Images/Figure-P52_47850.jpg?sign=1739481579-E0iPGAYg9GQoVfeBBoLKwxmv5RpTYxAV-0-a811bc6a43607e249af45f9617b69e4a)
上述程序第33行是建立暂时指标ptr,指向链表的第一个节点,第41~42行是建立暂时指标的前一个指标prev,未来找到删除节点时(ptr所指的节点),prev.next指向ptr.next,这样就算是删除暂时指标ptr所指的节点了,可以参考第45行。第43~44行主要是用在找不到指定节点时,可以直接返回。
3-8-7 建立循环链表
如果想要建立循环链表,只要将链表末端节点指向第1个节点即可。
程序实例ch3_7.py:建立循环链表,此列表有3个节点,打印6次。
![](https://epubservercos.yuewen.com/6BDBC6/23721658309542706/epubprivate/OEBPS/Images/Figure-P52_51179.jpg?sign=1739481579-z1bYFSC8NmdDk7vAlWBYU3onGXCWh4Uj-0-c4c6ccbaacd4695b327239657b1b3176)
执行结果
![](https://epubservercos.yuewen.com/6BDBC6/23721658309542706/epubprivate/OEBPS/Images/Figure-P53_47852.jpg?sign=1739481579-Sd1s9iyEL3uXZqSiDvtOQS1A4Xangi5z-0-0671eb0c4eac3edf2a183a5926270e29)
上述执行第12行后链表节点如下所示:
![](https://epubservercos.yuewen.com/6BDBC6/23721658309542706/epubprivate/OEBPS/Images/Figure-P53_47853.jpg?sign=1739481579-1Y8vHPv9wZJK5rNSkISe3Y1tJmFf14NF-0-e6d468361de1b388cbe5b4b124066563)
上述执行第13行后链表节点如下所示:
![](https://epubservercos.yuewen.com/6BDBC6/23721658309542706/epubprivate/OEBPS/Images/Figure-P53_47854.jpg?sign=1739481579-IhLOvuH9iWkI6af8gtlHRM4C8J0D8ZmP-0-f953d9b0c5abcd308c7ea583b6d8ded1)
这样就完成了循环链表。
3-8-8 双向链表
如果要建立双向链表,每个节点必须有向前指标和向后指标,可以使用下列方式定义此节点。
![](https://epubservercos.yuewen.com/6BDBC6/23721658309542706/epubprivate/OEBPS/Images/Figure-P53_47855.jpg?sign=1739481579-RbPXH7sw1Onm9EKb5t9Dr5dYZ3b2jdSv-0-a0713550314aa75b95b2ae44675b0027)
程序实例ch3_8.py:建立双向链表,在建立节点过程中,每次均从头部打印一次双向链表,最后从尾部打印一次双向链表。
![](https://epubservercos.yuewen.com/6BDBC6/23721658309542706/epubprivate/OEBPS/Images/Figure-P53_51183.jpg?sign=1739481579-tD0HXBSzr4gMPGpxZxmaGeT5N9GIOgc0-0-c70c237235dff1963854bb80f7f3d2d1)
执行结果
![](https://epubservercos.yuewen.com/6BDBC6/23721658309542706/epubprivate/OEBPS/Images/Figure-P54_47858.jpg?sign=1739481579-vDe4G1fpyoPRuXO8aqxXv9q5uRkMkEjB-0-156cbf355823439948513a23f6321fea)
这个程序第15~27行使用了add_double_list( )方法,将每个节点加入链表,第17行主要是确定所增加的数据是双向链表的节点,再执行18~26行。其中19~22行是增加第一个节点,当执行完第19行,链表节点内容如下:
![](https://epubservercos.yuewen.com/6BDBC6/23721658309542706/epubprivate/OEBPS/Images/Figure-P55_47859.jpg?sign=1739481579-asQ7MzOtffoIaJrP9zDSsno9ISgG7VVT-0-2c7696b52cbf0c4798e52cc7160f4283)
当执行完第20行,链表节点内容如下:
![](https://epubservercos.yuewen.com/6BDBC6/23721658309542706/epubprivate/OEBPS/Images/Figure-P55_47860.jpg?sign=1739481579-pUbSff6rnLPR6QrBjImLDE6d4z4MbMsx-0-b0eaf8ded848424fe1bbd841d2d88175)
当执行完第21行,链表节点内容如下:
![](https://epubservercos.yuewen.com/6BDBC6/23721658309542706/epubprivate/OEBPS/Images/Figure-P55_47861.jpg?sign=1739481579-j6s2S1v1UIeA2bmUOVoYF6fEAzd6t2hc-0-ecf31eee09552a698a90c9530d3d3784)
当执行完第22行,链表节点内容如下:
![](https://epubservercos.yuewen.com/6BDBC6/23721658309542706/epubprivate/OEBPS/Images/Figure-P55_47862.jpg?sign=1739481579-ve18etVOC1ld9l3Bg8GEt2FsQTP315Lx-0-8571c4a4b3408c64ab95ea6e43a83013)
上述就是建立双向链表的第一个节点过程。程序第24~26行是建立双向链表第2个(含)以后的节点过程,当执行完第24行,链表节点内容如下:
![](https://epubservercos.yuewen.com/6BDBC6/23721658309542706/epubprivate/OEBPS/Images/Figure-P55_47863.jpg?sign=1739481579-Zs18SpT24iiYO9Rygn6xVADcyYNvM8Gi-0-f32fb4350b8d3742e6a1787820327aeb)
当执行完第25行,链表节点内容如下:
![](https://epubservercos.yuewen.com/6BDBC6/23721658309542706/epubprivate/OEBPS/Images/Figure-P55_47864.jpg?sign=1739481579-AYV1VfSCy0mWZpF1H4mMRmJiAzSTOEv9-0-8762181b5127df6f2e13599423d4486e)
当执行完第26行,链表节点内容如下:
![](https://epubservercos.yuewen.com/6BDBC6/23721658309542706/epubprivate/OEBPS/Images/Figure-P56_47865.jpg?sign=1739481579-ou0IZa95ToK1qSn0wU0kcvVo1YqcB4um-0-54106efcb4574e30890279451b66a600)
程序第29~34行的print_list_from_head( )是从双向链表前端打印到末端,程序第36~41行的print_list_from_tail( )是从双向链表末端打印到前端。