- 删除链表中等于给定值 val 的所有节点。
#include <stdio.h>
ListNode* removeElements(ListNode* head, int val)
{
ListNode *prev =NULL;
ListNode *cur =head;
ListNode *tail =NULL;
while (cur)
{
if (cur->data == val)
{
tail = cur->next;
free (cur);
cur = tail;
if (prev == NULL)
{
head = tail;
}
else
{
prev->next = tail;
}
}
else
{
prev = cur;
cur = cur->next;//这里不能把tail赋给cur,因为当不满足cur->data==val条件时,tail
//的初始值为NULL。
}
return head;//遍历后的结果要返回一个链表
}
-
反转一个单链表。
输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL -
用三个指针依次挪动来改变位置
#include <stdio.h>
ListNode* reverseList(ListNode* head)
{
ListNode *prev = NULL;
ListNode *cur = head;
ListNode *tail = NULL;
while (cur)
{
tail = cur->next;
cur->next = prev;
prev = cur;//注意
cur = tail;
}
return prev;//因为prev最后作为新产生的链表的头结点
}
- 新设置一个结点,把它作为每次操作后新的头结点
#include <stdio.h>
ListNode* reverseList(ListNode* head)
{
ListNode *newnode = (ListNode*)malloc(sizeof(ListNode));
newnode =NULL;
ListNode *cur =head;
ListNode *tail =NULL;
while (cur)
{
tail =cur->next;
cur->next =newnode;
newnode =cur;
cur =tail;
}
return newnode;
}
-
给定一个带有头结点 head 的非空单链表,返回链表的中间结点。
如果有两个中间结点,则返回第二个中间结点。 输入:[1,2,3,4,5,6] 输出:此列表中的结点 4 (序列化形式:[4,5,6]) 由于该列表有两个中间结点,值分别为 3 和 4,我们返回第二个结点。
-
采用快慢指针的思想:
快指针走一步,慢指针走两步,当快指针走到尾部时,慢指针刚好走到中间位置。
#include <stdio.h>
ListNode* middleNode(ListNode* head)
{
ListNode *fast =head;
ListNode *slow =head;
while (fast && fast->next)
{
fast =fast->next->next;
slow =slow->next;
}
return slow;
}
- 先算出链表的结点个数,然后找中间结点,
#include <stdio.h>
ListNode* middleNode(ListNode* head)
{
ListNode *cur =head;
int count =0;
while (cur)
{
cur =cur->next;
}
int mid =cur/2;
cur =head;//第一次遍历后,cur的值已经改变了,需要重新让它开始从head遍历。
while (mid--)
{
cur =cur->next;
}
return cur;
}
- 编写一个程序,找到两个单链表相交的起始节点。
#include <stdio.h>
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB)
{
int lenA =0;
int lenB =0;
ListNode *curA =headA;
ListNode *curB =headB;
while (headA)
{
lenA++;
headA =headA->next;
}
while (headB)
{
lenB++;
headB =headB->next;
}
if (headA !=headB)//如果两条链表的最后一个结点都不相交,那这两条链表肯定不相交。
{
return NULL;
}
int gap = abs(lenA-lenB);
ListNode *Listlong =curA;
ListNode *Listshort =curB;
if (lenA < lenB)
{
Listlong =curB;
Listshort =curA;
}
while (gap--)//让链表长的指针走到和短链表初始结点相同的位置。
{
Listlong =Listlong->next;
}
while (Listlong !=Listshort)
{
Listlong =Listlong->next;
Listshort =Llistshort->next;
}
return Listlong;
}
- 给定一个链表,判断链表中是否有环。
运用快慢指针的思想,如果有环,快慢指针一定会相遇。
#include <stdio.h>
bool hasCycle(ListNode *head)
{
ListNode *fast =head;
ListNode *slow =head;
while (fast && fast->next)
{
fast =fast->next->next;
slow =slow->next;
if (fast == slow)//不是结点的值相等,而是快慢指针到达同一个结点。
{
return true;
}
}
return false;
}
- 给定一个链表,判断链表中是否有环,若有环,则返回入环的第一个结点。
- 可以自己画一个带环链表的图,快慢指针的思想走一遍,便于理解。
ListNode *detectCycle(struct ListNode *head) {
struct ListNode* fast = head;
struct ListNode* slow = head;
struct ListNode* s1 = head;
int meet = 0;
while(fast && fast->next){
fast = fast->next->next;
slow = slow->next;
if(fast == slow){
meet = 1;
break;
}
}
if(meet == 1){
while(s1 != fast){
s1 = s1->next;
fast = fast->next;
}
return s1;
}
return NULL;
}