struct ListNode
{
int date;
struct ListNode* next;
};
//反转链表思路1:
struct ListNode* reverseList(struct ListNode* head)
{
if (head == NULL);//指针为空
{
return NULL;
}
ListNode* n1, *n2, *n3;
n1 = NULL;
n2 = head;
n3 = head->next;
while (n2)
{
//反转
n2->next = n1;
//迭代
n1 = n2;
n2 = n3;
if(n3)//判断n3不为NULL
{
n3 = n3->next;
}
}
//n2为NULL时结束,此时n1为反转后的head
return n1;//返回
}
//反转链表思路2:头插
struct ListNode* reverseList(struct ListNode* head)
{
struct ListNode* cur = head;
struct ListNode* newhead = NULL;
while (cur)
{
struct ListNode* next = cur->next;//记录当前结点指向下一结点的指针
//头插
cur->next = newhead;
newhead = cur;
//迭代
cur = next;
}
return newhead;
}
//链表的中间结点:
struct ListNode* middleNode(struct ListNode* head)
{
struct ListNode* slow,*fast;
slow = fast = head;
while (fast && fast->next)//奇数个fast->next不为NULL,偶数个fast不为NULL
{
slow = slow->next;//慢指针走一步
fast = fast->next->next;//快指针走两步,慢指针走到中间结点,快指针走到尾
}
return slow;
}
//找链表的倒数第K个结点
struct ListNode* FindKthToTail(struct ListNode* head,size_t k)
{
struct ListNode* slow, * fast;
slow = fast = head;
//fast先走k个结点
while (k--)
{
if (!fast)//如果fast为NULL,说明k值大于所有元素结点个数(大于链表长度)
{
return NULL;
}
fast = fast->next;
}
//二者同步往后走,fast为NULL时,slow为第k个结点
while (fast)
{
slow = slow->next;
fast = fast->next;
}
return slow;
}
//合并两个升序链表
struct ListNode* FindKthToTail(struct ListNode* l1, struct ListNode* l2)
{
if (!l1)//如果l1为空
{
return l2;//返回l2
}
if (!l2)//如果l2为空
{
return l1;//返回l1
}
struct ListNode* head = NULL, *tail = NULL;
while (l1 && l2)//二者不为NULL
{
if (l1->date < l2->date)
{
if (head == NULL)//头部为空
{
head = tail = l1;
}
else
{
tail->next = l1;//当前tail->next指向l1的结点
tail = l1;//tail的地址往后移,记录了当前l1结点的位置,方便尾插
}
l1 = l1->next;//l1往后移
}
else
{
if (head == NULL)//头部为空
{
head = tail = l2;
}
else
{
tail->next = l2;//当前tail->next指向l2的结点
tail = l2;//tail的地址往后移,记录了当前l2结点的位置,方便尾插
}
l2 = l2->next;//l2往后移
}
}
if (l1)
tail->next = l1;
if (l2)
tail->next = l2;
return head;
}
struct ListNode* FindKthToTail(struct ListNode* l1, struct ListNode* l2)
{
if (!l1)//如果l1为空
{
return l2;//返回l2
}
if (!l2)//如果l2为空
{
return l1;//返回l1
}
struct ListNode* head = NULL, * tail = NULL;
//先确定小的结点做头部
if (l1->date < l2->date)
{
head = tail = l1;
l1 = l1->next;
}
else
{
head = tail = l2;
l2 = l2->next;//l2往后移
}
while (l1 && l2)//二者不为NULL
{
if (l1->date < l2->date)
{
tail->next = l1;//当前tail->next指向l1的结点
tail = l1;//tail的地址往后移,记录了当前l1结点的位置,方便尾插
l1 = l1->next;//l1往后移
}
else
{
tail->next = l2;//当前tail->next指向l2的结点
tail = l2;//tail的地址往后移,记录了当前l2结点的位置,方便尾插
l2 = l2->next;//l2往后移
}
}
if (l1)
tail->next = l1;
if (l2)
tail->next = l2;
return head;
}
//带头链表------------------------
//多一个哨兵位的头结点,这个结点不存储有效数据
struct ListNode* FindKthToTail(struct ListNode* l1, struct ListNode* l2)
{
if (!l1)//如果l1为空
{
return l2;//返回l2
}
if (!l2)//如果l2为空
{
return l1;//返回l1
}
struct ListNode* head = NULL, * tail = NULL;
//开辟一个哨兵位的头结点
head = tail = (struct ListNode*)malloc(sizeof(struct ListNode));
while (l1 && l2)//二者不为NULL
{
if (l1->date < l2->date)
{
tail->next = l1;//当前tail->next指向l1的结点
tail = l1;//tail的地址往后移,记录了当前l1结点的位置,方便尾插
l1 = l1->next;//l1往后移
}
else
{
tail->next = l2;//当前tail->next指向l2的结点
tail = l2;//tail的地址往后移,记录了当前l2结点的位置,方便尾插
l2 = l2->next;//l2往后移
}
}
if (l1)
tail->next = l1;
if (l2)
tail->next = l2;
struct ListNode* list = head->next;//将链表的实际头结点用list接收
free(head);//释放head哨兵位头结点空间
return list;//返回头结点
}
//链表的分割
//不能改变链表的已有的相对顺序
struct ListNode* partition(struct ListNode* pHead, int x)
{
struct ListNode* lessTail, * lessHead, * greaterTail, * greaterHead;
//创建一个哨兵位的头结点,方便尾插
//小于X的链表
lessTail = lessHead = (struct ListNode*)malloc(sizeof(struct ListNode));
lessTail->next = NULL;
//大于等于X的链表
greaterHead = greaterTail = (struct ListNode*)malloc(sizeof(struct ListNode));
greaterTail->next = NULL;
struct ListNode* cur = pHead;
while (cur)
{
if (cur->date < x)
{
lessTail->next = cur;//将小于X的结点链接在less的链表尾部
lessTail = cur;//链表尾部往后移
}
else
{
greaterTail->next = cur; //将大于等于X的结点链接在greater的链表尾部
greaterTail = cur; //链表尾部往后移
}
cur = cur->next;//cur指向下一个待比较的结点
}
//所有结点比较结束后,将小于X的链表尾部链接在大于等于X链表的头部,greaterHead->next
lessTail->next = greaterHead->next;
//将大于等于X的链表尾部指向空,防止死循环-------------
greaterTail->next = NULL;
struct ListNode* newHead = lessHead->next;
free(lessHead);
free(lessTail);
free(greaterHead);
free(greaterTail);
return newHead;
}
//判断链表是否为回文结构
bool chPalindrome(struct ListNode* A)
{
struct ListNode* mid = middleNode(A);
struct ListNode* rHead = reverseList(mid);
struct ListNode* curA = A;
struct ListNode* curR = rHead;
while (curA && curR)
{
if (curA->date != curR->date)
{
return false;
}
else
{
curA = curA->next;
curR = curR->next;
}
}
return true;
}
//链表相交
struct ListNode* getIntersectionNode(struct ListNode* headA, struct ListNode* headB)
{
struct ListNode* tailA = headA;
struct ListNode* tailB = headB;
int lenA = 1;
int lenB = 1;
//链表尾部相同,则链表相交,否则不相交
while (tailA)
{
lenA++;//计算链表长度
tailA = tailA->next;//遍历链表
}
while (tailB)
{
lenB++;//计算链表长度
tailB = tailB->next;//遍历链表
}
if (tailA != tailB)
{
return NULL;
}
//计算两个链表长度差值
int gap = abs(lenA - lenB);//abs绝对值
//假设A长B短
struct ListNode* shortList = headA;
struct ListNode* longList = headB;
//判断假设是否正确
if (lenA > lenB)
{
shortList = headB;
longList = headA;
}
//长链表先走gap步
while (gap--)
{
longList = longList->next;
}
//两个链表同时走
while (longList != shortList)
{
longList = longList->next;
shortList = shortList->next;
}
//找到交点,返回
return shortList;
}
//链表是否有环
bool hasCycle(struct ListNode* head)
{
struct ListNode* slow = head;
struct ListNode* fast = head;
while (fast&&fast->next)
{
slow = slow->next;//慢指针走一步
fast = fast->next->next;//快指针走两步
if (fast == slow)
{
return true;
}
}
return false;
}
//链表的环的切入点
struct ListNode* EntryNodeOfLoop(struct ListNode* pHead)
{
struct ListNode* slow = pHead;
struct ListNode* fast = pHead;
while (fast && fast->next)
{
slow = slow->next;//慢指针走一步
fast = fast->next->next;//快指针走两步
if (fast == slow)
{
//相遇
struct ListNode* meet = slow;
//pHead从起点往后走,meet从相遇点往后走
//环外长度L = 环长度C - 切点到相遇点的长度X
//证明:
//slow 步长 = L+X
//fast 步长 = L+ N*C +X(N为fast走的患难圈数
//fast的步长是slow步长的2倍
//2(L+X) = L+ N*C +X
//L = N*C -X
//L = (N-1)*C+ C -X
//(N-1)*C 为meet点
//L = C-X
while (meet != pHead)
{
meet = meet->next;
pHead = pHead->next;
}
//二者相遇时
return pHead;
}
}
//不相遇
return NULL;
}