![数据结构(C语言实现)](https://wfqqreader-1252317822.image.myqcloud.com/cover/699/43806699/b_43806699.jpg)
2.3.3 单链表应用举例
【例2.3】 利用单链表的基本运算,求A-B。即若单链表B中的元素出现在单链表A中,则从A中删除该元素。
【分析】对于单链表A中的每个元素e,在单链表B中进行查找,如果在B中存在与A中相同的元素,则将元素从A中删除。
算法描述如下:
![](https://epubservercos.yuewen.com/2EFA35/23083815801896206/epubprivate/OEBPS/Images/42_03.jpg?sign=1739532982-kFj8QZhEpQoCHJTDVnuQ6LIfsm9q3BiB-0-0277f5a9b03f010f686d9443145f1817)
![](https://epubservercos.yuewen.com/2EFA35/23083815801896206/epubprivate/OEBPS/Images/43_01.jpg?sign=1739532982-CUAXAPJgDJOxo4HX1uYwWQEEAx37NQUr-0-61a120fe5d401ac54211ebfc55fcb70d)
测试程序如下:
![](https://epubservercos.yuewen.com/2EFA35/23083815801896206/epubprivate/OEBPS/Images/43_02.jpg?sign=1739532982-680KTk6wkbjCyKXs6w8GK7XdiGS52f8U-0-65812f7611c8a119c51d641ae67b0a05)
![](https://epubservercos.yuewen.com/2EFA35/23083815801896206/epubprivate/OEBPS/Images/44_01.jpg?sign=1739532982-I2F81QF8F8JwMkbtGCb0JPS3Xw8p4uUL-0-ae7dd1020e1a646da30829f2e5d804b4)
程序的运行结果如图2.18所示。
在具体实现算法A-B时,利用p=Get(B,i)依次取出单链表B中的元素,然后通过pos=LocatePos(A,p->data)在链表A中查找与该值相等的元素,并调用函数DeleteList(A,pos,&e)将A中对应的结点删除。
![](https://epubservercos.yuewen.com/2EFA35/23083815801896206/epubprivate/OEBPS/Images/44_02.jpg?sign=1739532982-K8Lu01cVG7H9PK2UmBe57GXdSJaAIEaF-0-a143536785825c8f870a190050a157ce)
图2.18 程序运行结果
在该算法中,假设单链表A的长度为m,单链表B的长度为n,则时间主要耗费在A和B中对元素的查找上,算法的时间复杂度为O(m×n)。
上面的算法是通过单链表的基本运算实现的,也可以不用单链表的基本运算实现该算法。
![](https://epubservercos.yuewen.com/2EFA35/23083815801896206/epubprivate/OEBPS/Images/44_03.jpg?sign=1739532982-SYaxpjuatVM6Z8M1F4G43x4OGghjoZXJ-0-24d76cc31bbb986933dbfd883b532992)
![](https://epubservercos.yuewen.com/2EFA35/23083815801896206/epubprivate/OEBPS/Images/45_01.jpg?sign=1739532982-kxZBdfLrgikFQpyslIlhvbsE39LzGl0y-0-d46c980d62afe1133e8a4b58714636e7)
上面算法中,在单链表A中,指针p指向单链表A中与单链表B中要比较的结点,pre指向p的前驱结点,在单链表B中,利用指针q指向B中的第一个结点,依次与A中p指向的结点的元素比较。如图2.19所示。
![](https://epubservercos.yuewen.com/2EFA35/23083815801896206/epubprivate/OEBPS/Images/45_02.jpg?sign=1739532982-MHu0s93IIGtRaQ01i2v9FMk6KuYQGHcd-0-4e4ab71604fefe084072a5925c3075c3)
图2.19 初始时,p指向第一个要比较的结点
如果当前A中要比较的是元素ai,指针p指向ai所在结点,在B中,如果q指向元素bj所在结点,而bj=ai,则指针q停止向前比较。在A中,利用指针r指向要删除的结点p,令pre指向p的后继结点,从而使p指向的结点与链表断开,即r=p,pre->next=p->next。如图2.20所示。
![](https://epubservercos.yuewen.com/2EFA35/23083815801896206/epubprivate/OEBPS/Images/45_03.jpg?sign=1739532982-QezKqYoI2C6FvgMJcfWsJw9HinuaETQb-0-eba21e7f5e5f79c281ae98042b9c93d4)
图2.20 将A中要删除的结点与链表断开
然后,p指向链表A中下一个要比较的结点,最后释放r指向的结点。如图2.21所示。
![](https://epubservercos.yuewen.com/2EFA35/23083815801896206/epubprivate/OEBPS/Images/45_04.jpg?sign=1739532982-65m46Z9LzvkmBPsY27IsnZxT6aD11qt9-0-349599782c8392a8aa3263165004a6dc)
图2.21 p指向下一个要比较的结点,同时释放r指向的结点
算法DelElem2的时间复杂度也是O(m×n)。
说明:在算法DelElem2的实现过程中,隐藏了查找元素结点与删除元素结点的实现细节,而在算法DelElem2中,将整个查找过程和删除过程展现得淋漓尽致。
【考研真题】假设一个带有表头结点的单链表,结点结构如下。
![](https://epubservercos.yuewen.com/2EFA35/23083815801896206/epubprivate/OEBPS/Images/46_01.jpg?sign=1739532982-MF3mDRgZw8mlI4k34OERS8OB7yacj7ox-0-d6825f3e330a75171f2b70f5d3d3f13a)
假设该链表只给出了头指针list,在不改变链表的前提下,请设计一个尽可能高效的算法,查找链表中倒数第k个位置上的结点(k为正整数)。若查找成功,算法输出该结点数据域的值,并返回1;否则返回0。要求如下。
(1)描述算法的基本设计思想。
(2)描述算法的详细实现步骤。
(3)根据设计思想和实现步骤,采用程序设计语言描述算法。
【分析】这是一道考研试题,主要考察对链表的掌握程度,这个题目比较灵活,利用一般的思维方式不容易实现。
(1)算法的基本思想:定义两个指针p和q,初始时均指向头结点的下一个结点。p指针沿着链表移动,当p指针移动到第k个结点时,q指针与p指针同步移动;当p指针移动到链表表尾结点时,q指针所指向的结点即为倒数第k个结点。
(2)算法的详细步骤如下。
①令count=0,p和q指向链表的第一个结点。
②若p为空,则转向⑤执行。
③若count等于k,则q指向下一个结点;否则令count++。
④令p指向下一个结点,转向②执行。
⑤若count等于k,则查找成功,输出结点的数据域的值,并返回1;否则,查找失败,返回0。
(3)算法实现代码如下。
![](https://epubservercos.yuewen.com/2EFA35/23083815801896206/epubprivate/OEBPS/Images/46_02.jpg?sign=1739532982-UpupRPFhd15E0A69AcY5Rqqkx9kg907k-0-33ff44f5e99a3ef063effc54759e9427)
![](https://epubservercos.yuewen.com/2EFA35/23083815801896206/epubprivate/OEBPS/Images/47_01.jpg?sign=1739532982-9sQ1cUL1ymFRhrqlLkMjReKIUgpDSPJ5-0-7626d6b4fe5e042ed0cb4e1ad9d32a61)