![算法零基础一本通(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=1738832474-B0UUbmBienHi9zoX8jt7JoxFZ9V878lT-0-10112c7f1ab4953afa243ddc7907a501)
Node类别有2个属性,其中data是存储节点数据,next是存储指标,此指标未来可指向下一个节点,在尚未设定前我们可以使用None。
程序实例ch3_1.py:建立一个含3个节点的链表,然后打印此链表。
![](https://epubservercos.yuewen.com/6BDBC6/23721658309542706/epubprivate/OEBPS/Images/Figure-P44_51163.jpg?sign=1738832474-Hg3jsKl01c2M5AdsyqpHp4u4ibgrGac9-0-ec7e930c578e1d93d00730aee706fee6)
执行结果
![](https://epubservercos.yuewen.com/6BDBC6/23721658309542706/epubprivate/OEBPS/Images/Figure-P45_47825.jpg?sign=1738832474-KniPtfVOS19kOsFBI2LdgOBSzIlvyO34-0-5d7eb4ea31f5e75d7ee70c2d9b82ee78)
上述执行第8~10行后,可以在内存内建立下列3个节点。
![](https://epubservercos.yuewen.com/6BDBC6/23721658309542706/epubprivate/OEBPS/Images/Figure-P45_47826.jpg?sign=1738832474-TZs8Dvr7lLBPruuQOsSdd8mRkXnUfPHr-0-65ef17c54007c39af022b976e5532504)
执行第11行后链表节点内容如下:
![](https://epubservercos.yuewen.com/6BDBC6/23721658309542706/epubprivate/OEBPS/Images/Figure-P45_47827.jpg?sign=1738832474-xqHx71ogpu8aud1ygLnjsaOBPGwDGFGm-0-ae25f628ac517044fd5b3f41fe54a502)
执行第12行后链表节点内容如下:
![](https://epubservercos.yuewen.com/6BDBC6/23721658309542706/epubprivate/OEBPS/Images/Figure-P45_47828.jpg?sign=1738832474-415JGHgqDHZhxd8qEttD9aXgVUnQCdCj-0-8dadf6b12f182df8e65a87272d62013b)
执行第13行后会多一个指标ptr:
![](https://epubservercos.yuewen.com/6BDBC6/23721658309542706/epubprivate/OEBPS/Images/Figure-P45_47829.jpg?sign=1738832474-WqgERcCUZKWoDm34csOx4ywpc4D8e0ee-0-b20190d22778178f5f12ec1a5c55dd54)
第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=1738832474-LDVZdM0FMOZKdw30D9oHS4T5svzoNfe7-0-bd03356676a654d7272668723ab34f76)
执行结果 与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=1738832474-SHTC9FZtMKawObO5ff3vHUq3HkOGZtYN-0-b3290b51ef1738dfc968b320e7a855ca)
执行结果
![](https://epubservercos.yuewen.com/6BDBC6/23721658309542706/epubprivate/OEBPS/Images/Figure-P47_47833.jpg?sign=1738832474-Kn3nu3YW72OsDbOR7xItyu5O8O2CHcaQ-0-cb2b2bf88f69a09ba3a3b1c7488246e0)
上述程序第34行是调用begining( )方法,同时传递新节点值100,当执行第22行后,链表节点内容如下:
![](https://epubservercos.yuewen.com/6BDBC6/23721658309542706/epubprivate/OEBPS/Images/Figure-P47_47834.jpg?sign=1738832474-QkPbyeQpRh9Ytl8x1SwXTlRtYfL6Pp2H-0-a0d576e5d99bbcfc2a4b67ed7a90ff67)
当执行第23行后,链表节点内容如下:
![](https://epubservercos.yuewen.com/6BDBC6/23721658309542706/epubprivate/OEBPS/Images/Figure-P47_47835.jpg?sign=1738832474-eu0hS58s7DvkOps9UcYPvDwxkIRq6RF9-0-f292142d302ce1f1273b72569f6e1e6f)
当执行第24行后,链表节点内容如下:
![](https://epubservercos.yuewen.com/6BDBC6/23721658309542706/epubprivate/OEBPS/Images/Figure-P48_47836.jpg?sign=1738832474-vFEkRDUhZkEJQZzGegFS4odMkJnoT4tu-0-532e856a54566f044b08c05fc77451b3)
3-8-4 在链表末端插入新的节点
程序实例ch3_4.py:在链表的末端插入新的节点。
![](https://epubservercos.yuewen.com/6BDBC6/23721658309542706/epubprivate/OEBPS/Images/Figure-P48_51170.jpg?sign=1738832474-95Y9urGzivf9w7dZdCepg1KrCjM3SJSy-0-e0dfde9181e3ac016ccecac99b0f90fe)
执行结果
![](https://epubservercos.yuewen.com/6BDBC6/23721658309542706/epubprivate/OEBPS/Images/Figure-P49_47838.jpg?sign=1738832474-zOhEenPuPy6C4CI6tU7uwgimAkSMkDOK-0-8e6046ae900f138356b2628cf973d300)
对于在链表末端插入节点,程序在第20~29行使用了ending( )方法,当执行第26行后,链表节点内容如下:
![](https://epubservercos.yuewen.com/6BDBC6/23721658309542706/epubprivate/OEBPS/Images/Figure-P49_47839.jpg?sign=1738832474-UOCGXO3JnOOj5Jys2fmbjaDYx6sspwbh-0-071715405006989b883cad6f34d56954)
当执行第27~28行后,链表节点内容如下:
![](https://epubservercos.yuewen.com/6BDBC6/23721658309542706/epubprivate/OEBPS/Images/Figure-P49_47840.jpg?sign=1738832474-Vp6webVPDkpuVbtAcQnErpXbLuE7X5LN-0-f8565fe6798697bb5078e1ac42e40b75)
当执行第29行后,链表节点内容如下:
![](https://epubservercos.yuewen.com/6BDBC6/23721658309542706/epubprivate/OEBPS/Images/Figure-P49_47841.jpg?sign=1738832474-X1DlcYQNyofNoF0I2cG1TOIpSGhpjnFw-0-69e08cc6ea2ee02f4ba514abd0dbb461)
3-8-5 在链表中间插入新的节点
程序实例ch3_5.py:在链表n2节点的后面插入新的节点。
![](https://epubservercos.yuewen.com/6BDBC6/23721658309542706/epubprivate/OEBPS/Images/Figure-P49_51172.jpg?sign=1738832474-qoXbhepa1BfKYWAz4tUV1IkmoxbJqN9z-0-e467c66e064dfc3ad40b96ac133124ad)
执行结果
![](https://epubservercos.yuewen.com/6BDBC6/23721658309542706/epubprivate/OEBPS/Images/Figure-P50_47844.jpg?sign=1738832474-ROeyUFJDh4eaoWoWf94sB4JEI7UlQIGS-0-963633d6ebb3fbae9446085a4f5f5afc)
对于在链表中间插入节点,程序在第20~28行使用了between( )方法,调用这个方法需要使用2个参数,第1个参数pre_node是指出要将新数据插入哪一个节点,第2个参数是新节点的值,当执行第26行后,链表节点内容如下:
![](https://epubservercos.yuewen.com/6BDBC6/23721658309542706/epubprivate/OEBPS/Images/Figure-P50_47845.jpg?sign=1738832474-Ya8C4Cj5p2cliAkoBqAIg3GYzyHsWxYy-0-e2b66853fd078469d07cc42ab9fcbba4)
当执行第27行后,链表节点内容如下:
![](https://epubservercos.yuewen.com/6BDBC6/23721658309542706/epubprivate/OEBPS/Images/Figure-P50_47846.jpg?sign=1738832474-dgv5KgiCx5vuqOqqneXGWCijF05dAET6-0-700a13d2a0f6c27db8ef7cbea1c323de)
当执行第28行后,链表节点内容如下:
![](https://epubservercos.yuewen.com/6BDBC6/23721658309542706/epubprivate/OEBPS/Images/Figure-P51_47847.jpg?sign=1738832474-OioMTEpS4mRIepqU5o9M92iXkVzcIm9Q-0-e47d7bc9c5101dc745fd4015df92cd69)
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=1738832474-lPbFuy7FpCTGjlUIHtoIEDu0Vo4CjVwJ-0-8a53830c411bdf53654e9650d1dbfdb4)
执行结果
![](https://epubservercos.yuewen.com/6BDBC6/23721658309542706/epubprivate/OEBPS/Images/Figure-P52_47850.jpg?sign=1738832474-JOICVCspxJ68AiuTVorhKaw5CyzwgwfI-0-21ce703e0d55662f0ac559d4ff541924)
上述程序第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=1738832474-j0Disgn4GnGXcwiHTEppu4a0G3YkiLKz-0-ae9eac4d8f3c847a33cb231a95d631e9)
执行结果
![](https://epubservercos.yuewen.com/6BDBC6/23721658309542706/epubprivate/OEBPS/Images/Figure-P53_47852.jpg?sign=1738832474-3dRqoVfm4GYafTgZl4oHe6YGCqSmxAuR-0-4f6083b651266c862587272fd02819c3)
上述执行第12行后链表节点如下所示:
![](https://epubservercos.yuewen.com/6BDBC6/23721658309542706/epubprivate/OEBPS/Images/Figure-P53_47853.jpg?sign=1738832474-36IiwijKcd8LmZ182pnDOh2QZ0ezjyIz-0-461e0781df6b8ea5c408ad71eeaf3652)
上述执行第13行后链表节点如下所示:
![](https://epubservercos.yuewen.com/6BDBC6/23721658309542706/epubprivate/OEBPS/Images/Figure-P53_47854.jpg?sign=1738832474-RYLModCCJrsOlhUzyargcn05OUEet6oj-0-2d02b69b9159581fd00c9dc561010791)
这样就完成了循环链表。
3-8-8 双向链表
如果要建立双向链表,每个节点必须有向前指标和向后指标,可以使用下列方式定义此节点。
![](https://epubservercos.yuewen.com/6BDBC6/23721658309542706/epubprivate/OEBPS/Images/Figure-P53_47855.jpg?sign=1738832474-88oul76R643sKaR3KfsnPGGZRwhP1M7L-0-bbdfdd5ff4e734a774ca08014530c0e1)
程序实例ch3_8.py:建立双向链表,在建立节点过程中,每次均从头部打印一次双向链表,最后从尾部打印一次双向链表。
![](https://epubservercos.yuewen.com/6BDBC6/23721658309542706/epubprivate/OEBPS/Images/Figure-P53_51183.jpg?sign=1738832474-Jaz9dS9F4mfNsMU72Z90kWLnFcvpOgtm-0-6fe4a011b7c7264f1c4984dc884f6e7a)
执行结果
![](https://epubservercos.yuewen.com/6BDBC6/23721658309542706/epubprivate/OEBPS/Images/Figure-P54_47858.jpg?sign=1738832474-e1yBx5eZw7VJrXta7huhaiV6SgGpJgFq-0-819004654e03064370f1bc5013b57011)
这个程序第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=1738832474-QWFKhfjIvmE0vlJvOl9jlNmL36cKpwxY-0-ca193a1327d7472149c4b8622e7bd439)
当执行完第20行,链表节点内容如下:
![](https://epubservercos.yuewen.com/6BDBC6/23721658309542706/epubprivate/OEBPS/Images/Figure-P55_47860.jpg?sign=1738832474-jgbL4BtlXj81Ap3U9ZqSECeIKP6dT6Ri-0-ebbaddb9a74e966220b0b6e247e50948)
当执行完第21行,链表节点内容如下:
![](https://epubservercos.yuewen.com/6BDBC6/23721658309542706/epubprivate/OEBPS/Images/Figure-P55_47861.jpg?sign=1738832474-eEHAMdP0lECgNP9RTn2Kld6qwRed2f2Z-0-d3173dbae40de8050a7edd87662298e1)
当执行完第22行,链表节点内容如下:
![](https://epubservercos.yuewen.com/6BDBC6/23721658309542706/epubprivate/OEBPS/Images/Figure-P55_47862.jpg?sign=1738832474-2tGcuLhVkK4dQq4up38RQ729BMjFND0u-0-82b971f3efbe11d965122092fb65183d)
上述就是建立双向链表的第一个节点过程。程序第24~26行是建立双向链表第2个(含)以后的节点过程,当执行完第24行,链表节点内容如下:
![](https://epubservercos.yuewen.com/6BDBC6/23721658309542706/epubprivate/OEBPS/Images/Figure-P55_47863.jpg?sign=1738832474-QNAPwzLB30zaXm0fot6smEPikmNqOBgo-0-480ed9cecdac01ddbe4896ca873b8c89)
当执行完第25行,链表节点内容如下:
![](https://epubservercos.yuewen.com/6BDBC6/23721658309542706/epubprivate/OEBPS/Images/Figure-P55_47864.jpg?sign=1738832474-Wzrscklvyn8Zl9oez6ypFGWt9D5B1lyV-0-31bf3979420c2a773ee3b8149ff13eee)
当执行完第26行,链表节点内容如下:
![](https://epubservercos.yuewen.com/6BDBC6/23721658309542706/epubprivate/OEBPS/Images/Figure-P56_47865.jpg?sign=1738832474-y739jSNjbYMgKbLupZejQSi8hGL2jMMy-0-7f685eae0830cb9940bef5e124b3c302)
程序第29~34行的print_list_from_head( )是从双向链表前端打印到末端,程序第36~41行的print_list_from_tail( )是从双向链表末端打印到前端。