![数据结构(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=1739465182-PTxQlICSkdBOhLyDDQYokaEKp7Kh8fmY-0-f0b43d7188a0f78afb47c10ed47242f8)
![](https://epubservercos.yuewen.com/2EFA35/23083815801896206/epubprivate/OEBPS/Images/43_01.jpg?sign=1739465182-9JaEIiduRbF10tQaRmK7RlKbTDjGI8K0-0-fed63d95eba52775eb779645794251cd)
测试程序如下:
![](https://epubservercos.yuewen.com/2EFA35/23083815801896206/epubprivate/OEBPS/Images/43_02.jpg?sign=1739465182-7V3sHsZJiwHgaBW3LF0NVxCDLCrymZoc-0-e56edf996300e30bf15304bb4932cede)
![](https://epubservercos.yuewen.com/2EFA35/23083815801896206/epubprivate/OEBPS/Images/44_01.jpg?sign=1739465182-3T1t5BPC2776pTFo26L7Q1l1y5byRU8l-0-8b53c1d6e1dfd987320c7a28b4e5647e)
程序的运行结果如图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=1739465182-ZCWDto2AhPrw7ocFn6JvfcfpTgyz4vB1-0-cf3022fee5d16b52fa13d9fffbc9e7eb)
图2.18 程序运行结果
在该算法中,假设单链表A的长度为m,单链表B的长度为n,则时间主要耗费在A和B中对元素的查找上,算法的时间复杂度为O(m×n)。
上面的算法是通过单链表的基本运算实现的,也可以不用单链表的基本运算实现该算法。
![](https://epubservercos.yuewen.com/2EFA35/23083815801896206/epubprivate/OEBPS/Images/44_03.jpg?sign=1739465182-D1hI8986ZounVbjIBXxYDyPT23bAkA8L-0-8a442c44bf6bc4d1cf899d7c45adc38e)
![](https://epubservercos.yuewen.com/2EFA35/23083815801896206/epubprivate/OEBPS/Images/45_01.jpg?sign=1739465182-yzecjnLQ9J2o6DbDdI1umxCQu19KF6xh-0-db303abbe3385e3da141adda44644df9)
上面算法中,在单链表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=1739465182-S3h5HzDP1VeOUk8k6CtM8uO6ozhrgg6S-0-015de6a79a82e9eab0355f5e0b7a44de)
图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=1739465182-97WqhIJIZ0UI3QodGrjEd9259hx7TvpQ-0-393b23b72dd64c4831032ca92b10b7b8)
图2.20 将A中要删除的结点与链表断开
然后,p指向链表A中下一个要比较的结点,最后释放r指向的结点。如图2.21所示。
![](https://epubservercos.yuewen.com/2EFA35/23083815801896206/epubprivate/OEBPS/Images/45_04.jpg?sign=1739465182-UgOcZ5XI7l4iKLFOcmhpWp9FJ2KpX18n-0-ba235f0b475e98290c783af58ba4a5d0)
图2.21 p指向下一个要比较的结点,同时释放r指向的结点
算法DelElem2的时间复杂度也是O(m×n)。
说明:在算法DelElem2的实现过程中,隐藏了查找元素结点与删除元素结点的实现细节,而在算法DelElem2中,将整个查找过程和删除过程展现得淋漓尽致。
【考研真题】假设一个带有表头结点的单链表,结点结构如下。
![](https://epubservercos.yuewen.com/2EFA35/23083815801896206/epubprivate/OEBPS/Images/46_01.jpg?sign=1739465182-2l5wkvFlrPjOdTzWmzjh26cAeLc3RTED-0-de706ce2ebe7866f650c96662eb1c724)
假设该链表只给出了头指针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=1739465182-FtMa7DWwzv5B43ucUkODMNKF8HeX1tMy-0-d091973437137d395ea7fae81be7ce7b)
![](https://epubservercos.yuewen.com/2EFA35/23083815801896206/epubprivate/OEBPS/Images/47_01.jpg?sign=1739465182-NMUgFugDGECO22IyS4qE9YPtRK8kBtGd-0-8dc1bc09ec89baacd6d83c8853155302)