逆序打印单链表
逆序打印单链表这里用的是递归的打印方法。
void LinkListReverse(LinkNode* head)
{
if(head == NULL)
{
return;//空链表
}
if(head->next == NULL)
{
return;
}
LinkListReverse(head->next);
printf("[%c|%p]\n",head->data,head);
}
不允许遍历链表,在pos位置之前插入
这里进行对指针的改变指向,再进行覆盖内容即可。
void LinkListInsert2(LinkNode** phead, LinkNode* pos, Linktype value)//在无头单链表的一个节点前插入一个节点(不能遍历链表)
{
if(phead == NULL)
{
return;
}
if(*phead == NULL)
{
return;
}
LinkNode* cur = pos->Next;
pos->Next = Creat(value);
pos->Next->Next = cur;
Linktype tmp = pos->data;
pos->data = value;
pos->Next->data = tmp;
}
实现约瑟夫环
LinkNode* LinkListJosephCircle(LinkNode** phead,size_t num)//实现约瑟夫环
{
if(phead == NULL)
{
return NULL;
}
if(*phead == NULL)
{
return NULL;
}
if((*phead)->Next == NULL)
{
return NULL;
}
LinkNode* cur = *phead;
while(cur->Next != NULL)
{
cur = cur->Next;
}
cur->Next = *phead;
LinkNode* tmp = NULL;
cur = *phead;
while(1)
{
size_t i = 1;
if(cur->Next == cur)
{
break;
}
for(i = 1; i < num; i++)
{
tmp = cur;
cur = cur->Next;
}
tmp->Next = cur->Next;
free(cur);
cur = tmp->Next;
}
return cur;
}
单链表逆置
这里运用两种方法进行逆置,一种是删除后面插入至前面,另一种是对指针的指向进行移动。
void LinkListReverse(LinkNode** phead)//逆置反转单链表
{
if(phead == NULL)
{
return;
}
if(*phead == NULL)
{
return;
}
LinkNode* to_delete = NULL;
LinkNode* cur = *phead;
while(cur->Next != NULL)
{
to_delete = cur->Next;
cur->Next = to_delete->Next;
LinkListPushFront(phead,to_delete->data);
free(to_delete);
}
}
void LinkListReverse2(LinkNode** phead)//逆置反转单链表
{
if(phead == NULL)
{
return;
}
if(*phead == NULL)
{
return;
}
LinkNode* cur = (*phead)->Next;
LinkNode* pre = *phead;
LinkNode* next = NULL;
while(cur != NULL)
{
next = cur->Next;
pre->Next = next;
cur->Next = *phead;
*phead = cur;
cur = next;
}
}
单链表的冒泡排序
void Swap(Linktype* a, Linktype* b)
{
Linktype tmp = *a;
*a = *b;
*b = tmp;
}
void LinkListBubbleSort(LinkNode** phead)//冒泡排序链表
{
if(phead == NULL)
{
return;
}
if(*phead == NULL)
{
return;
}
LinkNode* count = *phead;
LinkNode* tail = NULL;
LinkNode* cur = *phead;
for(; count->Next != NULL; count = count->Next)
{
for(cur = *phead; cur->Next != tail; cur = cur->Next)
{
if(cur->data > cur->Next->data)
{
Swap(&cur->data,&cur->Next->data);
}
}
tail = cur;
}
}
找点链表倒数第K个节点
LinkNode* LinkListGetPos(LinkNode* head,size_t num)//查找单链表的倒数第num个节点 ,要求只能遍历一次链表
{
if(head == NULL)
{
return NULL;
}
LinkNode* cur = head;
LinkNode* tmp = head;
size_t i = 1;
while(cur->Next != NULL)
{
cur = cur->Next;
if(i >= num)
{
tmp = tmp->Next;
}
i++;
}
return tmp;
}
删除链表倒数第K个节点
这里我们可以直接调用前面的找到第K个,然后直接Erase
void LinkListEraseGetP(LinkNode** phead, size_t num)//删除链表的倒数第k个节点
{
if(phead == NULL)
{
return;
}
if(*phead == NULL)
{
return;
}
LinkNode* ret = LinkListGetPos(*phead,num);
LinkListErase(phead,ret);//此函数的实现在之前的单链表基本操作中有实现
}
判断单链表是否带环
利用两个指针,一快一慢,如果快的能够追上慢的,那么带环,返回其相遇的位置。
LinkNode* HasCycle(LinkNode* head)//判断链表是否带环,如果带环返回相遇点位置
{
if(head == NULL)
{
return NULL;
}
LinkNode* fast = head;
LinkNode* slow = head;
while(fast != NULL && fast->Next != NULL)
{
fast = fast->Next->Next;
slow = slow->Next;
if(fast == slow)
{
return slow;
}
}
return NULL;
}
如果链表带环,求出环的长度
size_t CycleLen(LinkNode* head)//求一个有环链表的环长度
{
if(head == NULL)
{
return 0;
}
if(head->Next == NULL)
{
return 0;
}
LinkNode* meet_node = HasCycle(head);
if(meet_node == NULL)
{
return 0;
}
LinkNode* cur = meet_node->Next;
size_t count = 1;
while(cur != meet_node)
{
cur = cur->Next;
count++;
}
return count;
}
如果链表带环,求出该链表环的入口点
LinkNode* GetCycleEntry(LinkNode* head)//求一个有环链表环的入口点
{
if(head == NULL)
{
return NULL;
}
if(head->Next == NULL)
{
return NULL;
}
LinkNode* meet_node = HasCycle(head);
if(meet_node == NULL)
{
return NULL;
}
LinkNode* cur = head;
while(cur != meet_node)
{
cur = cur->Next;
meet_node = meet_node->Next;
}
return cur;
}
判断两个链表是否相交
LinkNode* HasCross(LinkNode* head1, LinkNode* head2)//判断两个链表是否相交
{
if(head1 == NULL)
{
return NULL;
}
if(head2 == NULL)
{
return NULL;
}
LinkNode* cur1 = head1;
LinkNode* cur2 = head2;
while(cur1 != NULL && cur2 != NULL)
{
if(cur1 == cur2)
{
return cur1;
}
cur1 = cur1->Next;
cur2 = cur2->Next;
}
return NULL;
}
欢迎大家共同讨论,如有错误及时联系作者指出,并改正。谢谢大家!