在此基础上来看几道关于单链表的题目
1.判断链表是否成环
先看这样一个图
两条平行线
如果让A和B分别从一条线的起点出发,最终必然不会相遇
再看另一种情况
这时如果A和B都从起点O出发,A的速度为v,B的速度为2v,最终两人一定会相遇,这其实就对应了在单链表中出现环的情况.
也就是说为了判断链表中是否形成环,我们需要两个指针一开始都指向头(plist->_head),然后一个指针一次走一步,一个指针一次走两步,接下来只需要判断两个指针是否会相遇即可.
完整代码如下:
//判断链表是否有环
int SListHasCycle(SList* plist){
assert(plist);
SListNode* pfast = plist->_head;
SListNode* pslow = plist->_head;
while (pfast && pslow && pfast->_next){
pfast = pfast->_next->_next;
pslow = pslow->_next;
if (pslow == pfast){
return 1;
}
}
return 0;
}
相应的获取入环结点只需对上面代码做一些简单修改即可
//获取链表入环结点
SListNode* SListHasCycle(SList* plist){
assert(plist);
SListNode* pfast = plist->_head;
SListNode* pslow = plist->_head;
while (pfast && pslow && pfast->_next){
pfast = pfast->_next->_next;
pslow = pslow->_next;
if (pslow == pfast){
return pslow;
}
}
return NULL;
}
2.逆置单链表
三种方法
//单链表的逆置
void SListReverse(SList* plist){
assert(plist);
#if 0
//创建一个新的链表,不断进行头插操作
SList* reve = (SList*)malloc(sizeof(SList));
SListInit(reve);
SListNode* cur;
for (cur = plist->_head; cur; cur = cur->_next){
SListPopFront(reve, cur->_data);
}
SListDestroy(reve);
plist->_head = reve->_head;
#elif 0
SListNode* tmp = plist->_head->_next;
SListNode* cur = plist->_head;
while (tmp){
cur->_next = tmp->_next;
tmp->_next = plist->_head;
plist->_head = tmp;
tmp = cur->_next;
}
#else
SListNode* tmp = plist->_head->_next;
SListNode* cur = plist->_head;
cur->_next = NULL; //断链,将头结点和它的next断开
while (tmp){
plist->_head = tmp; //换新头
tmp = tmp->_next; //记录下次循环时tmp的位置
plist->_head->_next = cur; //断链并与旧头形成新链
cur = plist->_head; //记录下次循环时cur位置
}
#endif
}